快速业务通道

《深入浅出Linux设备驱动》第一章 设备驱动概述(3)

作者 佚名技术 来源 Linux系统 浏览 发布时间 2012-05-16
1.5设备驱动Hello World:LED驱动
1.5.1无操作系统时的LED驱动
在嵌入式系统的设计中,LED一般直接由CPU的GPIO(通用可编程I/O口)控制.GPIO一般由两组寄存器控制,即一组控制寄存器和一组数据寄存器.控制寄存器可设置GPIO口的工作方式为输入还是输出.当引脚被设置为输出时,向数据寄存器的对应位写入1和0会分别在引脚上产生高电平和低电平;当引脚设置为输入时,读取数据寄存器的对应位可获得引脚上的电平为高还是低.
在本例子中,我们屏蔽具体CPU的差异,假设在GPIO_REG_CTRL物理地址处的控制寄存器处的第n位写入1可设置GPIO为输出,在地址GPIO_REG_DATA物理地址处的数据寄存器的第n位写入1或0可在引脚上产生高或低电平,则无操作系统的情况下,设备驱动为代码清单1-3.
代码清单1-3 无操作系统时的LED驱动
1 #define reg_gpio_ctrl *(volatile int *)(ToVirtual(GPIO_REG_CTRL))
2 #define reg_gpio_data *(volatile int *)(ToVirtual(GPIO_REG_DATA))
3 /*初始化LED*/
4 void LightInit(void)
5 {
6 reg_gpio_ctrl |= (1 << n); /*设置GPIO为输出*/
7 }
8
9 /*点亮LED*/
10 void LightOn(void)
11 {
12 reg_gpio_data |= (1 << n); /*在GPIO上输出高电平*/
13 }
14
15 /*熄灭LED*/
16 void LightOff(void)
17 {
18 reg_gpio_data &= ~(1 << n); /*在GPIO上输出低电平*/
19 }
上述程序中的LightInit()、LightOn()、LightOff()都直接作为驱动提供给应用程序的外部接口函数.程序中ToVirtual()的作用是当系统启动了硬件MMU之后,根据物理地址和虚拟地址的映射关系,将寄存器的物理地址转化为虚拟地址.
1.5.2 Linux下的LED驱动
当在Linux操作系统下编写对应于代码清单1-3的LED设备清单时,操作硬件的LightInit()、LightOn()、LightOff()这些函数仍然需要,但是,遵循Linux编程的命名习惯,重新将其命名为light_init()、light_on()、light_off().这些函数将被LED设备驱动中独立于设备的针对内核的接口进行调用,代码清单1-4给出了Linux下LED的驱动,此时读者并不需要能读懂这些代码.
代码清单1-4 Linux操作系统下LED的驱动
1 #include .../*包含内核中的多个头文件*/
2
3 /*设备结构体*/
4 struct light_dev
5 {
6 struct cdev cdev; /*字符设备cdev结构体*/
7 unsigned char vaule; /*LED亮时为1,熄灭时为0,用户可读写此值*/
8 };
9
10 struct light_dev *light_devp;
11 int light_major = LIGHT_MAJOR;
12
13 MODULE_AUTHOR("Song Baohua");
14 MODULE_LICENSE("Dual BSD/GPL");
15
16 /*打开和关闭函数*/
17 int light_open(struct inode *inode, struct file *filp)
18 {
19 struct light_dev *dev;
20 /* 获得设备结构体指针 */
21 dev = container_of(inode->i_cdev, struct light_dev, cdev);
22 /* 让设备结构体作为设备的私有信息 */
23 filp->private_data = dev;
24 return 0;
25 }
26 int light_release(struct inode *inode, struct file *filp)
27 {
28 return 0;
29 }
30
31 /*写设备:可以不需要 */
32 ssize_t light_read(struct file *filp, char __user *buf, size_t count,
33 loff_t*f_pos)
34 {
35 struct light_dev *dev = filp->private_data; /*获得设备结构体 */
36
37 if (copy_to_user(buf, &(dev->value), 1))
38 {
39 return - EFAULT;
40 }
41 return 1;
42 }
43
44 ssize_t light_write(struct file *filp, const char __user *buf, size_t count,
45 loff_t *f_pos)
46 {
47 struct light_dev *dev = filp->private_data;
48
49 if (copy_from_user(&(dev->value), buf, 1))
50 {
51 return - EFAULT;

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号