LED子系统
一、设备树编写
节点属性添加参考内核源码Documentation/devicetree/bindings/leds/leds-gpio.yaml
文件 设备树插件如下所示:
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
leds {
compatible = "gpio-leds";
led-0 {
gpios = <&mcu_pio 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "disk-activity";
function = LED_FUNCTION_DISK;
};
led-1 {
gpios = <&mcu_pio 1 GPIO_ACTIVE_HIGH>;
/* Keep LED on if BIOS detected hardware fault */
default-state = "keep";
function = LED_FUNCTION_FAULT;
};
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
其中最重要的是 linux,default-trigger 属性,可以配置如下:
二、LED子系统
2.1、用户态
控制LED灯的方法如下:
在用户模式下,可以通过修改设备目录里的文件来控制LED灯。每个LED对应的目录路径通常是/sys/class/leds/xxx/,里面主要有以下文件:
① 调整亮度
- brightness:设置LED亮度 输入0-255之间的数字,0=完全熄灭,255=最亮。
- max_brightness:查看最大亮度值 一般显示255,表示这个LED能调到最亮。
② 设置工作模式(触发模式)
修改trigger
文件选择LED的运作方式:
none
:LED一直熄灭default-on
:LED一直亮着timer
:按设定时间闪烁(需配合调整闪烁间隔)heartbeat
:模拟心跳节奏闪烁(常用于系统状态提示)cpu0
:根据CPU使用率变化闪烁(数值越高闪烁越快)mmc0/nand-disk
:存储设备工作时闪烁(如U盘读写时)- 其他模式如
oneshot
/backlight
等:用于特定功能
③ 定时闪烁设置(仅限**timer**
模式)
当选择timer
模式后,通过以下文件调整闪烁节奏:
- delay_on:设置LED亮起的时长(单位:毫秒)
- delay_off:设置LED熄灭的时长(单位:毫秒)
示例: 若要让LED每秒闪烁一次(1Hz),可设置:
delay_on = 500
(亮0.5秒)delay_off = 500
(灭0.5秒)
::: 所有设置立即生效,无需重启。通过组合不同模式和参数,可以实现多种灯光效果。 :::
2.2、内核驱动
LED驱动程序主要存放在Linux内核的drivers/leds目录中,核心功能由三个文件实现:
2.2.1、核心文件作用
- led-core.c 处理LED的基本操作,比如设置亮度、闪烁等,并提供这些功能给其他文件使用。 关键功能包括:
- 初始化LED系统(led_init_core)
- 控制LED闪烁(设置/停止/单次闪烁)
- 亮度调节(支持休眠/非休眠场景)
- 维护所有LED的列表和锁机制
- 支持用户通过/sys文件系统开关LED
- led-class.c 管理所有LED设备的注册和管理:
- 注册LED设备(支持设备树配置)
- 注销设备
- 处理设备休眠/唤醒时的LED状态
- 在/sys创建控制接口(如亮度调节、最大亮度显示)
- led-triggers.c 管理所有LED的触发机制:
- 注册/注销触发器
- 支持多种触发方式(如定时、CPU使用率等)
2.2.2、可选触发方式(触发器)
通过配置可启用以下触发功能,每个触发器对应一个驱动文件:
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o //定时触发
obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o //单次触发
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o //硬盘触发
obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o //心跳触发
obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o //背光设置
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o //GPIO触发
obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o //CPU触发
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o //默认开
obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
2
3
4
5
6
7
8
9
10
2.2.3、设备驱动与触发器实现
1. LED设备驱动(如GPIO LED)
- 硬件连接:LED接在GPIO引脚上时,无需自己编写驱动。
- 配置方法:只需在设备树(Device Tree)中添加LED的GPIO引脚等信息,内核会自动加载已有驱动(如leds-gpio.c)。
- 注册流程:驱动通过
probe()
函数读取设备树配置,设置LED属性后调用注册函数(如devm_of_led_classdev_register
)完成设备注册。
2. 触发器实现(以定时触发为例)
- 注册过程:触发器模块(如ledtrig-timer.c)通过
led_trigger_register()
注册自身,需提供激活/停用函数。 - 用户控制:生成控制文件(如
delay_on
/delay_off
),允许用户设置闪烁时长。 - 注销:卸载时通过
led_trigger_unregister()
清理资源。
三、驱动代码
3.1、平台设备驱动的注册
- 第1-4行:
of_match_table
表用于驱动和设备匹配,这里将匹配主设备树leds
节点。 - 第5行: 宏
MODULE_DEVICE_TABLE(gtype,name)
,在这里该宏会会生成一个符号表,把该设备加入到设备队列中,该方式支持使用平台设备匹配驱动。 - 第7-14行: 定义平台驱动结构体,填充
of_match_table
段,设备树的方式匹配驱动。 - 第16行: 使用
module_platform_driver
宏注册平台驱动,该led驱动是一个platform_driver
的对象。
关于module_platform_driver()
宏,在内核源码/include/linux/platform_device.h
中有定义:
继续展开module_driver()
宏:
可以看到,最终该宏是执行module_init()
和module_exit()
进行驱动模块的注册和注销,其中””表示前后两部分粘和起来。
3.2、平台设备驱动的probe
create_gpio_led
-- devm_of_led_classdev_register
drivers/leds/led-class.c
led_update_brightness
led_init_core
led-core.c
四、数据结构
五、使用方法
重启加载设备树后,驱动已经编译进内核,会在/sys/class/leds
目录下多个led_test
目录。 进入led_test
目录
led-class.c
brightness max_brightness subsystem uevent
device power trigger
2
可以通过echo 0 > brightness
来关闭LED
灯,通过echo timer > trigger
改变触发模式。同时,cat trigger
可以显示支持的触发模式,以及当前的触发模式:
none nand-disk mmc0 cpu0 [heartbeat] timer default-on oneshot backlight gpio