日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux下的LED子系统

發布時間:2024/9/21 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux下的LED子系统 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最簡單的led驅動就是從端口輸出0或1來關閉或點亮燈。而我們這里講的led子系統,主要是對led事件進行了分裝和優化,這里我們主要講的是可以實現跨平臺的led驅動。不管你是使用三星的平臺,還是Atmel的平臺,你只要知道如何在你的BSP中添加平臺數據,并且知道如何在應用程序中使用這個驅動,那么你就不用因為新的平臺而再次編寫led驅動。

按鍵驅動屬于input子系統,源碼路徑在/driver/leds下,我們的跨平臺按鍵驅動文件是/driver/leds/leds-gpio.c,關于led子系統的核心文件是Led-class.c和Led-core.c

查看/driver/leds/Makefile

obj-$(CONFIG_LEDS_GPIO)??????????????????? += leds-gpio.o

查看/driver/leds/Konfig

config LEDS_GPIO

?????? tristate"LED Support for GPIO connected LEDs"

?????? dependson LEDS_CLASS && GENERIC_GPIO

其中

config LEDS_CLASS

?????? tristate"LED Class Support"

所以配置內核makemenuconfig 時,需要選中這兩項。

?

現在先來看如何移植,比如我們現在要給mini2440開發板上的led1到key4編寫led驅動,根據資料知道,led1到led4用的是GPB5-GPB8端口。下面就看移植代碼了,在mach-mini2440.c這個mini2440開發板的BSP中添加如下代碼

static struct gpio_led s3c_gpio_leds[] = {

?????? {

????????????? .name??????????????????? = "led1",

????????????? .gpio???????????????????? = S3C2410_GPB(5),

????????????? .active_low= 1,

?????? },

?????? {

????????????? .name??????????????????? = "led2",

????????????? .gpio???????????????????? = S3C2410_GPB(6),

????????????? .active_low= 1,

?????? },

?????? {

????????????? .name??????????????????? = "led3",

????????????? .gpio???????????????????? = S3C2410_GPB(7),

????????????? .active_low= 1,

?????? },

?????? {

????????????? .name??????????????????? = "led4",

????????????? .gpio???????????????????? = S3C2410_GPB(8),

????????????? .active_low= 1,

?????? },

};

?

static struct gpio_led_platform_datas3c_gpio_led_data = {

?????? .leds??????? = s3c_gpio_leds,

?????? .num_leds?????? = ARRAY_SIZE(s3c_gpio_leds),

};

?

static struct platform_device s3c_leds_gpio= {

?????? .name????? = "leds-gpio",

?????? .id??? = -1,

?????? .dev = {

????????????? .platform_data = &s3c_gpio_led_data,

?????? },

};

然后把這個s3c_leds_gpio加入到mini2440_devices數組

static struct platform_device*mini2440_devices[] __initdata = {

?????? ……

?????? &s3c_leds_gpio, //添加

};

最后添加頭文件

#include <linux/leds.h>

這樣配置完后,進行makezImage生成zImage內核鏡像。

?

下面大致說說/driver/leds/leds-gpio.c

直接看平臺驅動定義

static struct platform_drivergpio_led_driver = {

?????? .probe??????????? = gpio_led_probe,? //探測

?????? .remove????????? = __devexit_p(gpio_led_remove),

?????? .driver??????????? = {

????????????? .name????? = "leds-gpio",? //驅動名

????????????? .owner??? = THIS_MODULE,

?????? },

};

下面看probe探測函數

static int __devinit gpio_led_probe(structplatform_device *pdev)

{

?????? structgpio_led_platform_data *pdata = pdev->dev.platform_data;

?????? structgpio_led_data *leds_data;

?????? inti, ret = 0;

?????? if(!pdata)

????????????? return-EBUSY;

?????? leds_data= kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,? //分配空間

??????????????????????????? GFP_KERNEL);

?????? if(!leds_data)

????????????? return-ENOMEM;

?????? for(i = 0; i < pdata->num_leds; i++) {

????????????? ret= create_gpio_led(&pdata->leds[i], &leds_data[i],

??????????????????????????? ????? &pdev->dev,pdata->gpio_blink_set);? //創建led設備

????????????? if(ret < 0)

???????????????????? gotoerr;

?????? }

?????? platform_set_drvdata(pdev,leds_data);

?????? return0;

err:

?????? for(i = i - 1; i >= 0; i--)

????????????? delete_gpio_led(&leds_data[i]);

?????? kfree(leds_data);

?????? returnret;

}

繼續跟蹤probe中的create_gpio_led函數

static int __devinit create_gpio_led(conststruct gpio_led *template,

?????? structgpio_led_data *led_dat, struct device *parent,

?????? int(*blink_set)(unsigned, unsigned long *, unsigned long *))

{

?????? intret, state;

?????? led_dat->gpio= -1;

?????? if(!gpio_is_valid(template->gpio)) {

????????????? printk(KERN_INFO"Skipping unavailable LED gpio %d (%s)\n",

??????????????????????????? template->gpio,template->name);

????????????? return0;

?????? }

?????? ret= gpio_request(template->gpio, template->name);

?????? if(ret < 0)

????????????? returnret;

?????? led_dat->cdev.name= template->name;

?????? led_dat->cdev.default_trigger= template->default_trigger;

?????? led_dat->gpio= template->gpio;

?????? led_dat->can_sleep= gpio_cansleep(template->gpio);

?????? led_dat->active_low= template->active_low;

?????? if(blink_set) {

????????????? led_dat->platform_gpio_blink_set= blink_set;

????????????? led_dat->cdev.blink_set= gpio_blink_set;?? //定義函數

?????? }

?????? led_dat->cdev.brightness_set= gpio_led_set;? //定義函數

?????? if(template->default_state == LEDS_GPIO_DEFSTATE_KEEP)

????????????? state= !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low;

?????? else

????????????? state= (template->default_state == LEDS_GPIO_DEFSTATE_ON);

?????? led_dat->cdev.brightness= state ? LED_FULL : LED_OFF;

?????? if(!template->retain_state_suspended)

????????????? led_dat->cdev.flags|= LED_CORE_SUSPENDRESUME;

?????? ret= gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);

?????? if(ret < 0)

????????????? gotoerr;

?????? INIT_WORK(&led_dat->work,gpio_led_work);? //初始化工作隊列

?????? ret= led_classdev_register(parent, &led_dat->cdev);? //向leds類中注冊設備

?????? if(ret < 0)

????????????? gotoerr;

?????? return0;

err:

?????? gpio_free(led_dat->gpio);

?????? returnret;

}

?

講到這,讓我們恍然明白,這個leds子系統跟之前分析過的backlight背光子系統是非常類似的。backlight背光子系統在核心層定義了一套device_attribute機制,并且定義了操作backlight背光的操作函數集的接口,同時在device_attribute的show和store屬性中會調用backlight背光的操作函數集。然后我們使用這個backlight背光子系統核心層,編寫自己的驅動時,只需要向backlight背光子系統注冊設備,并填充backlight背光的操作函數集即可。用戶層只需要通過echo向brightness中寫數字觸發store屬性,或者通過cat向brightness中讀數字觸發show屬性。

再回過頭來看看我們這個leds子系統,在create_gpio_led函數中有這樣一行代碼led_dat->cdev.brightness_set= gpio_led_set;其中的函數gpio_led_set是設置燈亮滅的函數,這就是相當于我們給led子系統的操作函數賦值,跟蹤led_classdev_register函數,你會發現在那里會看到定義了leds類屬性,并創建了device_attribute機制,同時同時在device_attribute的store屬性中會調用我們這里定義的的操作函數gpio_led_set。

所以,leds子系統的源碼我就分析到這里了,我在學習backlight子系統的時候,就細細分析過這樣一個類里包含設備屬性,以及設備操作函數,這跟leds-gpio.c代碼原理類似,如果需要可以參考。

?

LED驅動測試

用戶可以先通過cd/sys/class/leds打開led子系統下的設備

然后應用層通過訪問/sys/class/leds/led1來設置等的亮滅

點亮led1:

echo 1 > /sys/class/leds/led1

關閉led1:

echo 0 > /sys/class/leds/led1

總結

以上是生活随笔為你收集整理的Linux下的LED子系统的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。