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
led子系统的更多相关文章
- LED子系统剖析
写之前,先看一张图: 上次说了LED驱动程序,Linux自身也携带了LED驱动,且是脱离平台的,即LED子系统.操作起来十分简单.但是它的实质却不是那么容易,研究了一个晚上,终于明白了其中一个文件的功 ...
- 初探linux子系统集之led子系统(三)
世界杯结束了,德国战车夺得了大力神杯,阿根廷最终还是失败了.也许3年,5年,或者10年后,人们就不知道巴西世界杯的亚军是谁,但是总是会记得冠军是谁.就像什么考试,比赛,第一永远会被人们所记住,所以我们 ...
- 初探linux子系统集之led子系统(二)
巴西世界杯,德国7比1东道主,那个惨不忍睹啊,早上起来看新闻,第一眼看到7:1还以为点球也能踢成这样,后来想想,点球对多嘛6比1啊,接着就是各种新闻铺天盖地的来了.其实失败并没有什么,人生若是能够成功 ...
- 初探linux子系统集之led子系统(一)
就像学编程第一个范例helloworld一样,学嵌入式,单片机.fpga之类的第一个范例就是点亮一盏灯.对于庞大的linux系统,当然可以编写一个字符设备驱动来实现我们需要的led灯,也可以直接利用g ...
- arm Linux 驱动LED子系统 测试
Linux内核在3.0以上引入了设备树概念(具体哪个版本不清楚)在编译内核后需要将与之对应的dtb文件也下载人板子上才能使内核与硬件关联起来. dtb文件是有dts文件编译后生成的:例如 /* * C ...
- linux led子系统(二)
对于led子系统中,有那么多得trigger,下面就来简单了解下. 1.default-on static void defon_trig_activate(struct led_classdev * ...
- linux led子系统(一)
就像学编程第一个范例helloworld一样,学嵌入式,单片机.fpga之类的第一个范例就是点亮一盏灯.对于庞大的linux系统,当然可以编写一个字符设备驱动来实现我们需要的led灯,也可以直接利用g ...
- 初探linux子系统集之led子系统(三)【转】
本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37822837 世界杯结束了,德国战车夺得了大力神杯,阿根廷最终还是失败了.也许3 ...
- 初探linux子系统集之led子系统(二)【转】
本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37606487 巴西世界杯,德国7比1东道主,那个惨不忍睹啊,早上起来看新闻,第一 ...
随机推荐
- Activity 变成对话框,然后再隐藏?
由于继续需要做一些无感操控的工作,之前也记录了下利用悬浮窗的方法.今天突然发现原来activity可以直接嗯嗯嗯啊. 首先我在AndroidManifest里给activity添加了如下一行: and ...
- JVM 入门三板斧
一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的.类加载器读取了类文件后,需要把类.方法.常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行,堆内存分为三部分: Young Ge ...
- MySql(十七):MySql架构设计——高可用设计之思路及方案
前言: 数据库系统是一个应用系统的核心部分,要想系统整体可用性得到保证,数据库系统就不能出现任何问题.对于一个企业级的系统来说,数据库系统的可用性尤为重要.数据库系统一旦出现问题无法提供服务,所有系统 ...
- Storm工作流程
为什么storm的数据来自于消息队列? Storm的解决问题的scope主要在于流计算,说流计算之前我们先简单的说下一般数据处理系统的过程.一般数据处理简单说要有几个环节:数据采集,数据计算,结果输出 ...
- 如何使用好android的可访问性服务(Accessibility Services)
原文:http://android.eoe.cn/topic/android_sdk * 主题* Manifest声明和权限 可访问性服务声明 可访问性服务配置 AccessibilityServic ...
- [CTCI] 子串判断
子串判断 题目描述 现有一个小写英文字母组成的字符串s和一个包含较短小写英文字符串的数组p,请设计一个高效算法,对于p中的每一个较短字符串,判断其是否为s的子串. 给定一个string数组p和它的大小 ...
- google云使用记录
gcloud工具在win下安装十分不便,而且由于众所周知的原因,无法连接,我的解决办法就是安装另外一个vps(centos7系统),然后在那里安装gcloud工具,对google进行远程访问. 1.利 ...
- ace admin后台模板
http://ace.jeka.by/index.html 下载: http://www.daimajiayuan.com/plus/download.php?open=0&aid=18152 ...
- android笔记---ScrollView
<!--在创建xml文件的时候选择ScrollView类型--> <?xml version="1.0" encoding="utf-8"?& ...
- (原创)发布一个C++版本的ORM库SmartDB(一)
先简单说说ORM的优点: 提高开发效率,减少重复劳动,只和业务实体打交道,由业务实体自动生成sql语句,不用手写sql语句. 简单易用, 可维护性好. 隔离数据源,使得我们更换数据源时不用修改代码. ...