s3c2440 在linux,LED驱动 - 基于S3C2440的Linux-3.6.6移植_Linux编程_Linux公社-Linux系统门户网站...

news/2024/5/20 10:47:46/文章来源:https://blog.csdn.net/weixin_42131633/article/details/117273380

目前的linux版本的许多驱动都是基于设备模型,LED也不例外。

简单地说,设备模型就是系统认为所有的设备都是挂接在总线上的,而要使设备工作,就需要相应的驱动。设备模型会产生一个虚拟的文件系统——sysfs,它给用户提供了一个从用户空间去访问内核设备的方法,它在linux里的路径是/sys。如果要写程序访问sysfs,可以像读写普通文件一样来操作/sys目录下的文件。

对于基于s3c2440的开发板来说,linux-3.6.6自动的LED驱动只需改变连接LED的IO端口,及高、低电平响应即可。我的开发板的四个LED连接在了B口的5到8引脚上,当输出低电平时被点亮,与linux自带的LED驱动一致,因此无需做任何改动。

使用menuconfig来配置内核,这里要加上对LED模块的内容,即:

Device Drivers--->

[*]LED Support--->

LED Class Support

LED Support for Samsung S3C24xx GPIO LEDs

编译内核,并把编译好的内核下载到开发板上,运行:

[root@zhaocj /]#ls

bin etc lib proc sys usr

dev home linuxrc sbin temp

[root@zhaocj /]#cd sys

[root@zhaocj /sys]#ls

block class devices fs module

bus dev firmware kernel power

进入sys目录下,我们看到该目录下有一些子目录。

[root@zhaocj /sys]#cd class

[root@zhaocj class]#ls

backlight hidraw leds rtc vc

bdi hwmon mem sound video_output

block i2c-adapter misc spi_master vtconsole

firmware i2c-dev mmc_host spidev watchdog

gpio input mtd tty

graphics lcd net udc

进入class目录,我们会看到在该目录下有一些设备,其中leds就是本次我们要操作的LED。

[root@zhaocj class]#cd leds

[root@zhaocj leds]#ls

backlight led1 led2 led3 led4

在leds目录下,会看到四个LED的目录,这就是开发板上的四个LED。另外backlight目录是关于LCD的背光,与LED无关。

[root@zhaocj leds]#cd led1

[root@zhaocj led1]#ls

brightness max_brightness subsystem

device power uevent

brightness文件就是LED设备,对其进行操作就可完成对LED的控制。

[root@zhaocj led1]#cat brightness

0

可以看出led1当前的状态是关闭。(0表示关闭,1表示打开)

[root@zhaocj led1]#cat >brightness<

> 1

> eof

#[root@zhaocj led1]#

向brightness写1,表示打开LED。这时led1会被点亮。

当然,我们也可以编写用户程序来控制开发板上的四个LED

/**********************

****leds.c**************

**********************/

#include

#include

#include

#include

#include

#include

#include

int main(int argc, char *argv[])

{

int fd, no;

/*判断是要控制哪个LED,并打开相应的文件*/

no=(int)argv[1][3]-48;

switch(no)

{

case 1:

fd = open("/sys/class/leds/led1/brightness", O_RDWR);

break;

case 2:

fd = open("/sys/class/leds/led2/brightness", O_RDWR);

break;

case 3:

fd = open("/sys/class/leds/led3/brightness", O_RDWR);

break;

case 4:

fd = open("/sys/class/leds/led4/brightness", O_RDWR);

break;

default:

return -1;

}

if(fd<0)

{

printf("can not open file.\n");

return -1;

}

/*完成打开或关闭LED操作*/

if(!strcmp(argv[2],"on"))

write(fd, "1", 1);

else if(!strcmp(argv[2],"off"))

write(fd, "0", 1);

close(fd);

return 0;

}

上面的程序只做简单测试之用。编译该文件:

arm-linux-gcc -o leds leds.c

把leds文件下载到temp目录下,运行:

[root@zhaocj /temp]# ./leds led2 on

则点亮led2。

[root@zhaocj /temp]# ./leds led2 off

则关闭led2。

下面我就来简单分析一下linux自带的LED子系统。

在mach-zhaocj2440.c文件,创建了LED设备,如下:

/* LEDS */

static struct s3c24xx_led_platdata zhaocj2440_led1_pdata = {

.name = "led1",

.gpio = S3C2410_GPB(5),

.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,

.def_trigger = "heartbeat",

};

static struct s3c24xx_led_platdata zhaocj2440_led2_pdata = {

.name = "led2",

.gpio = S3C2410_GPB(6),

.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,

.def_trigger = "nand-disk",

};

static struct s3c24xx_led_platdata zhaocj2440_led3_pdata = {

.name = "led3",

.gpio = S3C2410_GPB(7),

.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,

.def_trigger = "mmc0",

};

static struct s3c24xx_led_platdata zhaocj2440_led4_pdata = {

.name = "led4",

.gpio = S3C2410_GPB(8),

.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,

.def_trigger = "",

};

定义了四个LED数据,名字分别为led1~led4,这就是我们在leds目录下看到这四个子目录。它们所连接的引脚分别为B口的5~8,这是由S3C2410_GPB()宏定义完成的。标识S3C24XX_LEDF_ACTLOW表示的是低电平有效,S3C24XX_LEDF_TRISTATE表示的三态无效。另外def_trigger表示的是触发控制,如我们对nand进行读写操作时,led2会不停的闪,在这里我们没有用到这个功能,暂时不用理会。

static struct platform_device zhaocj2440_led1= {

.name = "s3c24xx_led",

.id = 1,

.dev = {

.platform_data = &zhaocj2440_led1_pdata,

},

};

static struct platform_device zhaocj2440_led2= {

.name = "s3c24xx_led",

.id = 2,

.dev = {

.platform_data = &zhaocj2440_led2_pdata,

},

};

static struct platform_device zhaocj2440_led3= {

.name = "s3c24xx_led",

.id = 3,

.dev = {

.platform_data = &zhaocj2440_led3_pdata,

},

};

static struct platform_device zhaocj2440_led4= {

.name = "s3c24xx_led",

.id = 4,

.dev = {

.platform_data = &zhaocj2440_led4_pdata,

},

};

上面则创建了总线平台设备,四个LED的设备名称都是s3c24xx_led,子设备id分别从1到4,设备数据则是上面定义的四个LED数据。然后把这四个LED设备再添加到开发板的设备数组中,即:

static struct platform_device *zhaocj2440_devices[]__initdata = {

……

&zhaocj2440_led1,

&zhaocj2440_led2,

&zhaocj2440_led3,

&zhaocj2440_led4,

……

};

最后,在开发板系统初始化过程中,再把设备数组中的设备逐一注册到系统总线上,即:

static void __init zhaocj2440_init(void)

{

……

platform_add_devices(zhaocj2440_devices,ARRAY_SIZE(zhaocj2440_devices));

……

}

这样就完成了LED设备的创建。

光有设备还不能工作,任何一个设备的运行还需要与之相对应的驱动。对于基于s3c24xx的LED来说,它的驱动是在drivers/leds目录下Leds-s3c24xx.c文件内创建的,即:

static struct platform_driver s3c24xx_led_driver = {

.probe = s3c24xx_led_probe,

.remove = s3c24xx_led_remove,

.driver = {

.name = "s3c24xx_led",

.owner = THIS_MODULE,

},

};

设备和驱动是如何匹配的呢?即设备如何找到它所对应的驱动的呢?靠的就是name。我们会发现platform_device和platform_driver都有元素name,它们的内容如果一致,设备和驱动就会配对成功。对于LED来说,它们的name都是s3c24xx_led。当设备和驱动匹配上以后,就要运行probe所指定的函数,简单地说,它就是完成一些初始化工作。当需要移除设备时,就需要运行remove所指定的函数,它完成的任务是注销设备。对于支持热插拔的设备来说,尤为重要。

现在就来说一下s3c24xx_led_probe函数:

static int s3c24xx_led_probe(struct platform_device *dev)

{

structs3c24xx_led_platdata*pdata = dev->dev.platform_data;

structs3c24xx_gpio_led *led;

intret;

/*用于给LED分配内存空间*/

led =devm_kzalloc(&dev->dev, sizeof(struct s3c24xx_gpio_led),

GFP_KERNEL);

if(led == NULL) {

dev_err(&dev->dev,"No memory for device\n");

return-ENOMEM;

}

/*保存LED设备结构*/

platform_set_drvdata(dev,led);

/*给LED结构体赋值,其中s3c24xx_led_set就是具体负责操作LED的函数*/

led->cdev.brightness_set= s3c24xx_led_set;

led->cdev.default_trigger= pdata->def_trigger;

led->cdev.name= pdata->name;

led->cdev.flags|= LED_CORE_SUSPENDRESUME;

led->pdata = pdata;

/*为LED分配io引脚*/

ret =devm_gpio_request(&dev->dev, pdata->gpio, "S3C24XX_LED");

if(ret < 0)

returnret;

/*no point in having a pull-up if we are always driving */

/*无需上拉*/

s3c_gpio_setpull(pdata->gpio, S3C_GPIO_PULL_NONE);

/*设置io引脚为输入*/

if(pdata->flags & S3C24XX_LEDF_TRISTATE)

gpio_direction_input(pdata->gpio);

else

gpio_direction_output(pdata->gpio,

pdata->flags& S3C24XX_LEDF_ACTLOW ? 1 :0);

/*register our new led device */

/*注册一个新的LED设备类对象

该函数是在drivers/leds目录下的Led-class.c文件内定义的*/

ret= led_classdev_register(&dev->dev, &led->cdev);

if(ret < 0)

dev_err(&dev->dev,"led_classdev_register failed\n");

return ret;

}

从以上分析可以看出,s3c24xx_led_probe函数主要就是完成LED设备的一些初始化工作。而负责开、关LED任务的是s3c24xx_led_set函数,在该函数内,gpio_set_value(pd->gpio, state);是具体完成为相应引脚置1或清零的任务。

drivers/leds目录下的Led-class.c文件是LED子系统的底层核心文件,它主要负责创建LED类,以及创建设备节点,上面提到的led_classdev_register函数就是在这个文件中定义的。为了更好的理解LED子系统,我们再简单分析一下该文件。

在子系统初始化时,会调用leds_init函数,它的第一段代码:

leds_class = class_create(THIS_MODULE,"leds");

就是创建leds类,也就是我们在sys/class目录下看到的leds目录。另外

leds_class->dev_attrs = led_class_attrs;

是赋予该类的属性。那么我们再来看看led_class_attrs结构的第一句代码:

__ATTR(brightness, 0644, led_brightness_show,led_brightness_store)

其中brightness就是我们对LED具体操作的设备文件名,0644是该文件的权限,led_brightness_show是读文件所调用的函数,led_brightness_store是写文件所调用的函数。读文件也就是读取LED的状态(是关还是开),写文件也就是完成打开LED或关闭LED操作。

最后再分析一下前面提到的led_classdev_register函数。在该函数内首先利用device_create函数创建设备节点,也就是在leds目录下,生成led1~led4这四个目录。另一项重要的任务就是把设备节点添加到leds的链表中。

对linux自带的LED子系统的分析就到这里。我想只要理解了该子系统,那么自己完全可以写出关于GPIO读写操作的任何驱动程序来。0b1331709591d260c1c78e86d0c51c18.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_837717.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php毕业设计定制,基于PHP的玩偶定制网站设计毕业论文+设计源码+测试说明

基于PHP的玩偶定制网站设计摘 要网上定制相比传统购物的更加便捷的优势&#xff0c;加上如今配套物流的建设&#xff0c;网上支付技术的完善。使得消费者能够做到足不出户&#xff0c;即可享受到安全便捷的购物过程。因而越来越多的人开始亲睐”网购”。而网上商城可以不受地域…

站长服务器维护,站长管理,该如何定期维护网站?

随着时代的不断发展&#xff0c;网站对于企业的发展有着越来越重要的作用了&#xff0c;无论什么类型的企业&#xff0c;都已经有了独立的网站了&#xff0c;也都开始利用网站来进行推广宣传了。但是&#xff0c;有些企业在做网站推广宣传的时候&#xff0c;会遇到一些问题&…

php+mysql图书管理系统_[源码和文档分享]基于PHP和MYSQL数据库实现的公共考试报名管理系统网站...

前 言随着社会的快速发展&#xff0c;体力不再是我们唯一的生存方式了&#xff0c;人们也越来越注重自身的文化素养&#xff0c;随之而来的也有许多成人考试&#xff0c;为已经步入社会的人提供一个再学习的机会。众所周知&#xff0c;作为学生&#xff0c;考试是我们必经的过程…

怎么查看网站用什么数据库服务器,怎么查看网站数据库服务器ip

怎么查看网站数据库服务器ip 内容精选换一换内网域名是指仅在VPC内生效的虚拟域名&#xff0c;无需购买和注册&#xff0c;无需备案。云解析服务提供的内网域名功能&#xff0c;可以让您在VPC中拥有权威DNS&#xff0c;且不会将您的DNS记录暴露给互联网&#xff0c;解析性能更高…

专利查询下载的几个网站

专利查询 a. Espacenet Patent search 网址&#xff1a;https://worldwide.espacenet.com/ b. Soopat专利搜索 网址&#xff1a;http://www.soopat.com/ c. 专利信息服务平台 网址&#xff1a;http://search.cnipr.com/ d. 佰腾网 网址&#xff1a;https://www.baiten.cn/…

Chrome禁用JavaScript复制网站内容

如何复制一个网站中的内容&#xff0c;例如打开360doc网站&#xff0c;选中内容复制会弹出需要登录账号才能复制内容。 如何才能复制选中的内容呢&#xff0c;下面在chrome中演示如何复制网站内容。 在chrome中如何操作可以直接复制呢。 第一步&#xff1a;在需要复制的页面…

忘记网站登录密码不要慌,一招拯救你

忘记网站登录密码不要慌&#xff0c;一招拯救你 有些朋友可能曾经有过这样的痛苦&#xff0c;忘记某个网站的密码&#xff0c;只好找回密码&#xff0c;但操作比较麻烦&#xff0c;更难过的是可能有些网站不能找回密码就更惨&#xff0c;只能一遍一遍的尝试&#xff0c;直到。。…

网站实现GNSS数据批量下载

作为一名双非高校硕士研究生&#xff0c;硕士期间主要从事GNSS这个大类方向的研究&#xff0c;目前面临毕业就业问题&#xff0c;所以正在考虑转码&#xff0c;为了给自己硕士研究方向画个句号同时为转码打下基础&#xff0c;最近开发了一个网站&#xff1a;www.gnssget.cn。这…

Chrome API获取登录网站的cookie信息

谷歌插件 chrome.cookies.getAll API获取登录网站的cookie信息代码实现效果图代码实现 <div class"layui-form-item"><label class"layui-form-label">链接:</label><div class"layui-input-block"><input type&quo…

selenium 通过chrome浏览器携带用户数据登录网站

selenium 携带用户数据chromedriver登录网站 1.在chrome浏览器数据Chrome://versin 会得到本地谷歌用户数据:如图 2.启动chromeDriver需要添加user_data_dir 目录&#xff0c;这里只写到User Data 目录。 option webdriver.ChromeOptions() user_data_dirrC:\Users\12501\Ap…

2 亿元网站的官司,让我们看到了大公司+高预算≠好产品

前情回顾&#xff1a;美国汽车租赁公司赫兹&#xff08;Hertz&#xff09;将一个数字化转型项目交给了顶级咨询公司埃森哲&#xff08;Accenture&#xff09;负责。结果耗时 2 年多&#xff0c;耗费 2 个多亿&#xff0c;连一个可用的网站或者 APP 都没有交付出来&#xff0c;还…

静态网站架构的演进和最佳实践

作者&#xff1a;CODING - 杨周 新冠肺炎期间&#xff0c;约翰霍普金斯大学开发的疫情地图网站单日 PV 达 10 亿次&#xff0c;查看源代码可以看出它是一个单页应用&#xff08;single-page application&#xff0c;缩写 SPA&#xff09;&#xff0c;JS 调用后端 API 返回动态数…

CODING 静态网站服务升级,快速、稳定、高拓展!

CODING 静态网站拥有强大的页面托管服务&#xff0c;目前已有数万开发者、设计师、产品经理、团队与企业使用 CODING 静态网站托管了他&#xff08;她&#xff09;们的个人网站、博客、企业与产品官网、在线文档等。CODING 静态网站上线运营多年来&#xff0c;由于复杂多变的网…

robots.txt配合google网站管理员工具进行快速删除google收录

新版google工具在【优化】栏目进行删除网址。 google网站管理员工具介绍 google的“网站管理员工具”&#xff0c;是非常强大的&#xff0c;如果你能够熟练的使用它&#xff0c;你的网站将得到不少的提高&#xff0c;这不仅限于google优化哦&#xff0c;还有助于对其它搜索引…

php mysql怎么上传_php网站如何上传数据库

php程序建站最麻烦的就是数据库&#xff0c;因为php必须用独立的数据库&#xff0c;许多新手在建设网站上传数据库经常出错&#xff0c;下面合肥PHP培训小编和大家分享&#xff1a;其实带有数据库的php文件和我们习惯了的html文件的上传是差不多的&#xff0c;就使用dreamwaver…

Github搭建个人网站并上传个人项目

1.Github搭建个人网站参考博客&#xff1a; http://blog.csdn.net/yuexianchang/article/details/53431703 自己的域名&#xff1a;www.lvxingyu.xyz 欢迎访问&#xff0c;不过模板是参考别人的&#xff0c;正在完善&#xff0c;不足之处请多指出&#xff0c;如有侵权&#xf…

设计一个简单的家乡网站

利用HTML和CSS 即可完成简单设计 整体思路&#xff1a;利用网页内链接跳转到不同页面&#xff0c;index.html是主页面&#xff0c;分有几个小部分的页面&#xff0c;可以根据设计者需要安排不同主题的内容&#xff0c;然后实现跳转即可。整体代码用到的都是比较常用的标签例如列…

能爬旅游景点数据的知名网站_某知名网站公布年度数据,十大吸金主播斗鱼独占前四,小团团终成“女幻神”,339斩获一哥...

转眼间斗鱼直播平台又陪伴大家度过了愉快的一年&#xff0c;如今回顾整个2019年&#xff0c;我们收获了很多快乐&#xff0c;与此同时创下无数个记录&#xff01;比如在知名数据网站“头榜”近日发布的“2019头榜星势力直播风云人物”里&#xff0c;多位斗鱼主播均有所斩获&…

网络请求可以返回数据的网站_互联网大数据在门户网站、网络推广方面的应用...

社会经济的快速发展&#xff0c;人们生活之中沟通交流方式发生了很大的变化&#xff0c;从传统的信封交流到如今的手机交流&#xff0c;互联网的快速发展&#xff0c;给人们提供了一个良好的互动平台&#xff0c;人们可以借助互联网终端设备进行自由的交流、沟通&#xff0c;互…

大型网站架构

从网站架构的性能、可用性、伸缩性、扩展性、安全等指标出发&#xff0c;以思维导图的形式发散网站架构需要的技术和架构&#xff0c;有补充的请留言回复~