本文轉載自:http://blog.csdn.net/yuanlulu/article/details/6438847
============================================
作者:yuanlulu
http://blog.csdn.NET/yuanlulu
版權沒有,但是轉載請保留此段聲明
============================================
gpio-led框架
/driver/leds/leds-gpio.c下實現了gpio-led框架。這個gpio-led框架的作用是把傳入的gpio端口信息,注冊成 led_classdev。
數據結構
平台設備相關的gpio led數據結構
/include/linux/leds.h
struct gpio_led {
const char *name; //名字
char *default_trigger; //默認觸發器的名字
unsigned gpio; //使用的gpio編號
u8 active_low; //如果為真則邏輯1代表低電平
};
struct gpio_led_platform_data {
int num_leds; //gpio led的數量
struct gpio_led *leds; //指向要注冊的gpio_led數組
int (*gpio_blink_set)(unsigned gpio, //硬件閃爍加速設置,可以為NULL
unsigned long *delay_on,
unsigned long *delay_off);
};
const char *name; //名字
char *default_trigger; //默認觸發器的名字
unsigned gpio; //使用的gpio編號
u8 active_low; //如果為真則邏輯1代表低電平
};
struct gpio_led_platform_data {
int num_leds; //gpio led的數量
struct gpio_led *leds; //指向要注冊的gpio_led數組
int (*gpio_blink_set)(unsigned gpio, //硬件閃爍加速設置,可以為NULL
unsigned long *delay_on,
unsigned long *delay_off);
};
如何注冊gpio-led平台設備
例子如下:
#define GPIO_LED3 138
#define GPIO_LED4 139
static struct gpio_led gpio_leds[] = {
{
.name = "led3",
.default_trigger = "heartbeat",
.gpio = GPIO_LED3,
.active_low = 1,
.default_state = LEDS_GPIO_DEFSTATE_OFF,
},
{
.name = "led4",
.gpio = GPIO_LED4,
.active_low = 1,
.default_state = LEDS_GPIO_DEFSTATE_OFF,
},
};
static struct gpio_led_platform_data gpio_led_info = {
.leds = gpio_leds,
.num_leds = ARRAY_SIZE(gpio_leds),
};
static struct platform_device leds_gpio = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &gpio_led_info,
},
};
#define GPIO_LED4 139
static struct gpio_led gpio_leds[] = {
{
.name = "led3",
.default_trigger = "heartbeat",
.gpio = GPIO_LED3,
.active_low = 1,
.default_state = LEDS_GPIO_DEFSTATE_OFF,
},
{
.name = "led4",
.gpio = GPIO_LED4,
.active_low = 1,
.default_state = LEDS_GPIO_DEFSTATE_OFF,
},
};
static struct gpio_led_platform_data gpio_led_info = {
.leds = gpio_leds,
.num_leds = ARRAY_SIZE(gpio_leds),
};
static struct platform_device leds_gpio = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &gpio_led_info,
},
};
最后調用platform_device_register(&leds_gpio)將LED設備注冊到內核中。注冊之前一定要保證編號為138和139的兩個端口是可用的。
成功注冊之后,系統中便會出現名為led3和led4的兩個led_classdev了。由於是用gpio模擬led,所以對gpio-led設置的亮度,只要不是0就是全亮(gpio只有兩個狀態)。
對於可能睡眠的gpio,gpio-led會借助於工作隊列去設置亮度,所以不用擔心會被阻塞。
default-on觸發器
在/driver/leds/ledtrig-default-on.c中實現了一個名為“default-on”的觸發器。這個觸發器只定義了activate成員函數。它的activate函數的定義如下:
static void defon_trig_activate(struct led_classdev *led_cdev)
{
led_set_brightness(led_cdev, LED_FULL);
}
{
led_set_brightness(led_cdev, LED_FULL);
}
也就是說,點亮led只能是最亮的亮度,無法調節。一旦ledl_classdev與之建立了連接,就一直處於最亮的狀態,直到取消和觸發器的連接。
心跳燈觸發器
在/driver/leds/ledtrig-heartbeat.c中定義了一個名為"heartbeat"的心跳觸發器,它可以控制所有與之建立連接的led會不停的閃爍。這個觸發器用來指示內核是否已經掛掉。如果與之建立連接的led不再閃爍了,說明內核已經掛掉了。這就是“心跳”的含義,和從人的心臟是否跳動來判斷人是否死亡的原理是類似的。
IDE硬盤指示燈觸發器
在/driver/leds/ledtrig-ide-disk.c中定義了一個名為“ide-disk”的IDE硬盤指示燈觸發器,與之建立連接的led可以指示硬盤的忙碌狀態。這個觸發器並沒有active接口,因此不會自動閃爍。當內核中的其他模塊調用以下函數的時候硬盤指示燈就會亮閃一下:
void ledtrig_ide_activity(void);
這個函數是全局函數,內核空間都可以調用。每調用一次就閃爍一下。具體怎么用,完全依賴於IDE驅動。
可以有多個led_classdev和這個觸發器建立連接。每次調用ledtrig_ide_activity,所有與之連接的led都會閃爍一下。
使用ledtrig_ide_activity這個函數的模塊應該包含<linux/leds.h>這個頭文件。
閃爍定時觸發器
在/driver/leds/ledtrig-timer.c中定義了一個名為“timer”的觸發器。當某個led_classdev與之連接后,這個觸發器會在/sys/class/leds/<device>/下創建兩個屬性文件delay_on/delay_off。用戶空間往這兩個文件中寫入數據后,相應的led會按照設置的高低電平的時間(單位毫秒)來閃爍。如果led_classdev注冊了硬件閃爍的接口led_cdev->blink_set就是用硬件控制閃爍,否則用軟件定時器來控制閃爍。
led_classdev的sysfs屬性文件
現在假設有一個名為“REDLED”的led_classdev被注冊了,那么會出現/sys/class/leds/REDLED這個目錄,這個目錄下默認有brightness和trigger這兩個屬性文件,分別可以設置/讀取led的亮度和觸發器。如果和觸發器“timer”建立了連接,還會有delay_on和delay_off,這兩個文件用於設置/讀取閃爍的熄滅和點亮的時間,單位是毫秒。
LED子系統的使用
系統定義了四個默認觸發器:default_on、心跳觸發器、硬盤燈觸發器、閃爍觸發器。除了硬盤燈觸發器,其他觸發器沒有留從其它內核模塊訪問的接口。led子系統的目的主要是給用戶空間控制led的。當然可以定義自己的觸發器並留給其它模塊訪問的接口。
- 頂
- 0
- 踩