北航国家精品课程嵌入式系统Experiment4Linux设备驱动程序设计PPT资料.ppt
- 文档编号:8694806
- 上传时间:2023-05-13
- 格式:PPT
- 页数:28
- 大小:313.50KB
北航国家精品课程嵌入式系统Experiment4Linux设备驱动程序设计PPT资料.ppt
《北航国家精品课程嵌入式系统Experiment4Linux设备驱动程序设计PPT资料.ppt》由会员分享,可在线阅读,更多相关《北航国家精品课程嵌入式系统Experiment4Linux设备驱动程序设计PPT资料.ppt(28页珍藏版)》请在冰点文库上搜索。
一般将主设备建立一个目录,再将具体的子设备文件建立在此目录下。
例如,/dev/mtdblock0,基本概念,驱动程序使用的2个重要结构structfilestructfile_operations,基本概念,structfile,基本概念,structfile数据结构定义位于include/fs.hstructfile结构与驱动相关的成员mode_tf_mode标识文件的读写权限loff_tf_pos当前读写位置unsignedint_f_flag文件标志,主要进行阻塞/非阻塞型操作时检查structfile_operation*f_op文件操作的结构指针void*private_data驱动程序一般将它指向已经分配的数据structdentry*f_dentry文件对应的目录项结构,基本概念,设备驱动程序接口(structfile_operations),标记化方法:
staticstructfile_operationsdemo_fops=owner:
THIS_MODULE,write:
demo_write,read:
demo_read,ioctl:
demo_ioctl,open:
demo_open,release:
demo_release,;
基本概念,设备驱动程序接口(structfile_operations)通常所说的设备驱动程序接口是指structfile_operations,它的定义位于include/linux/fs.h中。
在嵌入式系统的开发中,通常只要实现如下几个接口函数就能完成系统所需要的功能init加载驱动程序时,内核自动调用read从设备中读取数据write向字符设备中写数据ioctl控制设备,实现除读写操作以外的其他控制命令open打开设备并进行初始化release关闭设备并释放资源exit卸载驱动程序时,内核自动调用,基本概念,驱动程序注册过程(动态分配主设备号)insmodmodule_name;
加载驱动程序,运行init函数(register_chrdev(dev_Major,“module_name”,*fs)查看/proc/devicesmknod/dev/module_namec/b主设备号次设备号rmmodmodule_name;
卸载驱动,运行exit函数(unregister_chrdev(dev_Major,“module_name”,*fs))用户程序调用Open(“/dev/module_name”,mode);
O_RDWRIoctl()Write()Read()Close(),开发驱动程序时须注意的事项,中断处理中断是现代微处理器的一个重要功能Linux驱动程序中的中断处理函数externintrequest_irq(unsignedintirq,void(*handler)(int,void*,structpt_regs*),unsignedlongflag,constchar*dev_name,void*dev_id);
/请求为中断号irq分配中断处理函数externvoidfree_irq(unsignedint,void*);
/释放中断注意事项不能向用户空间发送或者接收数据不能执行有睡眠操作的函数不能调用调度函数谨慎使用全局变量(可重入)自旋锁的使用,基本概念,字符设备的管理驱动程序模块通过函数intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops)完成向内核的注册,其中major是主设备号,name是设备名,fops是针对该设备的驱动程序的接口。
在系统中为驱动程序模块建立一个设备节点minjunRedHatAS$mknod/dev/democ2540其中/dev/demo标识设备名为demo,“c”说明是字符设备,254是指定的主设备号,0是次设备号,基本概念,驱动程序的编译以demo.c为例Makefile的形式参考实验指导书命令行的形式minjunRedHatAS$armv4l-unknown-linux-gcc-Wall-c-O-D_KERNEL_-I/home/minjun/embedded/kernel-2410s/includedemo.c-odemo.o加载驱动minjunRedHatAS$insmoddemo.o卸载驱动minjunRedHatAS$rmmoddemo.o,基本概念,测试程序实例/test.c#include#include#includeintmain()intfd;
fd=open(/dev/demo,O_RDWR);
if(fd0)exit(fd);
/yourcodehereread(fd,buffer,size);
write(fd,buffer,size);
.close(fd);
return0;
驱动程序的实现驱动程序框架,#include#include#include#include/*printk()*/#include/*everything.*/#include/*errorcodes*/#include/*size_t*/#include#include/*O_ACCMODE*/#include/*COPY_TO_USER*/#include/*cli(),*_flags*/#defineDEVICE_NAMEdemo#definedemo_MAJOR250#definedemo_MINOR0staticssize_tdemo_write(structfile*filp,constchar*buffer,size_tcount)copy_from_user(drv_buf,buffer,count);
WRI_LENGTH=count;
printk(userwritedatatodrivern);
/yourcodeherereturncount;
驱动程序的实现驱动程序框架,staticssize_tdemo_read(structfile*filp,char*buffer,size_tcount,loff_t*ppos)if(countMAX_BUF_LEN)count=MAX_BUF_LEN;
copy_to_user(buffer,drv_buf,count);
printk(userreaddatafromdrivern);
returncount;
staticintdemo_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)printk(ioctlruningn);
switch(cmd)case1:
printk(runingcommand1n);
break;
case2:
printk(runingcommand2n);
default:
printk(errorcmdnumbern);
staticintdemo_open(structinode*inode,structfile*file)MOD_INC_USE_COUNT;
sprintf(drv_buf,deviceopensucess!
n);
printk(deviceopensucess!
驱动程序的实现驱动程序框架,staticintdemo_release(structinode*inode,structfile*filp)MOD_DEC_USE_COUNT;
printk(devicereleasen);
staticint_initdemo_init(void)SET_MODULE_OWNER(,驱动程序的实现驱动程序框架,open提供给驱动程序初始化设备的能力,为后续的操作做准备此外一般会递增使用计数,防止文件关闭前模块被卸载通常情况下,open完成如下工作:
递增使用计数检查特定设备错误如果设备是首次打开,则对其进行初始化识别次设备号,如有必要,则修改f_op指针分配并填写filp-private_data中的数据release与open正好相反释放由open分配的filp-private_data中的数据在最后一次关闭操作时关闭设备使用计数减一,驱动程序的实现驱动程序框架,read和writeread将数据从内核拷贝到应用程序空间,write则将数据从应用程序空间拷贝到内核。
由于用户空间和内核空间的内存映射方式不同,所以在内核和用户空间传输数据的时候需要使用如下的函数unsignedlongcopy_to_user(void*to,constvoid*from,unsignedlongcount);
unsignedlongcopy_from_user(void*to,constvoid*from,unsignedlongcount);
在阻塞型IO中,read和write调用可能会出现阻塞read调用当前无数据可读,而又没有数据马上可读,这时会睡眠并且等待,write调用也会出现这样的情况等待队列机制wait_queue_head_t;
(定义在中)如果声明了等待队列并完成初始化,进程就可以睡眠,可以调用sleep_on的不同变体来完成睡眠(函数声明位于中)大多数情况下应使用“可中断”的函数,如interruptible_sleep_on。
睡眠进程被唤醒并不一定代表有数据,也有可能是被其他的信号唤醒,所以醒来后需要测试condition.,8段LED显示器外形原理图,一个数码管(LED)由一个8位的字节控制当该位为“1”时点亮,为“0”时灭,LED连接原理图,LED显示驱动器,ZLG7290I2CLED/键盘驱动器I2C串行接口提供键盘中断信号方便与处理器接口可驱动8位共阴数码管或64只独立LED和64个按键可控扫描位数可控任一数码管闪烁提供数据译码和循环移位段寻址等控制8个功能键可检测任一键的连击次数无需外接元件即直接驱LED可扩展驱动电流和驱动电压详细资料参加课程网站上的:
zlg7290.pdfzlg7290_led.pdf,图1ZLG7290引脚图,LED显示驱动器功能框图,IIC基地址是0x70有24个8位寄存器(0x00x17),通过IIC总线访问,必须是字节操作主要寄存器SystemReg0x0FlashOnOff0x0cScanNum0x0dDpRam070x10-0x17CmdBuf020x7-0x8两种控制方式:
-寄存器映象控制-命令解释控制参考zlg7290.pdf,LED驱动程序的主要函数,staticintled_write(structfile*filp,constchar*buffer,size_tcount,loff_t*ppos)staticintled_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)staticintled_open(structinode*inode,structfile*filp)staticintled_release(structinode*inode,structfile*filp)staticint_initled_init(void)staticvoid_exitled_exit(void)staticstructfile_operationsled_fops=owner:
THIS_MODULE,open:
led_open,release:
led_release,write:
led_write,ioctl:
led_ioctl,;
可以使用IIC_Write(charbaseAddr,charoffSet,chardata)来设置寄存器的值(字节操作),该函数在iic.h文件中定义。
LED测试应用程序框架,#include#include#include#include#includeintmain()intfd;
intret;
if(fd=open(/dev/led,O_RDWR)0)printf(openleddevicefailed!
exit(fd);
ioctl();
write();
close(fd);
下一次实验内容,内核驱动设计入门模块方式驱动程序(5.1)在PClinux和开发平台上运行通过内核驱动设计实验触摸屏驱动(5.2)写一个简单的应用程序,显示触摸位置的坐标(x,y)在开发平台上装载驱动程序,运行编写的测试应用程序开发一个LED(数码管)驱动程序,并编写一个应用程序对所开发的驱动程序进行测试(如果做不完,可以在下下次实验接着做)开发led_driver.c开发led_test.c,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北航 国家 精品课程 嵌入式 系统 Experiment4Linux 设备 驱动程序 设计