leds-gpio驅動移植

概述

leds-gpio封裝得十分好,只需要提供可正常使用的GPIO即可。另外還具備觸發器功能,其實就是控制LED的亮滅(及頻率)。比如default-on是點亮LED燈的觸發器,沒有取消前一直亮着。heartbeat是心跳觸發器,經筆者實踐,此觸發器是快速閃爍2次,然後滅掉,滅掉時間較亮的時間長。timer爲定時觸發器,即1HZ內亮滅。其它還有如ide硬盤、mmc、CPU觸發器,就不一一介紹了。

leds驅動位於drivers/leds目錄。leds-gpio驅動名稱爲“leds-gpio”,驅動文件爲drivers/leds/leds-gpio.c。

觸發器驅動位於drivers/leds/trigger目錄。

內核配置

本文基於linux 3.17.1版本內核進行分析。

Device Drivers->  
    -*- LED Support  --->    
        {*}   LED Class Support # 與用戶空間交互的  
        <M>   LED Support for GPIO connected LEDs   # 可爲模塊,也可編譯到內核中  
        -*-   LED Trigger support  ---> #觸發器,最好編譯到內核中(即選項“*”)  
        <*>   LED Timer Trigger  
        <*>   LED One-shot Trigger  
        <*>   LED Heartbeat Trigger  
        <*>   LED backlight Trigger  
        [*]   LED CPU Trigger  
        <*>   LED GPIO Trigger  
        <*>   LED Default ON Trigger

從配置中看到,筆者將LED觸發器全部編譯到內核中。這樣方便使用和選擇。

設備註冊及使用

LED相關結構體

驅動開發者使用gpio_led對LED進行賦值,包括LED名稱、GPIO引腳號、燈亮是哪個電平,還有默認狀態。gpio_led結構體定義如下:

struct gpio_led {  
    const char *name; // 名稱,會生成/sys/.../leds/name目錄  
    const char *default_trigger; // 默認觸發器,可寫可不寫,在命令行可以重新賦值  
    unsigned     gpio; // GPIO引腳號  
    unsigned    active_low : 1; // 爲1表示低電平LED點亮  
    unsigned    retain_state_suspended : 1;  
    unsigned    default_state : 2; // 默認狀態  
    /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */  
}; 

另外還要填寫gpio_led_platform_data結構體,其定義如下:

struct gpio_led_platform_data {  
    int         num_leds; // 一共有多少個LED燈  
    const struct gpio_led *leds; // 上面的結構體指針  
  
#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閃爍回調函數,可置爲NULL  
}; 

一個實例如下:

static struct gpio_led gpio_leds[] = {  
    {  
        .name = "red",  
        .gpio = 33, // GP2_1   GPIO_NO = Group * 32 + Id  
        .default_state = LEDS_GPIO_DEFSTATE_ON, // 默認LED亮  
        .active_low = 1, // 低電平亮  
        //.default_trigger = "timer", // 觸發器  
    },  
    {  
        .name = "green",  
        .gpio = 34,  
        .default_state = LEDS_GPIO_DEFSTATE_ON,   
        .active_low = 1,  
        //.default_trigger = "heartbeat",   
    },  
};  
  
static struct gpio_led_platform_data gpio_led_info = {  
     .leds          = gpio_leds,  
     .num_leds     = ARRAY_SIZE(gpio_leds),  
}; 

從結構體中知道,系統有2個LED,一個紅燈,一個綠燈,都是低電平燈亮。

驅動源碼分析

leds-gpio驅動定義如下(drivers/leds/leds-gpio.c):

static struct platform_driver gpio_led_driver = {  
    .probe        = gpio_led_probe,  
    .remove        = gpio_led_remove,  
    .driver        = {  
        .name    = "leds-gpio",  
        .owner    = THIS_MODULE,  
        .of_match_table = of_match_ptr(of_gpio_leds_match),  
    },  
};  
  
module_platform_driver(gpio_led_driver); 

從gpio_led_driver結構體中可以看到驅動名稱爲leds-gpio。因此要使用這個驅動,必須另外定義一個platform設備,並調用函數platform_device_register註冊。本文實例如下:

static struct platform_device leds_gpio = {  
    .name = "leds-gpio",  
    .id = -1,  
    .dev = {  
        .platform_data = &gpio_led_info,  
        .release = platformdev_release,  
    },  
};  

其中name表示設備名稱,必須爲“leds-gpio”,這樣才能匹配並加載成功。最後提一下release成員,在較新的內核中必須對此進行賦值,否則會有錯誤信息提示:

Device 'leds-gpio' does not have a release() function, it is broken and must be fixed.

最後,註冊leds設備——建議在板子的GPIO正常工作之後再進行註冊。

platform_device_register(&leds_gpio); // 註冊leds設備  

注意,如果是以modules形式動態加載的話,必須要適合的地方如remove函數在卸載leds設備:

platform_device_unregister(&leds_gpio); // 卸載leds設備  

應用實例

LED設備和驅動都正常情況下,系統啓動後,會產生/sys/bus/platform/devices/leds-gpio/leds目錄,其下分別有red和green兩個子目錄。可以分別對不同的紅色LED和綠色LED做操作。

亮滅LED

將1或0寫入brightness文件即可控制亮滅。

示例如下:

echo 0 > /sys/bus/platform/devices/leds-gpio/leds/green/brightness  
echo 0 > /sys/bus/platform/devices/leds-gpio/leds/red/brightness   

echo 1 > /sys/bus/platform/devices/leds-gpio/leds/green/brightness  
echo 1 > /sys/bus/platform/devices/leds-gpio/leds/red/brightness   

觸發器

直接查看trigger文件,即可知道當前系統支持的觸發器,示例:

cat /sys/bus/platform/devices/leds-gpio/leds/red/trigger   
[none] timer oneshot heartbeat backlight gpio cpu0 default-on mmc0 mmc1 mmc2  

在前面的驅動中註釋掉了trigger,所以現在是none。

設置觸發器很簡單,使用ecoh將需要的觸發器名稱寫入trigger文件即可。注意,寫入的字符串一定是trigger文件已經存在的,否則會提示參數非法。寫入心跳觸發器示例:

echo heartbeat > /sys/bus/platform/devices/leds-gpio/leds/red/trigger 

此時板子上紅燈應會閃爍。

再次查看:

cat /sys/bus/platform/devices/leds-gpio/leds/red/trigger   

none timer oneshot [heartbeat] backlight gpio cpu0 default-on mmc0 mmc1 mmc2  

設置值已經生效了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章