浅谈linux驱动3linux系统下led驱动.docx

上传人:b****8 文档编号:10965587 上传时间:2023-02-24 格式:DOCX 页数:11 大小:478.58KB
下载 相关 举报
浅谈linux驱动3linux系统下led驱动.docx_第1页
第1页 / 共11页
浅谈linux驱动3linux系统下led驱动.docx_第2页
第2页 / 共11页
浅谈linux驱动3linux系统下led驱动.docx_第3页
第3页 / 共11页
浅谈linux驱动3linux系统下led驱动.docx_第4页
第4页 / 共11页
浅谈linux驱动3linux系统下led驱动.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

浅谈linux驱动3linux系统下led驱动.docx

《浅谈linux驱动3linux系统下led驱动.docx》由会员分享,可在线阅读,更多相关《浅谈linux驱动3linux系统下led驱动.docx(11页珍藏版)》请在冰豆网上搜索。

浅谈linux驱动3linux系统下led驱动.docx

浅谈linux驱动3linux系统下led驱动

浅谈linux驱动(3)-linux系统下led驱动2012年02月21日23:

13:

52

首先我提一下我过程中遇到的一些问题。

1.led驱动模块的编译

2.led驱动内核模块的安装

3.开发板nand的意外处理

4.当前linuxkerner版本与led内核模块版本的一致性

接下来我来谈谈具体我做的一个过程

看原理图之前我先略微的讲下什么上拉电阻下拉电阻,下面会用到

上拉是将不确定的信号通过一个电阻与电源相连,固定在高电平。

下拉是将不确定的信号通过一个电阻与地相连,固定在低电平。

上拉是对器件注入电流,下拉是对器件导出电流,当一个接有上拉电阻的I/O端口设置为输入状态的时候,它的常态为高电平,可用于检测低电平的输入。

首先看LED的原理图

从上面的原理图可以得知,LED与CPU引脚的连接方法如下,低电平点亮。

     LED1 -GPM0

     LED2-GPM1

     LED3 -GPM2

     LED4 -GPM3

s3c6410包含GPA,GPB,GPC......GPQ17组I/O端口,我这里也没有读完上s3c6410的datasheet,主要看了下led的寄存器的三个功能

 

GPMCON用来设置端口功能,(00表示输入,01表示输出,10表示特殊功能,11表示保留不用),GPMDAT用来读/写数据,GPMPUD用来决定是否内部使用上拉电阻,某位为0时,相应引脚无内部上拉,某位为1时候,相应引脚内部上拉)。

s3c6410_leds.c程序代码

//#include/*包涵内核中的多个头文件,以下头文件都是内核当中已经存在的*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#defineDEVICE_NAME"leds"/*定义设备名字为leds*/

#defineLED_MAJOR231/*定义led主设备号为231*/

staticunsignedlongled_table[]={

S3C64XX_GPM(0),

S3C64XX_GPM

(1),

S3C64XX_GPM

(2),

S3C64XX_GPM(3),

};

staticunsignedintled_cfg_table[]={

S3C64XX_GPM_OUTPUT(0),

S3C64XX_GPM_OUTPUT

(1),

S3C64XX_GPM_OUTPUT

(2),

S3C64XX_GPM_OUTPUT(3),

};

/*这里IOCTL的工作大概分两个步骤,定义命令,执行命令,但大家会发现这里并有defineIOCTL,但是我们会发现下面的case0,case1,这里其实是直接用定义为了数字,比如0表示灯灭,1表示灯亮*/

staticints3c6410_leds_ioctl(

structinode*inode,

structfile*file,

unsignedintcmd,

unsignedlongarg)

{

unsignedlongtmp;

switch(cmd){

case0:

case1:

if(arg>4){

return-EINVAL;

}

tmp=__raw_readl(S3C64XX_GPMDAT);

if(cmd)

tmp&=(~(1<

else

tmp|=(1<

__raw_writel(tmp,S3C64XX_GPMDAT);

//gpio_set_value(led_table[arg],!

cmd);

return0;

default:

return-EINVAL;

}

}

/*structfile_operations函数来定义我们能进行哪些操作,比如IOCTL*/

staticstructfile_operationss3c6410_leds_fops={

.owner=THIS_MODULE,

.ioctl=s3c6410_leds_ioctl,

};/*大家可以上去看一下s3c6410_leds_ioctl的定义*/

staticstructcdevcdev_leds;

structclass*my_class;

staticint__inits3c6410_leds_init(void)/*函数初始化,配置I/O口的模式*/

{

intret;

unsignedlongtmp;

inti;

dev_tdevno;

printk(KERN_NOTICE"enters3c6410_leds_init\n");

devno=MKDEV(LED_MAJOR,0);

ret=register_chrdev_region(devno,1,DEVICE_NAME);/*注册LED设备*/

ret=0;

if(ret<0)

{

printk(KERN_NOTICE"cannotregisterleddevice");

returnret;

}

cdev_init(&cdev_leds,&s3c6410_leds_fops);

cdev_leds.owner=THIS_MODULE;

ret=cdev_add(&cdev_leds,devno,1);

if(ret)

{

printk(KERN_NOTICE"cannotaddledsdevice");

returnret;

}

my_class=class_create(THIS_MODULE,"my_class");

if(IS_ERR(my_class))

{

printk("Err:

Failedincreatingclass\n");

return-1;

}

device_create(my_class,NULL,MKDEV(LED_MAJOR,0),NULL,DEVICE_NAME);

//gpm0-3pullup

tmp=__raw_readl(S3C64XX_GPMPUD);

tmp&=(~0xFF);

tmp|=0xaa;

__raw_writel(tmp,S3C64XX_GPMPUD);

//gpm0-3outputmode

tmp=__raw_readl(S3C64XX_GPMCON);

tmp&=(~0xFFFF);

tmp|=0x1111;

__raw_writel(tmp,S3C64XX_GPMCON);

//gpm0-3output0

tmp=__raw_readl(S3C64XX_GPMDAT);

tmp|=0x10;

__raw_writel(tmp,S3C64XX_GPMDAT);

//printk("S3C64XX_GPMCONis%x\n",__raw_readl(S3C64XX_GPMCON));

//printk("S3C64XX_GPMDATis%x\n",__raw_readl(S3C64XX_GPMDAT));

//printk("S3C64XX_GPMPUDis%x\n",__raw_readl(S3C64XX_GPMPUD));

printk(DEVICE_NAME"initialized\n");

return0;

}

staticvoid__exits3c6410_leds_exit(void)/*模块卸载函数,大家可以参考我前一篇《字符设备驱动》*/

{

cdev_del(&cdev_leds);/*删除字符设备结构体*/

unregister_chrdev_region(MKDEV(LED_MAJOR,0),1);/*释放设备号*/

printk(KERN_NOTICE"s3c6410_leds_exit\n");

}

module_init(s3c6410_leds_init);/*首先从这里开始分析,这里是驱动程序的初始化函数*/

module_exit(s3c6410_leds_exit);

MODULE_LICENSE("GPL");因为我这里不想直接编译进内核,所以采取内核模块加载的方式把led的内核模块加载进内核,那么我这里就要自己写一个简单的makefile

makefile这里相对来说还是比较简单的,这个可以当做一个模板,因为需要修改的仅仅是obj-m:

=s3c6410_leds.o我的C文件就是s3c6410_leds.c.还有就是修改KDIR的路径,改成当前内核源码的路径。

然后我make,结果出错了

我看了我下makefile是没问题的,但是看到出错信息里面提示的makefile的第一个字母M是大写Makefile,然后我改了下。

结果好了

接下来我用nfs共享目录来进行led驱动模块向内核进行加载结果是这样

不能加载,错误提示里面显示不能创建一个类然后我cat/proc/devices查看了下,我内核里原本已经有一个LED的驱动了

既然这样吧,我决定重新编译个内核,没有led驱动的内核,makemenuconfig里面在devicedrivers里面的char类驱动设备里面把led的驱动设置为M。

然后保存退出,编译,makezImage然后把新的内核烧到板子上去接下来再试试加载内核模块

好了,终于加载上去了。

这里有一个要注意的,你的LED内核模块版本和当前板子上跑的linux系统的内核的版本需要一致才行。

如图

这是查看的板子上linux内核的版本

这是查看的编译的LED驱动模块的版本OK,都是linux2.6.28.6.——————————————————————————————我早上细看了下内核配置,如图

选上这个应该就能解决不同版本的模块的问题了...但不知道是否会出现BUG。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 思想汇报心得体会

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1