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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux下的LED子系统

發(fā)布時(shí)間:2024/9/21 linux 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux下的LED子系统 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

最簡(jiǎn)單的led驅(qū)動(dòng)就是從端口輸出0或1來(lái)關(guān)閉或點(diǎn)亮燈。而我們這里講的led子系統(tǒng),主要是對(duì)led事件進(jìn)行了分裝和優(yōu)化,這里我們主要講的是可以實(shí)現(xiàn)跨平臺(tái)的led驅(qū)動(dòng)。不管你是使用三星的平臺(tái),還是Atmel的平臺(tái),你只要知道如何在你的BSP中添加平臺(tái)數(shù)據(jù),并且知道如何在應(yīng)用程序中使用這個(gè)驅(qū)動(dòng),那么你就不用因?yàn)樾碌钠脚_(tái)而再次編寫led驅(qū)動(dòng)。

按鍵驅(qū)動(dòng)屬于input子系統(tǒng),源碼路徑在/driver/leds下,我們的跨平臺(tái)按鍵驅(qū)動(dòng)文件是/driver/leds/leds-gpio.c,關(guān)于led子系統(tǒng)的核心文件是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"

所以配置內(nèi)核makemenuconfig 時(shí),需要選中這兩項(xiàng)。

?

現(xiàn)在先來(lái)看如何移植,比如我們現(xiàn)在要給mini2440開(kāi)發(fā)板上的led1到key4編寫led驅(qū)動(dòng),根據(jù)資料知道,led1到led4用的是GPB5-GPB8端口。下面就看移植代碼了,在mach-mini2440.c這個(gè)mini2440開(kāi)發(fā)板的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,

?????? },

};

然后把這個(gè)s3c_leds_gpio加入到mini2440_devices數(shù)組

static struct platform_device*mini2440_devices[] __initdata = {

?????? ……

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

};

最后添加頭文件

#include <linux/leds.h>

這樣配置完后,進(jìn)行makezImage生成zImage內(nèi)核鏡像。

?

下面大致說(shuō)說(shuō)/driver/leds/leds-gpio.c

直接看平臺(tái)驅(qū)動(dòng)定義

static struct platform_drivergpio_led_driver = {

?????? .probe??????????? = gpio_led_probe,? //探測(cè)

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

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

????????????? .name????? = "leds-gpio",? //驅(qū)動(dòng)名

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

?????? },

};

下面看probe探測(cè)函數(shù)

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);? //創(chuàng)建led設(shè)備

????????????? 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;

}

繼續(xù)跟蹤probe中的create_gpio_led函數(shù)

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;?? //定義函數(shù)

?????? }

?????? led_dat->cdev.brightness_set= gpio_led_set;? //定義函數(shù)

?????? 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);? //初始化工作隊(duì)列

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

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

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

?????? return0;

err:

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

?????? returnret;

}

?

講到這,讓我們恍然明白,這個(gè)leds子系統(tǒng)跟之前分析過(guò)的backlight背光子系統(tǒng)是非常類似的。backlight背光子系統(tǒng)在核心層定義了一套device_attribute機(jī)制,并且定義了操作backlight背光的操作函數(shù)集的接口,同時(shí)在device_attribute的show和store屬性中會(huì)調(diào)用backlight背光的操作函數(shù)集。然后我們使用這個(gè)backlight背光子系統(tǒng)核心層,編寫自己的驅(qū)動(dòng)時(shí),只需要向backlight背光子系統(tǒng)注冊(cè)設(shè)備,并填充backlight背光的操作函數(shù)集即可。用戶層只需要通過(guò)echo向brightness中寫數(shù)字觸發(fā)store屬性,或者通過(guò)cat向brightness中讀數(shù)字觸發(fā)show屬性。

再回過(guò)頭來(lái)看看我們這個(gè)leds子系統(tǒng),在create_gpio_led函數(shù)中有這樣一行代碼led_dat->cdev.brightness_set= gpio_led_set;其中的函數(shù)gpio_led_set是設(shè)置燈亮滅的函數(shù),這就是相當(dāng)于我們給led子系統(tǒng)的操作函數(shù)賦值,跟蹤led_classdev_register函數(shù),你會(huì)發(fā)現(xiàn)在那里會(huì)看到定義了leds類屬性,并創(chuàng)建了device_attribute機(jī)制,同時(shí)同時(shí)在device_attribute的store屬性中會(huì)調(diào)用我們這里定義的的操作函數(shù)gpio_led_set。

所以,leds子系統(tǒng)的源碼我就分析到這里了,我在學(xué)習(xí)backlight子系統(tǒng)的時(shí)候,就細(xì)細(xì)分析過(guò)這樣一個(gè)類里包含設(shè)備屬性,以及設(shè)備操作函數(shù),這跟leds-gpio.c代碼原理類似,如果需要可以參考。

?

LED驅(qū)動(dòng)測(cè)試

用戶可以先通過(guò)cd/sys/class/leds打開(kāi)led子系統(tǒng)下的設(shè)備

然后應(yīng)用層通過(guò)訪問(wèn)/sys/class/leds/led1來(lái)設(shè)置等的亮滅

點(diǎn)亮led1:

echo 1 > /sys/class/leds/led1

關(guān)閉led1:

echo 0 > /sys/class/leds/led1

總結(jié)

以上是生活随笔為你收集整理的Linux下的LED子系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。