- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
基于linux的led驱动程序实现
基于linux的led驱动程序实现
一. 博创开发平台硬件LED的实现
平台设置了3个GPIO控制的LED和一个可直接产生外部硬件中断的按键,LED分别使用了S3C2410的GPC5GPC6,GPC7三个GPIO,按键接到INT5中断。下面对S3C2410 PIO的各个寄存器作出说明,用GPIO控制的LED就是通过操作GPIO的各个寄存器进行配置和操作的。S3C2410包含GPA 、GPB 、……、GPH 八个I/O端口。它们的寄存器是相似的:GPxCON用于设置端口功能(00 表示输入、01表示输出、10 表示特殊功能、11 保留不用),GPxDAT 用于读/写数据,GPxUP 用于决定是否使用内部上拉电阻(某位为0 时,相应引脚无内部上拉;为1时,相应引脚使用内部上拉)
。这里要稍微注意一点的地方是PORTA和其他几组端口的使用不太一样,这里不讨论A口,B到H组口的使用完全相同。是S3C2410手册上的数据:
图 S3C2410端口GPC口有16个IO口,查datasheet《S3C2410》所用的地址为:
图 C组GPIO的地址
即GPCCON 地址为0 GPCDAT地址为0各位的设置具体见下图,则对应的GPCCON寄存器的位为:
图 GPCCON寄存器相应的位
这里用到了5,6,7三个口,CON寄存器要完成对对应口的设置工作,将相应的口设置为输出状态,其他的口不用考虑,设置为输出的话就是 0x1510,这样3个IO口就设置为了输出。下面就可以通过向DATA口写入低电平来点亮LED,GPCDAT的各位分布如下,每一个bit对应一个口。
图GPCDAT的位分布
GPCDAT有16位,我们这里要用到的就是57三位即将这3位设置为低电平点亮LED。具体使用情况见驱动的实现。
这三个LED的硬件原理图如下:
图 GPIO控制的LED硬件原理图通过GPIO控制的LED驱动程序
本驱动中没有用到内核提供的write_gpio宏,对硬件地址的操作完全自己实现,可分为以下几部分:
① 模块的和退出:
int led_init(void)
{
int ret;
ret=register_chrdev(MAJOR_LED,NAME,leds_fops);
port_addr= (unsigned long )ioremap(00x8);
if(ret0)
goto fail;
printk(KERN_INFO NAMEinitialized!!\n);
return 0;
fail:
printk(NAMECan not register major number %d!!\n,MAJOR_LED);
unregister_chrdev(MAJOR_LED,NAME);
return ret;
}
void led_exit(void)
{
iounmap(port_addr);
printk(KERN_INFO NAMEquit!!\n);
unregister_chrdev(MAJOR_LED,NAME);
}
module_init(led_init);
module_exit(led_exit);
module_init和module_exit为内核提供的接口,以模块方式插入到内核中时内核首先要找的就是这两个宏,找到对应的初始函数这里为led_init初始化模块,和卸载函数这里为led_exit当模块撤出内核时调用。这两个函数名称可以自己定义,但是module_init这个两个宏的名字不能改变,并且led_init的返回值类型必须为int型,led_exit的返回类型必须为空。这两个函数只是告诉内核驱动模块在内核中了,但并不一定在使用它,而open和release是当设备被打开和关闭的时候才回被调用,模块不会退出内核。
初始化函数led_init中主要完成的工作为:注册设备号和文件操作结构;映射内存地址空间;做出一定的错误处理。设备注册的工作由register_chrdev来完成,如果返回值是负值表示错误,0或者返回值为正值表示操作成功,其中MAJOR_LED为静态申请的主设备号定义为#define MAJOR_LED 237,NAME为设备的名称定义为#define NAME leds,leds_fops为file_operations类结构体定义如下:
static struct file_operations leds_fops=
{
owner:THIS_MODULE,
open: led_open,
release:led_close,
ioctl: led_ioctl,
};
原创力文档


文档评论(0)