《深入浅出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 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |
你可能对下面的文章感兴趣
关于《深入浅出Linux设备驱动》第一章 设备驱动概述(3)的所有评论