前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux Led 子系统

Linux Led 子系统

作者头像
Jasonangel
发布2023-08-22 13:51:36
4420
发布2023-08-22 13:51:36
举报
文章被收录于专栏:嵌入式Linux系统开发

1、前言

什么叫做驱动框架?

内核中驱动维护者针对每种驱动设计一套【成熟的、标准的、典型的】驱动实现,并把不同厂家的同类硬件驱动中相同的部分抽出来实现好,再把不同部分留出接口给具体的驱动工程师来实现,这就叫驱动框架。

2、概述

led 子系统驱动框架:

所有 led 共性:

  1. 有和用户通信的设备节点
  2. 亮和灭

不同点:

  1. 有的 led 可能是接在 gpio 管脚上,不同的 led 有不同的 gpio 来控制
  2. 有的 led 可能由其他的芯片来控制(节约 cpu 的 pin,或者为了控制 led 的电流等)
  3. 可以设置亮度
  4. 可以闪烁

所以 Linux led 子系统把所有 led 的共性给实现了,把不同的地方留给驱动工程师去做。

led 子系统核心文件:

代码语言:javascript
复制
driver/leds/led-class.c
driver/leds/led-core.c
driver/leds/led-triggers.c
include/linux/leds.h

其他文件(按需)

代码语言:javascript
复制
driver/leds/led-gpio.c
driver/leds/wm8350.c
driver/leds/led-xxx.c
driver/leds/trigger/ledtrig-backlight.c
driver/leds/trigger/ledtrig-camera.c
driver/leds/trigger/ledtrig-cpu.c
driver/leds/trigger/ledtrig-default-on.c
driver/leds/trigger/ledtrig-gpio.c
driver/leds/trigger/ledtrig-heartbeat.c
driver/leds/trigger/ledtrig-ide-disk.c
driver/leds/trigger/ledtrig-multi-control.c
driver/leds/trigger/ledtrig-oneshot.c
driver/leds/trigger/ledtrig-timer.c
driver/leds/trigger/ledtrig-transient.c

led 子系统相关描述可在内核源码 Documentation/leds/leds-class.txt 了解。

led 子系统是一个简单的 Linux 子系统 ,在目录 /sys/class/leds 下展示该子系统设备,每个设备都有自己的属性:

代码语言:javascript
复制
brightness:设置 LED 亮度,范围 0 ~ max_brightness
max_brightness:最大亮度(255 或其他数字)
trigger:触发方式,如 heartbeat、mmc0、backlight、gpio

delay_off、delay_on:trigger为timer时,LED亮灭的时间,单位ms

kernel/include/linux/leds.h

代码语言:javascript
复制
enum led_brightness {
 LED_OFF  = 0,    //全暗
 LED_HALF = 127,  //一半亮度
 LED_FULL = 255,  //最大亮度
};

3、代码框架分析

led-class.c (led 子系统框架的入口)

代码语言:javascript
复制
维护 LED 子系统的所有 LED 设备,为 LED 设备提供注册操作函数: 

led_classdev_register()
devm_led_classdev_register()

注销操作函数:
led_classdev_unregister()
devm_led_classdev_unregister();

电源管理的休眠和恢复操作函数: 
led_classdev_suspend()
led_classdev_resume();

用户态操作接口:brightness 、max_brightness

led-core.c

代码语言:javascript
复制
抽象出 LED 操作逻辑,封装成函数导出,供其它文件使用:

led_init_core(): 核心初始化;
led_blink_set(): 设置led闪烁时间:
led_blink_set_oneshot() : 闪烁一次
led_stop_software_blink() : led停止闪烁
led_set_brightness() : 设置led的亮度
led_update_brightness : 更新亮度
led_sysfs_disable : 用户态关闭
led_sysfs enable : 用户态打开
leds_list : leds链表;
leds_list_lock : leds链表锁

led-triggers.c

代码语言:javascript
复制
维护 LED 子系统的所有触发器,为触发器提供注册操作函数: 

led_trigger_register()
devm_led_trigger_register()
led_trigger_register_simple()

注销操作函数: 

led_trigger_unregister()
led_trigger_unregister_simple()

以及其它触发器相关的操作函数

ledtrig-timer.c、ledtrig-xxx.c

代码语言:javascript
复制
以 ledtrig-timer.c 为例

入口函数调用 led_trigger_register() 注册触发器,
注册时候传入 led_trigger 结构体,里面有 activate 和 deactivate 成员函数指针,
作用是生成 delay_on 、 delay_off 文件

同时还提供 delay_on 和 delay_off 的用户态操作接口
卸载时,使用 led_trigger_unregister() 注销触发器

leds-gpio.c、leds-xxx.c :

代码语言:javascript
复制
以 leds-gpio.c 为例

在通过设备树或者其它途径匹配到设备信息后,将调用 probe() 函数,
然后再根据设备信息设置 led_classdev,
最后调用 devm_led_classdev_register() 注册 LED 设备。

led_classdev 结构体代表 led 实例:

代码语言:javascript
复制
struct led_classdev {
 const char  *name;//名字
 enum led_brightness  brightness;//亮度
 enum led_brightness  max_brightness;//最大亮度
 int    flags;

 /* Lower 16 bits reflect status */
#define LED_SUSPENDED  (1 << 0)
 /* Upper 16 bits reflect control information */
#define LED_CORE_SUSPENDRESUME (1 << 16)
#define LED_BLINK_ONESHOT (1 << 17)
#define LED_BLINK_ONESHOT_STOP (1 << 18)
#define LED_BLINK_INVERT (1 << 19)
#define LED_SYSFS_DISABLE (1 << 20)
#define SET_BRIGHTNESS_ASYNC (1 << 21)
#define SET_BRIGHTNESS_SYNC (1 << 22)
#define LED_DEV_CAP_FLASH (1 << 23)

//设置亮度API
 void  (*brightness_set)(struct led_classdev *led_cdev,enum led_brightness brightness);
 int  (*brightness_set_sync)(struct led_classdev *led_cdev,enum led_brightness brightness);
          
//获取亮度API
 enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);

//闪烁时点亮和熄灭的时间设置
 int  (*blink_set)(struct led_classdev *led_cdev,unsigned long *delay_on,unsigned long *delay_off);

 struct device  *dev;
 const struct attribute_group **groups;

//leds-list的node
 struct list_head  node;
//默认trigger的名字
 const char  *default_trigger;
//闪烁的开关时间
 unsigned long   blink_delay_on, blink_delay_off;
//闪烁的定时器链表
 struct timer_list  blink_timer;
//闪烁的亮度
 int    blink_brightness;
 void   (*flash_resume)(struct led_classdev *led_cdev);

 struct work_struct set_brightness_work;
 int   delayed_set_value;

#ifdef CONFIG_LEDS_TRIGGERS
//trigger的锁
 struct rw_semaphore  trigger_lock;
//led的trigger
 struct led_trigger *trigger;
//trigger的链表
 struct list_head  trig_list;
//trigger的数据
 void   *trigger_data;
 bool   activated;
#endif
 struct mutex  led_access;
};

led_trigger 结构:

代码语言:javascript
复制
struct led_trigger {
 /* Trigger Properties */
 const char  *name;
 void  (*activate)(struct led_classdev *led_cdev);
 void  (*deactivate)(struct led_classdev *led_cdev);

 /* LEDs under control by this trigger (for simple triggers) */
 rwlock_t   leddev_list_lock;
 struct list_head  led_cdevs;

 /* Link to next registered trigger */
 struct list_head  next_trig;
};

trigger 是控制 LED 类设备的算法,这个算法决定着 LED 什么时候亮什么时候暗。

1、点亮 LED

代码语言:javascript
复制
echo 255 > /sys/class/leds/led1/brightness
cat /sys/class/leds/led1/brightness
cat /sys/class/leds/led1/max_brightness

2、闪烁

代码语言:javascript
复制
cat /sys/class/leds/led1/trigger

会看到 trigger_list
[none] mmc0 mmc1 mmc2 timer
其中的 timer 这个 trigger 是 ledtrig-timer.c 中模块初始化的时候注册进去的

echo timer > /sys/class/leds/led1/trigger
这一句会调用
led_trigger_store()->
   led_trigger_set()->
     trigger->activate(led_cdev);
从而调用 ledtrig-timer.c 文件里 的timer_trig_activate(),
在 /sys/class/leds/led1/ 下创建 delay_on、delay_off 两个文件

echo 100 > /sys/class/leds/led1/delay_on
echo 200 > /sys/class/leds/led1/delay_off
这样会闪烁,亮 100ms 灭 200ms

3、关闭 LED

代码语言:javascript
复制
echo 0 > /sys/class/leds/led1/delay_on
或
echo 0 > /sys/class/leds/led1/brightness

对于 led 子系统的学习,可以直接参考 /drivers/leds/leds-gpio.c

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式Linux系统开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、前言
  • 2、概述
  • 3、代码框架分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档