linux led子系统(一)
就像學(xué)編程第一個范例helloworld一樣,學(xué)嵌入式,單片機(jī)、fpga之類的第一個范例就是點(diǎn)亮一盞燈。對于龐大的linux系統(tǒng),當(dāng)然可以編寫一個字符設(shè)備驅(qū)動來實(shí)現(xiàn)我們需要的led燈,也可以直接利用gpio口,應(yīng)用程序來拉高拉低管腳控制。不過,既然linux系統(tǒng)自己本來就帶有l(wèi)ed子系統(tǒng),那么就可以好好利用之。好處不用多說了,主要對于應(yīng)用層來說,不同平臺都用linux的led子系統(tǒng),那么應(yīng)用程序不用做任何的改變,就可以在新的平臺上運(yùn)行,可移植性好。
linux的led子系統(tǒng)的源碼路徑:
include/Linux/leds.h //頭文件 drivers/leds //led子系統(tǒng)相關(guān)源碼以及API 首先看一下led子系統(tǒng)中的主要文件: # LED Core obj-$(CONFIG_NEW_LEDS) +=led-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_TRIGGERS) +=led-triggers.o # LED PlatformDrivers obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) +=ledtrig-timer.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 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o 主要由leds.h、led-core.c、led-class.c、led-triggers.c,其中l(wèi)ed-triggers又分為了timer、ide-disk、heartbeat、backlight、gpio、default-on等算法。
例子程序是leds-gpio,接下去會主要分析這個驅(qū)動實(shí)現(xiàn)。
首先簡單看一下主要的文件
leds.h
Led的亮度,分為三等級,關(guān)、中間、最亮。
enum led_brightness {
LED_OFF = 0, //全暗
LED_HALF = 127, //一半亮度
LED_FULL = 255, //最大亮度
};
struct led_classdev {
const char *name; //led名字
int brightness; //當(dāng)前亮度
int max_brightness;//參考值,最大亮度
int flags; //標(biāo)志,目前只支持 LED_SUSPENDED和LED_CORE_SUSPENDRESUME
/* Lower 16 bits reflect status */
#define LED_SUSPENDED (1 << 0)
/* Upper 16 bits reflect control information */
#define LED_CORE_SUSPENDRESUME (1 << 16)
/* Set LED brightness level */
/* Must not sleep, use a workqueue if needed */
//核心回調(diào)函數(shù),當(dāng)設(shè)置/sys/class/leds/下的led接口里的brightness(亮度)屬性文件時,會回調(diào)該函數(shù)
void (*brightness_set)(struct led_classdev *led_cdev,
enum led_brightness brightness); //亮度設(shè)置函數(shù)指針
/* Get LED brightness level */
//核心回調(diào)函數(shù),當(dāng)獲得led當(dāng)前亮度值時會調(diào)用
enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);//獲取亮度函數(shù)指針
/*
* Activate hardware accelerated blink, delays are in milliseconds
* and if both are zero then a sensible default should be chosen.
* The call should adjust the timings in that case and if it can't
* match the values specified exactly.
* Deactivate blinking again when the brightness is set to a fixed
* value via the brightness_set() callback.
*/
/* 激活硬件加速的閃爍 */
int (*blink_set)(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off);//閃爍時點(diǎn)亮和熄滅的時間設(shè)置
//嵌入的標(biāo)準(zhǔn)設(shè)備模型
struct device *dev;
/* 所有已經(jīng)注冊的led_class dev使用這個節(jié)點(diǎn)串聯(lián)起來 */
struct list_head node; /* LED Device list */ //leds-list的node
/* 默認(rèn)觸發(fā)器 */
const char *default_trigger; /* Trigger to use */ //默認(rèn)trigger的名字
unsigned long blink_delay_on, blink_delay_off; //閃爍的開關(guān)時間
struct timer_list blink_timer; //閃爍的定時器鏈表
int blink_brightness; //閃爍的亮度
//如果配置內(nèi)核時使能了觸發(fā)器功能,才會編譯下面一段
#ifdef CONFIG_LEDS_TRIGGERS
/* Protects the trigger data below */
struct rw_semaphore trigger_lock; /* 這個讀寫鎖保護(hù)下面的觸發(fā)器數(shù)據(jù) */
struct led_trigger *trigger; //觸發(fā)器指針
struct list_head trig_list; //觸發(fā)器使用的鏈表節(jié)點(diǎn),用來連接同一觸發(fā)器上的所有l(wèi)ed_classdev
void *trigger_data; //觸發(fā)器使用的私有數(shù)據(jù)
#endif
};
struct led_trigger {
const char *name; //trigger名字
void (*activate)(struct led_classdev *led_cdev);//激活led,led_classdev和觸發(fā)器建立連接時會調(diào)用這個方法。
void (*deactivate)(struct led_classdev *led_cdev);//取消激活。led_classdev和觸發(fā)器取消連接時會調(diào)用這個方法。
/* LEDs under control by this trigger (for simple triggers) */
/* 本觸發(fā)器控制之下的led鏈表 */
rwlock_t leddev_list_lock; //保護(hù)鏈表的鎖
struct list_head led_cdevs; //鏈表頭
/* Link to next registered trigger */
struct list_head next_trig; /* 連接下一個已注冊觸發(fā)器的鏈表節(jié)點(diǎn) ,所有已注冊的觸發(fā)器都會被加入一個全局鏈表*/
};
//平臺設(shè)備相關(guān)的led數(shù)據(jù)結(jié)構(gòu)
struct led_info {
const char *name;
const char *default_trigger;
int flags;
};
struct led_platform_data {
int num_leds;
struct led_info *leds;
};
/* For the leds-gpio driver */
//平臺設(shè)備相關(guān)的gpio led數(shù)據(jù)結(jié)構(gòu)
struct gpio_led {
const char *name; //led的名字
const char *default_trigger; //默認(rèn)的trigger
unsigned gpio; //gpio口
unsigned active_low : 1;
unsigned retain_state_suspended : 1;
unsigned default_state : 2;
/* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
};
#define LEDS_GPIO_DEFSTATE_OFF 0
#define LEDS_GPIO_DEFSTATE_ON 1
#define LEDS_GPIO_DEFSTATE_KEEP 2
struct gpio_led_platform_data {
int num_leds; //led的個數(shù)
const struct gpio_led *leds; //平臺設(shè)備相關(guān)的gpio led數(shù)據(jù)結(jié)構(gòu)
#define GPIO_LED_NO_BLINK_LOW 0 /* No blink GPIO state low */
#define GPIO_LED_NO_BLINK_HIGH 1 /* No blink GPIO state high */
#define GPIO_LED_BLINK 2 /* Please, blink */
int (*gpio_blink_set)(unsigned gpio, int state,
unsigned long *delay_on,
unsigned long *delay_off);
};
led-core.c
//主要聲明led的鏈表和鎖
22 DECLARE_RWSEM(leds_list_lock);
23 EXPORT_SYMBOL_GPL(leds_list_lock);
25 LIST_HEAD(leds_list);
26 EXPORT_SYMBOL_GPL(leds_list);
led-class.c
1、 leds_init
主要是創(chuàng)建leds_class,賦值suspend和resume以及dev_attrs。
led_class_attrs
84 static struct device_attribute led_class_attrs[] = {
85 __ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
86 __ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
87 #ifdef CONFIG_LEDS_TRIGGERS
88 __ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
89 #endif
90 __ATTR_NULL,
91 };
2、led_classdev_register
創(chuàng)建classdev設(shè)備,也即Leds_class類中實(shí)例化一個對象,類似于c++的new一個對象,leds有很多種,而這里是注冊一個特定的led,內(nèi)核中的面向?qū)ο笏枷胍矘O其豐富。
加到leds_list鏈表中,初始化blinktimer,指定blink_timer的function和data,設(shè)置trigger,然后一個新的led設(shè)備就注冊好了,就可以使用了。
led-triggers.c
1、led_trigger_register
掃描trigger鏈表中是否有同名的trigger,接著把當(dāng)前trigger加入到鏈表中,如果led_classdev中有默認(rèn)的trigger,那么就設(shè)置這個默認(rèn)的。
好了,簡單看了下led子系統(tǒng)中比較重要的結(jié)構(gòu)體和函數(shù),那么接下去就可以通過leds-gpio這個驅(qū)動來進(jìn)一步了解led子系統(tǒng)了。
總結(jié)
以上是生活随笔為你收集整理的linux led子系统(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis缓存数据表
- 下一篇: 美团支付方式怎么更改