您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > 第11章-嵌入式Linux设备驱动程序-2
1第11章嵌入式Linux设备驱动程序211.4Linux设备驱动程序开发设备驱动程序开发流程(字符设备)模块化的驱动程序设计方式(字符设备)字符型设备驱动demo源程序分析LED驱动程序开发实例键盘驱动程序开发实例311.4.1设备驱动程序开发流程定义主、次设备号,也可以动态获取。通过file_operations结构定义设备所需的文件操作:所定义的文件操作对应的file_operations结构体函数指针,指向相应的设备操作函数(设备驱动程序的各个函数)实现设备驱动初始化函数---申请中断(如果有)、注册设备和退出函数—释放中断(如果有)、卸载设备。如果驱动程序采用模块方式,则要实现模块的初始化和退出函数。实现设备所需的文件操作:相应的设备操作函数(设备驱动程序的各个函数)实现实现中断服务程序(如果有)将驱动编译到内核。如果驱动程序采用模块方式,需先编译成模块,然后加载。411.4.2模块化的驱动程序设计方式模块机制“module”可以根据需要在不重新编译内核的情况下,将编译好的模块动态的插入运行中的内核,或者从运行中内核中将内核已经存在的一个模块移走。这种机制可以动态加载设备驱动程序到内核,为驱动程序开发调试提供了很大的方便在调试的过程中一般使用模块动态加载的方式,它的调试效率较高。当驱动调试完成后,在发行的过程就集成进内核。但编译进内核是某些驱动运行的唯一方法。例如:console驱动,flash驱动和对至少一种文件系统的支持等等511.4.2模块化的驱动程序设计方式用gcc编译成模块,要加上以下参数:-D__KERNEL__-DMODULE–I$(KERNELDIR_INCLUDE)在内核运行时,可以通过lsmod察看内核中已经动态加载的模块。而模块加载到内核和从内核中卸载可以通过以下命令实现,它们的操作对象xxxx是经过编译但没有链接的.ko文件(实际上就是.o文件,在2.4版本及之前不用.ko文件,直接就沿用为.o文件)insmodxxxx将编译的模块直接插入内核rmmodxxxx将编译的模块从内核中卸载611.4.2模块化的驱动程序设计方式以驱动程序源文件为demo.c为例驱动程序的编译(生成模块)gcc–c-D__KERNEL__-DMODULE-I/usr/src/linux-2.4/includedemo.c-odemo.ko加载驱动(模块):insmoddemo.ko卸载驱动(模块):rmmoddemo.ko对应的模块化驱动程序编程中,设备驱动程序源程序中必须至少提供两个宏:module_init(驱动程序初始化函数名):初始化模块的宏,在模块加载时调用module_exit(驱动程序退出函数名):卸载模块的宏,在模块卸载时调用711.4.2模块化的驱动程序设计方式例:一个简单的模块化设备驱动程序/*------------mdemo.c------------*/#defineMODULE#includelinux/module.hintinit_module(void){printk(\nhello,world!\n\n”);return0;}voidcleanup_module(void){printk(\nByeBye\n\n);}module_init(init_module);module_exit(cleanup_module);811.4.2模块化的驱动程序设计方式首先通过下面命令来编译源文件mdemo.c:gcc-c-D__KERNEL__-DMODULE-omdemo.komdemo.c在得到了mdemo.ko模块文件后,用insmod命令把它动态加载到内核:#insmodmdemo.ko#helloworld!#rmmodmdemo.ko#ByeByeinsmodrmmodmodule_init()module_exit()模块内核设备功能设备注册设备卸载用户调用9驱动程序与应用程序的区别设备驱动程序在Linux内核中以模块形式出现,与应用程序的执行过程不同,模块通常只是预先向内核注册自己,当内核需要时才被调用执行。insmodrmmodmodule_init()module_exit()模块内核设备功能设备注册设备卸载用户调用11.4.2模块化的驱动程序设计方式10驱动程序与应用程序的区别应用程序一般有一个main函数,从头到尾执行一个任务;驱动程序却不同,它没有main函数,因为它实际上只是在内核中可供调用的函数。应用程序可以和C函数库链接,因此可以包含标准的头文件,比如stdio.h、stdlib.h等;在驱动程序中是不能使用标准C库的,因此不能调用C库函数,只能调用内核函数。eg:比如输出打印函数只能使用内核的printk函数,包含的头文件只能是内核的头文件,比如linux/module.h11.4.2模块化的驱动程序设计方式11假设有一个简单的虚拟字符型设备设备名为“demo”设备中只有一个20个字节的缓冲区drv_buf(位于内核空间),对该设备的读写操作就是对缓冲区drv_buf的操作由于没有实际的硬件设备,故不需要驱动程序的下半部分,更加不需要采用中断方式实现11.4.3字符型设备驱动demo源程序分析12demo设备的驱动程序结构11.4.3字符型设备驱动demo源程序分析13/*头文件*/#includelinux/module.h#includelinux/init.h#includelinux/kernel.h/*printk()*/#includelinux/errno.h/*errorcodes*/#includelinux/sched.h/*定义主、次设备号*/#defineDEVICE_NAME“demo”/*设备名*/#definedemo_MINOR0/*定义次设备号*/staticintdemo_MAJOR0/*自动获取主设备号*///设备文件系统支持#ifdefCONFIG_DEVFS_FSstaticdevfs_handle_tdevfs_DbDemo_dir,devfs_DbDemoRaw;#endif/*定义虚拟字符型设备demo的内存数据结构*/#defineMAX_BUF_LEN20staticchardrv_buf[MAX_BUF_LEN];/*处于内核空间*/11.4.3字符型设备驱动demo源程序分析14/*函数声明*/staticintdemo_init(void);/*声明初始化函数*/staticvoiddemo_exit(void);/*声明退出函数*//*设备操作函数(设备驱动程序的各个函数)声明*/staticintdemo_open(structinode*inode,structfile*filp);staticintdemo_release(structinode*inode,structfile*filp);staticssize_tdemo_read(structfile*filp,char*buffer,size_tcount,loff_t*ppos);staticssize_tdemo_write(structfile*filp,constchar*buffer,size_tcount);staticintdemo_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg);11.4.3字符型设备驱动demo源程序分析15/*全局变量定义*//*通过file_operations结构定义设备所需的文件操作:指向相应的设备操作函数(设备驱动程序的各个函数)*/staticstructfile_operationsdemo_fops={#ifLINUX_KERNEL_VERSION=KERNEL_VERSION(2,4,0)owner:THIS_MODULE,#endifllseek:NULL,write:demo_write,read:demo_read,ioctl:demo_ioctl,open:demo_open,release:demo_release,};11.4.3字符型设备驱动demo源程序分析16/*实现初始化和退出函数*/staticintdemo_init(void){intresult;result=register_chrdev(demo_MAJOR,DEVICE_NAME,&demo_fops);if(result0)returnresult;demo_MAJOR=result;//创建设备文件(节点文件)---设备文件系统支持#ifdefCONFIG_DEVFS_FSdevfs_DbDemo_dir=devfs_mk_dir(NULL,DEVICE_NAME,NULL);devfs_DbDemoRaw=devfs_register(devfs_DbDemo_dir,0,DEVFS_FL_DEFAULT,demo_MAJOR,demo_MINOR,S_IFCHR|S_IRUSR|S_IWUSR,&s3c2410_fops,NULL);#endifprintk(DEVICE_NAME“initialized\n);return0;}11.4.3字符型设备驱动demo源程序分析demo_fops指向file_operations结构体变量17在LINUX2.4内核中引入了设备文件系统(devfs),它是文件系统的一部分。有了设备文件系统的支持,可以在设备驱动程序中自动创建设备文件(节点文件)。以前的Linux版本需要手工创建设备文件先给register_chrdev()传递0主设备号,以动态分配获得可用的主设备号后可在devfs_register()中指定次设备号devfs下,设备文件命名规则比以前的Linux版本也发生了变化,多创建了一层目录:主设备号建立一个设备目录,再将具体的设备实例建立在此目录下Eg:串口0设备为:/dev/tts/011.4.3字符型设备驱动demo源程序分析1811.4.3字符型设备驱动demo源程序分析devfs相关函数devfs_mk_dir函数,创建一个名为demo的设备文件目录(/dev/demo),并返回一个带有目录结构的数据结构变量devfs_DbDemo_dir。将该变量作为下一步devfs_register函数的参数。该参数在调用设备文件系统注册清除函数devfs_unregister时也要作为参数传入devfs_register函数在刚才创建的demo目录下再创建一个名为0的设备文件(节点文件)。该函数的参数中,DEVFS_FL_DEFAULT为该函数的标志选项,demo_MAJOR为注册字符设备时系统自动分配的主设备号,demo_MINOR为次设备号,S_IFCHR|S_IRUSR|S_IWUSR为默认的文件模式,&s3c2410_fops为传入内核的demo设备file_operations变量。该函数返回一个devfs_handle_t数据结构的变量devfs_DbDemoRaw。这在调用设备文件系统注册清除函数devfs_unregister时也要作为参数传入19/*实现退出函数*/staticvoiddemo_exit(void){//删除设备文件(节点文件)#ifdefCONFIG_DEVFS_FSdevfs_unregister(devfs_DbDemoRaw);devfs_unregister(devfs_DbDemo_dir);#endifunregister_chrdev(demo_MAJOR,DEVICE_NAME);printk(DEVICE_NAME“unloaded\n);}/*实现模块初始化和退出函数*/module_init(demo_init);module_exit(demo_exit);11.4.3字符型设备驱动
本文标题:第11章-嵌入式Linux设备驱动程序-2
链接地址:https://www.777doc.com/doc-8638048 .html