4412开发板android入门篇-字符设备驱动框架_第1页
4412开发板android入门篇-字符设备驱动框架_第2页
4412开发板android入门篇-字符设备驱动框架_第3页
4412开发板android入门篇-字符设备驱动框架_第4页
4412开发板android入门篇-字符设备驱动框架_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

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

文档简介

UT4412BV03起始板入门篇文字设备驱动程序框架的介绍本章的一部分见linux设备驱动详解第一部分是以前在学习linux设备驱动程序的细节时记录的字符设备的通用函数和结构,第二部分是以字符设备为模板写的LED驱动程序。linux驱动程序分为三种类型:字符设备、块设备和网络设备字符设备:字符设备以字节流进行访问,即,字符设备的读写操作以字节为单位,并且字符设备的操作函数通常是open、close、read、write等系统调用的函数。常用的串行等设备的数据传输也以字节为单位进行数据交换。块设备:在块设备上数据作为块存储,例如flash、SD卡等数据以页为单位被读写。 对SD卡、硬盘等块设备的读写,应用程序为open、open系统调用函数(如close、read、write )以任意字节读写块设备。网络设备:网络设备同时具有文字设备、块设备的特征、数据的读写有一定的格式,以套接字包方式进行数据的传送。创建设备驱动程序的一般步骤:1 .查看电路图硬件连接,查看控制设备数据手册,并知道kernel设备的操作函数组在kernel中找到类似的设备驱动程序副本。 一般来说,芯片制造商提供了相应芯片的驱动程序模板3 .实现驱动程序的初始化和在内核中的设备注册,创建设备节点4 .一组实现设备控制的操作函数,如通用系统调用函数open、close、read、write等。5 .将驱动程序编译到内核中6 .创建应用程序测试驱动程序。1 .字符设备的一般函数1 .加载和卸载驱动程序中的设备的函数module_init和module_exit在写入模块时这两个函数分别在insmod和rmmod时被调用。调用module_init函数在kernel中注册驱动程序,调用module_exit下载驱动程序。2.文字设备中常用的函数和结构1 .描述字符装置的结构cdevstruct cdev ;struct kobject kobj;结构模块* owner;const struct file_operations *ops;结构列表_头列表;dev_t dev; /设备编号unsigned int count;cdev结构的dev_t成员定义设备编号,该设备编号为32位,其中,高位12位是主设备编号,低位20位是子设备编号。使用以下宏从dev_t中获取主设备号和辅助设备号。MAJOR(dev_t dev )MINOR(dev_t dev )以下宏可以根据主设备号和设备号生成dev_t。MKDEV(int major,int minor )用于操作cdev结构的函数linux/fs/char_dev.c此函数初始化cdev结构的成员void cdev_init(struct cdev *cdev,conststructfile _ operations * fops )此函数向cdev结构请求内存struct cdev *cdev_alloc(void )此函数在内核中注册cdevint cdev_add(struct cdev *p,dev_t dev,unsigned count )此函数从内核中删除cdevvoid cdev_del(struct cdev *p )3 .设备编号的申请和释放函数对一个字符驱动一个或多个设备号来使用intregister _ chrdev _ region (dev _ to from、unsigned count、const char *name )参数: from :您分配的开始软元件编号,总是将值设为0count :您请求的连续设备编号的总数应该连接到此号码范围的设备的名称显示在/proc/devices和sysfs中返回值: 0返回成功,错误返回负值用于向系统动态申请设备编号未知且未使用的设备编号int alloc _ chrdev _ region (dev _ t * dev,未unsigned baseminor,未unsigned count,const char *name )角色:此函数必须传递最初分配的次编号baseminor (通常为0 )、分配的设备数count和设备名,调用此函数时,自动分配的设备编号会保存在dev中。baseminor:通常为0*dev:存储了返回的设备编号count:连续号码范围如果major为248,count为2,则意味着249相当于使用成功返回0,失败返回-1发行申请的设备编号。voi unregister _ chrdev _ region (dev _ to from,unsigned count )4.file_operations结构struct file_operations 结构模块* owner; /具有此结构的模块的指针通常是THIS_MODULES用于更改loff_t (*llseek) (struct file *、loff_t、int) /文件的当前读取/写入位置ssize_t (*读取) (结构文件*、char _user *、size _ t、loff_t *; /从设备同步读取数据ssize_t (*写入) (结构文件*、const char _user *、size _ t、loff_t *; /向设备发送数据ssize _ t (* AIO _ read ) (struct kiocb *,const struct iovec *,unsigned long,loff_t ); /初始化异步读取操作ssize _ t (* AIO _ write ) (struct kiocb *,const struct iovec *,unsigned long,loff_t ); /初始化异步写入仅用于读取int (*readdir) (struct file *、void *、filldir_t) /目录,对于设备文件,此字段为空unsigned int (*poll) (struct file *、struct poll_table_struct *; /轮询函数确定当前是否可以读取或写入非阻塞运行int (*ioctl) (struct inode *、struct file *、unsigned int、unsigned long) /设备I/O控制命令不使用long (* unlocked _ ioctl ) (struct file *、unsigned int、unsigned long) /blk文件系统,而使用此函数指针代替ioctl在long (* compat _ ioctl ) (struct file *、unsigned int、unsigned long) /64位系统中,32位的ioctl调用将由该函数指针替换结构文件*、结构VM _ area _ struct *; /用于将设备内存映射到进程地址空间的请求int (*打开) (结构节点*、结构文件*;int (* flush ) (结构文件*、fl_owner_t id )int (* release ) (结构节点*、结构文件*;int (*fsync) (struct file *、struct dentry *、int datasync) /更新要处理的数据int (*aio_fsync) (struct kiocb *,int datasync )int (*fasync) (int,struct file *,int) /异步fsync结构文件*、结构文件、结构文件_锁定*; /向设备通知设备FASYNC标志已更改ssize_t (* sendpage ) (结构文件*,结构页*,int,size _ t,loff_t *,int );无符号长(* get _ unmapped _ area ) (结构文件*,无符号长,无符号长,无符号长);int (*check_flags)(int )int (* flock ) (结构文件*、int、结构文件_ lock *;ssize_t (* splice _ write ) (struct pipe _ inode _ info *,struct file *,loff_t *,size _ t,unsigned int );ssize_t (* splice _ read ) (结构文件*,loff_t *,struct pipe_inode_info *,size _ t,unsigned int );int (* set lease ) (结构文件*,长,结构文件_ lock * * );llseek ()函数更改文件的当前读取和写入位置,并返回新位置。 如果发生错误,此函数返回负值。read ()函数用于从设备读取数据,如果成功,则返回读取的字节数,如果发生错误,则返回负值。write ()函数向设备发送数据,并返回成功时写入的字节数。 如果此函数没有实现如果用户调用write ()系统,则返回-EINVAL的返回值。readdir ()函数仅用于目录,不需要设备节点实现。ioctl ()提供与设备相关的控制命令的实现(既不是读操作也不是写操作),在调用成功时向调用方返回非负值。 内核本身识别一些控制命令,而无需调用设备驱动程序中的我是ioctl ()。 如果设备没有提供ioctl ()函数,则用户对内核无法识别的命令执行ioctl ()系统调用获取-EINVAL的返回值。mmap ()函数将设备内存映射到进程内存,如果设备驱动程序未实现此函数,则由用户输入mmap ()行在系统调用时获取-enovo的返回值。 此函数对帧缓冲区等设备特别有意识义。poll ()函数通常用于查询设备是否能以非阻塞方式立即读写。 如果没有触发查询条件,则用户空间执行select ()和poll ()系统调用会阻止进程aio_read ()和aio_write ()函数分别异步读取和写入与文件描述符对应的设备。 机器实现这两个函数后用户空间可以读写设备文件描述符调用aio_read ()、aio_write ()等系统调用5.copy_from_user ()和copy_to_user ()的原型如下所示因为内核空间和用户空间的内存不能直接相互访问,所以使用函数copy_from_user ()完成用户空间和内核空间的复制函数copy_to_user ()完成从内核空间到用户空间的复制。无符号长复制_ from _ user (void * to,const void _user *from,无符号长计数);无符号长复制_ to _ user (void _ _ user * to,const void *from,无符号长计数);上述函数返回无法复制的字节数。 因此,如果完全复制成功,返回值为0。如果要复制的内存为char、int、long等简单类型,则可以使用简单的put_user ()和get_user ()如下所示PPS; /内核空间整数变量get_user(val,(int *) arg) /用户空间到内核空间,arg是用户空间的地址put_user(val,(int *) arg) /从内核空间到用户空间,arg是用户空间的地址以下第二部分:第一部分介绍字符设备驱动的常用函数,并创建基于UT4412BV03开发板控制LED的驱动程序。 在字符设备中,驱动器的创建实质上

温馨提示

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

评论

0/150

提交评论