1. 程式人生 > >初探linux子系統集之led子系統(一)

初探linux子系統集之led子系統(一)

         就像學程式設計第一個範例helloworld一樣,學嵌入式,微控制器、fpga之類的第一個範例就是點亮一盞燈。對於龐大的linux系統,當然可以編寫一個字元裝置驅動來實現我們需要的led燈,也可以直接利用gpio口,應用程式來拉高拉低管腳控制。不過,既然linux系統自己本來就帶有led子系統,那麼就可以好好利用之。好處不用多說了,主要對於應用層來說,不同平臺都用linux的led子系統,那麼應用程式不用做任何的改變,就可以在新的平臺上執行,可移植性好。

         linux的led子系統的原始碼路徑:

                   Include/Linux/leds.h
                  /drivers/leds

         首先看一下led子系統中的主要檔案:

# 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,其中led-triggers又分為了timer、ide-disk、heartbeat、backlight、gpio、default-on等演算法。

例子程式是leds-gpio,接下去會主要分析這個驅動實現。

首先簡單看一下主要的檔案

Leds.h

1、enum led_brightness{
         LED_OFF           = 0,
         LED_HALF         = 127,
         LED_FULL         = 255,
};

Led的亮度,分為三等級,關、中間、最亮。

2、struct led_classdev{
         constchar                  *name;   // Led的名字
         int                       brightness;   //led亮度
         int                       max_brightness; //led最大亮度
         int                       flags;
 
         /*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 */
         void           (*brightness_set)(struct led_classdev*led_cdev,
                                                 enum led_brightness brightness);   //亮度設定函式指標
         /*Get LED brightness level */
         enumled_brightness (*brightness_get)(struct led_classdev *led_cdev); //獲取亮度函式指標
 
         int              (*blink_set)(struct led_classdev*led_cdev,
                                          unsigned long *delay_on,
                                          unsigned long *delay_off);  //閃爍時點亮和熄滅的時間設定
 
         structdevice             *dev;
         structlist_head        node;                        //leds-list的node
         constchar                  *default_trigger;     //預設trigger的名字
 
         unsignedlong           blink_delay_on,blink_delay_off;   //閃爍的開關時間
         structtimer_list       blink_timer;                    //閃爍的定時器連結串列
         int                       blink_brightness;                   //閃爍的亮度
 
#ifdef CONFIG_LEDS_TRIGGERS
         /*Protects the trigger data below */
         structrw_semaphore      trigger_lock;               //trigger的鎖
 
         structled_trigger    *trigger;                      //led的trigger
         structlist_head        trig_list;                     //trigger的連結串列
         void                    *trigger_data;                     //trigger的資料
#endif
};
3、struct led_trigger {
         /*Trigger Properties */
         constchar        *name;           //trigger的名字
         void           (*activate)(struct led_classdev*led_cdev);   //啟用trigger
         void           (*deactivate)(struct led_classdev*led_cdev);  
 
         /*LEDs under control by this trigger (for simple triggers) */
         rwlock_t   leddev_list_lock;
         structlist_head  led_cdevs;                     //led裝置的連結串列
 
         /*Link to next registered trigger */
         structlist_head  next_trig;
};
4、/* For the leds-gpiodriver */
struct gpio_led {
         constchar *name;              //led的名字
         constchar *default_trigger;            //預設的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) */
};
 
5、structgpio_led_platform_data {
         int           num_leds;             led的個數
         conststruct gpio_led *leds;       led結構體
 
#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,
                                               unsignedlong *delay_on,
                                               unsignedlong *delay_off);
};
 


led-core.c

DECLARE_RWSEM(leds_list_lock);
EXPORT_SYMBOL_GPL(leds_list_lock);
 
LIST_HEAD(leds_list);
EXPORT_SYMBOL_GPL(leds_list);

主要是聲明瞭leds的連結串列和鎖。

Led-class.c

1、  leds_init

主要是建立leds_class,賦值suspend和resume以及dev_attrs。

led_class_attrs

static  struct device_attribute led_class_attrs[] = {
         __ATTR(brightness,0644, led_brightness_show, led_brightness_store),
         __ATTR(max_brightness,0444, led_max_brightness_show, NULL),
#ifdef CONFIG_LEDS_TRIGGERS
         __ATTR(trigger,0644, led_trigger_show, led_trigger_store),
#endif
         __ATTR_NULL,
};

2、led_classdev_register

         建立classdev裝置,也即Leds_class類中例項化一個物件,類似於c++的new一個物件,leds有很多種,而這裡是註冊一個特定的led,核心中的面向物件思想也極其豐富。

         加到leds_list連結串列中,初始化blinktimer,指定blink_timer的function和data,設定trigger,然後一個新的led裝置就註冊好了,就可以使用了。

led-triggers.c

1、led_trigger_register

         掃描trigger連結串列中是否有同名的trigger,接著把當前trigger加入到連結串列中,如果led_classdev中有預設的trigger,那麼就設定這個預設的。

好了,簡單看了下led子系統中比較重要的結構體和函式,那麼接下去就可以通過leds-gpio這個驅動來進一步瞭解led子系統了。