8. led子系统

本章使用C库系统调用操作方式控制开发板的LED灯,展示如何在应用层通过系统提供的设备文件控制相关硬件。

8.1. LED子系统

在Linux系统中,绝大多数硬件设备都有非常成熟的驱动框架, 驱动工程师使用这些框架添加与板子相关的硬件支持,建立硬件与Linux内核的联系, 内核再通过统一文件系统接口呈现给用户,用户通过对应的设备文件控制硬件。

对于LED设备,Linux提供了LED子系统驱动框架, 在Linux内核源码中的“Documentation/leds/leds-class.txt”有相关的描述, 它实现了一个leds类,用户层通过sysfs文件系统对LED进行控制。

8.1.1. LED设备目录

使用了LED子系统驱动的设备,会被展现在/sys/class/leds目录下,可在主机和开发板使用如下命令查看, 命令的输出可能会因为硬件环境不同而不一样:

1
2
3
4
5
#在开发板的终端上执行如下命令:
ls /sys/class/leds/

#在开发板上有heartbeat目录,可在开发板上执行如下命令查看
ls /sys/class/leds/heartbeat

如下所示

1
2
3
4
5
root@npi:/# ls /sys/class/leds/
blue  green  heartbeat  red
root@npi:/# ls /sys/class/leds/heartbeat
brightness  device  invert  max_brightness  power  subsystem  trigger  uevent
root@npi:/#

上图可看到,开发板/sys/class/leds下包含了以LED设备名字命名的目录, 如“blue”、“heartbeat”等LED灯,这些目录对应的具体LED灯如下表所示。

表 /sys/class/leds下目录对应的设备

/sys/class/leds下的目录

对应的LED灯设备

heartbeat

开发板的心跳灯

red

Pro开发板RGB灯的红色(STM32MP157开发板为用户灯)

green

Pro开发板RGB灯的绿色(STM32MP157开发板为用户灯)

blue

Pro开发板RGB灯的蓝色(STM32MP157开发板为用户灯)

8.1.2. LED设备属性

上图中,在具体的LED目录下又包含brightness、max_brightness、trigger等文件,这些文件包含了LED设备的属性和控制接口。

  • max_brightness文件:表示LED灯的最大亮度值。

  • brightness文件:表示当前LED灯的亮度值,它的可取 值范围为[0~max_brightness],一些LED设备不支持多级亮度,直接以非0值来 表示LED为点亮状态,0值表示灭状态。

  • trigger文件:则指示了LED灯的触发方式,查看该文件的内容时,该文件会 列出它的所有可用触方式,而当前使用的触发方式会以“[]”符号括起。常见的触 发方式如下表所示。

表 trigger常见的触发方式

触发方式

说明

none

无触发方式

disk-activity

硬盘活动

nand-disk

nand flash活动

mtd

mtd设备活动

timer

定时器

heartbeat

系统心跳

8.2. 控制LED实验

本小节通过系统调用的文件操作方式控制RGB中的红灯(stm32mp157为普通用户灯),源码如下所示。

代码仓库/Source/led/led.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define RLED_DEV_PATH "/sys/class/leds/red/brightness"

int main(int argc,int *argv[])
{
   int r_fd;

   r_fd = open(RLED_DEV_PATH,O_WRONLY);
   if(r_fd < 0)
   {
      perror(RLED_DEV_PATH);
      exit(1);
   }

   while(1)
   {
      write(r_fd,"255",3);
      sleep(1);
      write(r_fd,"0",3);
      sleep(1);
   }

   close(r_fd);
}

代码相对简单, 最后使用直接使用arm-linux-gnueabihf-gcc进行编译即可。

1
arm-linux-gnueabihf-gcc -o  led led.c

8.3. LED设备树插件修改

LED子系统设备树的修改方法在 《设备树插件修改方法指导》 已经有描述,此处不再赘述。