设备驱动程序创新设计_第1页
设备驱动程序创新设计_第2页
设备驱动程序创新设计_第3页
设备驱动程序创新设计_第4页
设备驱动程序创新设计_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、设备驱动程序创新设计实验目的学习Linux下进行驱动程序设计的原理掌握Linux设备驱动程序开发的根本过程和设计方法实验内容内核驱动设计入门模块方式驱动程序5.1内核驱动设计实验触摸屏驱动5.2写一个简单的应用程序,显示触摸位置的坐标x,y开发一个LED数码管驱动程序,并编写一个应用程序对所开发的驱动程序进行测试大作业实验实现的功能是上电复位后,数码管显示数字0-7,然后每一个数字依次闪烁一次,小数点也要点亮,即: 0.1.2.3.4.5.6.7.Linux的设备驱动程序硬件设备与应用程序之间的一个中间软件层它使得某个特定硬件能够响应一个定义良好的内部编程接口,同时完全隐蔽了设备的工作细节用户

2、通过一组与具体设备无关的标准化的调用来完成相应的操作驱动程序的任务就是把这些标准化的系统调用映射到具体设备对于实际硬件的特定操作上驱动程序是内核的一局部,可以使用中断、DMA等操作驱动程序在用户态和内核态之间传递数据设备驱动程序的分类字符设备所有能够象字节流一样访问的设备都通过字符设备来实现它们被映射为文件系统中的节点,通常在/dev/目录下面一般要包含open read write close等系统调用的实现块设备通常是指诸如磁盘、内存、Flash等可以容纳文件系统的存储设备。块设备也是通过文件系统来访问,与字符设备的区别是:内核管理数据的方式不同它允许象字符设备一样以字节流的方式来访问,也

3、可一次传递任意多的字节。网络接口设备通常它指的是硬件设备,但有时也可能是一个软件设备(如回环接口loopback),它们由内核中网络子系统驱动,负责发送和接收数据包。它们的数据传送往往不是面向流的,因此很难将它们映射到一个文件系统的节点上。根本概念主设备号和次设备号主设备号和次设备号能够唯一地标识一个设备128V2.0以前), 256(V2.0以后)主设备号相同的设备使用相同的驱动程序,次设备号用于区分具体设备的实例动态获取主设备号Linux下对设备号的分配请参考Documentation/devices.txt设备文件 Linux使用设备文件来统一对设备的访问接口,将设备文件放在/dev/目

4、录下设备的命名一般为设备文件名+数字或者字母表示的子类,例如/dev/hda1, /dev/hda2等Linux 2.4以后引入了设备文件系统devfs的概念,所有的设备文件作为一个可以挂装的文件系统,这样就可以被文件系统统一管理,从而设备文件就可以挂装到任何需要的地方。一般将主设备建立一个目录,再将具体的子设备文件建立在此目录下。例如,/dev/mtdblock0根本概念驱动程序使用的2个重要结构struct filestruct file_operations根本概念struct file根本概念struct file数据结构定义位于include/fs.hstruct file结构与驱动

5、相关的成员mode_t f_mode标识文件的读写权限loff_t f_pos当前读写位置unsigned int_f_flag文件标志,主要进行阻塞/非阻塞型操作时检查struct file_operation * f_op 文件操作的结构指针void * private_data驱动程序一般将它指向已经分配的数据struct dentry* f_dentry 文件对应的目录项结构根本概念设备驱动程序接口( struct file_operations), 标记化方法:static struct file_operations demo_fops = owner: THIS_MODULE,w

6、rite: demo_write,read: demo_read,ioctl: demo_ioctl,open: demo_open,release: demo_release,;根本概念设备驱动程序接口 struct file_operations 通常所说的设备驱动程序接口是指struct file_operations ,它的定义位于include/linux/fs.h中。在嵌入式系统的开发中,通常只要实现如下几个接口函数就能完成系统所需要的功能init加载驱动程序时,内核自动调用read从设备中读取数据write向字符设备中写数据ioctl控制设备,实现除读写操作以外的其他控制命令op

7、en翻开设备并进行初始化release关闭设备并释放资源exit 卸载驱动程序时,内核自动调用根本概念驱动程序注册过程动态分配主设备号insmod module_name ;加载驱动程序,运行init函数(register_chrdev(dev_Major, “module_name, * fs )查看/proc/devicesmknod /dev/module_name c/b 主设备号 次设备号rmmod module_name ;卸载驱动,运行 exit函数unregister_chrdev(dev_Major, “module_name, * fs )用户程序调用Open(“/dev/

8、module_name, mode) ;O_RDWRIoctl()Write()Read()Close()开发驱动程序时须注意的事项中断处理中断是现代微处理器的一个重要功能Linux驱动程序中的中断处理函数extern int request_irq(unsigned int irq, void(*handler)(int, void*, struct pt_regs *), unsigned long flag, const char *dev_name, void *dev_id);/请求为中断号irq分配中断处理函数extern void free_irq(unsigned int, v

9、oid*);/释放中断 本卷须知不能向用户空间发送或者接收数据不能执行有睡眠操作的函数不能调用调度函数谨慎使用全局变量可重入自旋锁的使用根本概念字符设备的管理驱动程序模块通过函数int register_chrdev(unsigned int major, const char *name, struct file_operations *fops) 完成向内核的注册,其中major是主设备号,name是设备名,fops是针对该设备的驱动程序的接口。在系统中为驱动程序模块建立一个设备节点minjunRedHatAS $ mknod /dev/demo c 254 0其中/dev/demo标识设

10、备名为demo,“c说明是字符设备,254是指定的主设备号, 0是次设备号根本概念驱动程序的编译以demo.c为例Makefile的形式参考实验指导书命令行的形式minjunRedHatAS $ armv4l-unknown-linux-gcc -Wall -c -O -D_KERNEL_ -I/home/minjun/embedded/kernel-2410s/include demo.c -o demo.o加载驱动minjunRedHatAS $ insmod demo.o卸载驱动minjunRedHatAS $ rmmod demo.o根本概念测试程序实例/test.c#include#

11、include#includeint main()int fd;fd=open(/dev/demo, O_RDWR);if(fd 0)exit(fd);/your code hereread(fd, buffer, size);write(fd, buffer, size);.close(fd);return 0;驱动程序的实现驱动程序框架#include #include #include #include /* printk() */#include /* everything. */#include /* error codes */#include /* size_t */#inclu

12、de #include /* O_ACCMODE */#include /* COPY_TO_USER */#include /* cli(), *_flags */#define DEVICE_NAMEdemo#define demo_MAJOR 250#define demo_MINOR 0static ssize_t demo_write(struct file *filp,const char *buffer, size_t count) copy_from_user(drv_buf , buffer, count);WRI_LENGTH = count;printk(user wri

13、te data to drivern);/your code herereturn count;驱动程序的实现驱动程序框架static ssize_t demo_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)if(count MAX_BUF_LEN)count=MAX_BUF_LEN;copy_to_user(buffer, drv_buf,count);printk(user read data from drivern);return count;static int demo_ioctl(struct i

14、node *inode, struct file *file, unsigned int cmd, unsigned long arg)printk(ioctl runingn);switch(cmd)case 1:printk(runing command 1 n);break;case 2:printk(runing command 2 n);break;default:printk(error cmd numbern);break;return 0;static int demo_open(struct inode *inode, struct file *file)MOD_INC_US

15、E_COUNT;sprintf(drv_buf,device open sucess!n);printk(device open sucess!n);return 0;驱动程序的实现驱动程序框架static int demo_release(struct inode *inode, struct file *filp)MOD_DEC_USE_COUNT;printk(device releasen);return 0; static struct file_operations demo_fops = owner:THIS_MODULE,write:demo_write,read:demo_r

16、ead,ioctl:demo_ioctl,open:demo_open,release:demo_release,; static int _init demo_init(void) SET_MODULE_OWNER(&demo_fops); result = register_chrdev(demo_MAJOR, demo, &demo_fops); if (result private_data中的数据release与open正好相反释放由open分配的filp-private_data中的数据在最后一次关闭操作时关闭设备使用计数减一驱动程序的实现驱动程序框架read和writeread将

17、数据从内核拷贝到应用程序空间,write那么将数据从应用程序空间拷贝到内核。由于用户空间和内核空间的内存映射方式不同,所以在内核和用户空间传输数据的时候需要使用如下的函数unsigned long copy_to_user(void *to, const void* from, unsigned long count);unsigned long copy_from_user(void *to, const void *from, unsigned long count);在阻塞型IO中,read和write调用可能会出现阻塞read调用当前无数据可读,而又没有数据马上可读,这时会睡眠并且等待

18、,write调用也会出现这样的情况等待队列机制wait_queue_head_t;(定义在中)如果声明了等待队列并完成初始化,进程就可以睡眠,可以调用sleep_on的不同变体来完成睡眠(函数声明位于中)大多数情况下应使用“可中断的函数,如interruptible_sleep_on。睡眠进程被唤醒并不一定代表有数据,也有可能是被其他的信号唤醒,所以醒来后需要测试condition.8段LED显示器外形原理图 一个数码管LED由一个8位的字节控制当该位为“1时点亮,为“0时灭acbdefhgLED连接原理图LED显示驱动器ZLG7290 I2C LED/键盘 驱动器I2C 串行接口提供键盘中断

19、信号方便与处理器接口可驱动8 位共阴数码管或64 只独立LED 和64 个按键可控扫描位数可控任一数码管闪烁提供数据译码和循环移位段寻址等控制8 个功能键可检测任一键的连击次数无需外接元件即直接驱LED 可扩展驱动电流和驱动电压详细资料参加课程网站上的:zlg7290.pdfzlg7290_led.pdf图1 ZLG7290引脚图LED显示驱动器功能框图IIC基地址是0 x70有24个8位存放器0 x00 x17,通过IIC总线访问,必须是字节操作主要存放器 SystemReg 0 x0 FlashOnOff 0 x0c ScanNum 0 x0d DpRam07 0 x10-0 x17 Cm

20、dBuf01 0 x7-0 x8两种控制方式:-存放器映象控制-命令解释控制参考zlg7290.pdfLED驱动程序的主要函数static int led_write(struct file* filp, const char* buffer, size_t count, loff_t* ppos) static int led_ioctl(struct inode *inode, struct file*file, unsigned int cmd, unsigned long arg) static int led_open(struct inode* inode, struct file

21、* filp) static int led_release(struct inode* inode, struct file* filp) static int _init led_init(void) static void _exit led_exit(void) static struct file_operations led_fops = owner:THIS_MODULE,open:led_open,release:led_release,write:led_write,ioctl:led_ioctl,;可以使用IIC_Write(char baseAddr, char offS

22、et, char data)来设置存放器的值字节操作,该函数在iic.h文件中定义。LED测试应用程序框架#include #include #include #include #include int main()int fd;int ret;if(fd=open(/dev/led, O_RDWR) 0)printf(open led device failed!n);exit(fd);ioctl(int fd, int cmd,); write(int fd, char* buf, int length);close(fd);return 0;实验内容内核驱动设计入门模块方式驱动程序5.1

23、在PC linux和开发平台上运行通过内核驱动设计实验触摸屏驱动5.2写一个简单的应用程序,显示触摸位置的坐标x,y在开发平台上装载驱动程序,运行编写的测试应用程序开发一个LED数码管驱动程序,并编写一个应用程序对所开发的驱动程序进行测试(如果做不完,可以在下下次实验接着做)开发led_driver.c开发led_test.c实验步骤-demo驱动程序阅读和理解源代码进入/arm2410s/exp/drivers/demo, 阅读理解源代码编译驱动模块修改Makefile文件, 编译实验平台运行的驱动程序测试驱动程序装载驱动程序和建立设备文件节点insmod demo.o mknod /dev/demo c 254 0编译测试程序并运行 a

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论