嵌入式ppt课件.ppt
《嵌入式ppt课件.ppt》由会员分享,可在线阅读,更多相关《嵌入式ppt课件.ppt(46页珍藏版)》请在三一办公上搜索。
1、第6章 嵌入式Linux驱动程序开发,6.1 嵌入式Linux的设备管理,Linux将设备分成两大类:一类是块设备,类似磁盘以记录块或扇区为单位,成块进行输入/输出的设备;另一类是字符设备,类似键盘以字符为单位,逐个进行输入/输出的设备。网路设备是介于块设备和字符设备之间的一种特殊设备。块设备接口仅支持面向块的I/O操作,所有I/O操作都通过在内核地址空间中的I/O缓冲区进行,它可以支持随机存取的功能。文件系统通常都建立在块设备上。字符设备接口支持面向字符的I/O操作,由于它们不经过系统的快速缓存,所以它们负责管理自己的缓冲区结构。字符设备接口只支持顺序存取的功能,一般不能进行任意长度的I/O
2、请求,而是限制I/O请求的长度必须是设备要求的基本块长的倍数。处理器与设备间数据交换方式处理器与外设之间传输数据的控制方式通常有3种:查询方式、中断方式和直接内存存取(DMA)方式。1查询方式设备驱动程序通过设备的I/O端口空间,以及存储器空间完成数据的交换。例如,网卡一般将自己的内部寄存器映射为设备的I/O端口,而显示卡则利用大量的存储器空间作为视频信息的存储空间。利用这些地址空间,驱动程序可以向外设发送指定的操作指令。通常来讲,由于外设的操作耗时较长,因此,当处理器实际执行了操作指令之后,驱动程序可采用查询方式等待外设完成操作。驱动程序在提交命令之后,开始查询设备的状态寄存器,当状态寄存器
3、表明操作完成时,驱动程序可继续后续处理。查询方式的优点是硬件开销小,使用起来比较简单。但在此方式下,CPU要不断地查询外设的状态,当外设未准备好时,就只能循环等待,不能执行其他程序,这样就浪费了CPU的大量时间,降低了处理器的利用率。,2中断方式查询方式白白浪费了大量的处理器时间,而中断方式才是多任务操作系统中最有效利用处理器的方式。当CPU进行主程序操作时,外设的数据已存入端口的数据输入寄存器,或端口的数据输出寄存器已空,此时由外设通过接口电路向CPU发出中断请求信号。CPU在满足一定条件下,暂停执行当前正在执行的主程序,转入执行相应能够进行输入/输出操作的子程序,待输入/输出操作执行完毕之
4、后,CPU再返回并继续执行原来被中断的主程序。这样,CPU就避免了把大量时间耗费在等待、查询外设状态的操作上,使其工作效率得以大大提高。中断方式的原理示意图如图6.1所示。能够向CPU发出中断请求的设备或事件称为中断源。中断源向CPU发出中断请求,若优先级别最高,则CPU在满足一定的条件时,可中断当前程序的运行,保护好被中断的主程序的断点及现场信息,然后根据中断源提供的信息,找到中断服务子程序的入口地址,转去执行新的程序段,这就是中断响应。CPU响应中断是有条件的,如内部允许中断、中断未被屏蔽、当前指令执行完等。CPU响应中断以后,就会中止当前的程序,转去执行一个中断服务子程序,以完成为相应设
5、备的服务。系统引入中断机制后,CPU与外设处于“并行”工作状态,便于实现信息的实时处理和系统的故障处理。,3直接访问内存(DMA)方式利用中断,系统和设备之间可以通过设备驱动程序传送数据,但是,当传送的数据量很大时,因为中断处理上的延迟,利用中断方式的效率会大大降低。而直接内存访问(DMA)可以解决这一问题。DMA可允许设备和系统内存间在没有处理器参与的情况下传输大量数据。设备驱动程序在利用DMA之前,需要选择DMA通道并定义相关寄存器,以及数据的传输方向,即读取或写入,然后将设备设定为利用该DMA通道传输数据。设备完成设置之后,可以立即利用该DMA通道在设备和系统的内存之间传输数据,传输完毕
6、后产生中断以便通知驱动程序进行后续处理。在利用DMA进行数据传输的同时,处理器仍然可以继续执行指令。,设备驱动程序的概念,设备驱动程序实际是处理和操作硬件控制器的软件,从本质上讲,是内核中具有最高特权级的、驻留内存的、可共享的底层硬件处理例程。驱动程序是内核的一部分,是操作系统内核与硬件设备的直接接口,驱动程序屏蔽了硬件的细节,完成以下功能: 对设备初始化和释放; 对设备进行管理,包括实时参数设置,以及提供对设备的操作接口; 读取应用程序传送给设备文件的数据或者回送应用程序请求的数据; 检测和处理设备出现的错误。Linux操作系统将所有的设备全部看成文件,并通过文件的操作界面进行操作。对用户程
7、序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说,是把设备映射为一个特殊的设备文件,用户程序可以像对其他文件一样对此设备文件进行操作。这意味着: 由于每一个设备至少由文件系统的一个文件代表,因而都有一个“文件名”。 应用程序通常可以通过系统调用open()打开设备文件,建立起与目标设备的连接。 打开了代表着目标设备的文件,即建立起与设备的连接后,可以通过read()、write()、ioctl()等常规的文件操作对目标设备进行操作。设备文件的属性由三部分信息组成:第一部分是文件的类型,第二部分是一个主设备号,第三部分是一个次设备号。其中类型和主设备号结合在一起
8、惟一地确定了设备文件驱动程序及其界面,而次设备号则说明目标设备是同类设备中的第几个。由于Linux 中将设备当做文件处理,所以对设备进行操作的调用格式与对文件的操作类似,主要包括open()、read()、write()、ioctl()、close()等。应用程序发出系统调用命令后,会从用户态转到核心态,通过内核将open()这样的系统调用转换成对物理设备的操作。,驱动程序结构,1自动配置和初始化子程序,用来检测所需驱动的硬件设备是否工作正常、对正常工作的设备及其相关驱动程序所需要的软件状态进行初始化。2服务于I/O请求的子程序,该子程序称为驱动程序的上半部。这部分程序在执行时,系统仍认为与进
9、行调用的进程属于同一个进程,只是由用户态变成了核心态,可以在其中调用sleep()等与进程运行环境有关的函数。3中断服务程序,又称为驱动程序的下半部,由Linux系统来接收硬件中断,再由系统调用中断服务子程序。在系统内部,I/O设备的存取通过一组固定的入口点来进行,入口点也可以理解为设备的句柄,就是对设备进行操作的基本函数。字符型设备驱动程序提供如下几个入口点: open入口点。打开设备准备I/O操作。对字符设备文件进行打开操作,都会调用设备的open入口点。open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等。如果设备是独占的,即同一时刻只能有一个程序访问此设备,则op
10、en子程序必须设置一些标志以表示设备处于忙状态。 close入口点。关闭一个设备。当最后一次使用设备完成后,调用close子程序。独占设备必须标记设备方可再次使用。 read入口点。从设备上读数据。对于有缓冲区的I/O操作,一般是从缓冲区里读数据。对字符设备文件进行读操作将调用read子程序。 write入口点。往设备上写数据。对于有缓冲区的I/O操作,一般是把数据写入缓冲区里。对字符设备文件进行写操作将调用write子程序。 ioctl入口点。执行读、写之外的操作。 select入口点。检查设备,看数据是否可读或设备是否可用于写数据。select系统调用在检查与设备文件相关的文件描述符时使用
11、select入口点。,struct file_operations struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char *, size_t, loff_t *);ssize_t (*write) (struct file *, const char *, size_t, loff_t *);int (*readdir) (struct file *, void *, filldir_t);unsigned int (*poll) (stru
12、ct file *, struct poll_table_struct *);int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);int (*open) (struct inode *, struct file *);int (*flush) (struct file *);int (*release) (struct inode *, struct file *);int (*fsync) (
13、struct file *, struct dentry *, int datasync);int (*fasync) (int, struct file *, int);int (*lock) (struct file *, int, struct file_lock *);ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
14、ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);unsigned long (*get_unmapped_area)(struct file *,unsigned long, unsigned long, unsigned long, unsigned long); lseek,移动文件指针的位置,只能用于可以随机存取的设备。 read,进行读操作,buf为存放读取结果的缓冲区,count为所要读取的数据长度。 write,进行写操作,与read类似。 select,进行选择操作。 i
15、octl,进行读、写以外的其他操作。 mmap,用于把设备的内容映射到地址空间,一般只有块设备驱动程序使用。 open,打开设备进行I/O操作。返回0表示成功,返回负数表示失败。 release,即close 操作。,struct inode称做索引节点数据结构,定义如下:struct inode struct list_headi_hash;struct list_headi_list;struct list_headi_dentry;struct list_headi_dirty_buffers;struct list_headi_dirty_data_buffers;unsigned l
16、ongi_ino;atomic_ti_count;kdev_ti_dev;umode_ti_mode;nlink_ti_nlink;uid_ti_uid;gid_ti_gid;kdev_ti_rdev;loff_ti_size;time_ti_atime;time_ti_mtime;time_ti_ctime;unsigned inti_blkbits;unsigned longi_blksize;unsigned longi_blocks;unsigned longi_version;struct semaphorei_sem;struct semaphorei_zombie;struct
17、inode_operations*i_op;struct file_operations*i_fop;struct super_block*i_sb;wait_queue_head_ti_wait;struct file_lock*i_flock;struct address_space*i_mapping;struct address_spacei_data;struct dquot*i_dquotMAXQUOTAS;struct list_headi_devices;struct pipe_inode_info*i_pipe;struct block_device*i_bdev;struc
18、t char_device*i_cdev;unsigned longi_dnotify_mask; struct dnotify_struct*i_dnotify; unsigned longi_state;unsigned inti_flags;unsigned chari_sock;atomic_ti_writecount;unsigned inti_attr_flags;,_u32i_generation;union struct minix_inode_infominix_i; struct ext2_inode_infoext2_i; struct ext3_inode_infoex
19、t3_i; struct hpfs_inode_infohpfs_i; struct ntfs_inode_infontfs_i; struct msdos_inode_infomsdos_i; struct umsdos_inode_infoumsdos_i; struct iso_inode_infoisofs_i; struct nfs_inode_infonfs_i; struct sysv_inode_infosysv_i; struct affs_inode_infoaffs_i; struct ufs_inode_infoufs_i; struct efs_inode_infoe
20、fs_i; struct romfs_inode_inforomfs_i; struct shmem_inode_infoshmem_i; struct coda_inode_infocoda_i; struct smb_inode_infosmbfs_i; struct hfs_inode_infohfs_i; struct adfs_inode_infoadfs_i; struct qnx4_inode_infoqnx4_i; struct reiserfs_inode_inforeiserfs_i; struct bfs_inode_infobfs_i; struct udf_inode
21、_infoudf_i; struct ncp_inode_infoncpfs_i; struct proc_inode_infoproc_i; struct socketsocket_i; struct usbdev_inode_info usbdev_i; struct jffs2_inode_infojffs2_i; void*generic_ip; u;,struct file主要用于与文件系统相关的设备驱动程序,可提供关于被打开的文件的信息,定义如下:struct file struct list_headf_list;struct dentry*f_dentry;struct vfs
22、mount *f_vfsmnt;struct file_operations*f_op;atomic_tf_count;unsigned int f_flags;mode_tf_mode;loff_tf_pos;unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;struct fown_structf_owner;unsigned intf_uid, f_gid;intf_error;unsigned longf_version;/* needed for tty driver, and maybe others */void*p
23、rivate_data;/* preallocated helper kiobuf to speedup O_DIRECT */struct kiobuf*f_iobuf;longf_iobuf_lock;在用户自己的驱动程序中,首先要根据驱动程序的功能,完成file_operations结构中函数的实现。不需要的函数接口可以直接在file_operations结构中初始化为NULL。file_operations中的变量会在驱动程序初始化时,注册到系统内部。每个进程对设备的操作,都会根据主次设备号,转换成对file_operations结构的访问。,6.2 设备驱动程序的开发过程,由于嵌入式
24、设备由于硬件种类非常丰富,在默认的内核发布版中不一定包括所有驱动程序。所以进行嵌入式Linux系统的开发,很大的工作量是为各种设备编写驱动程序。除非系统不使用操作系统,程序直接操纵硬件。嵌入式Linux系统驱动程序开发与普通Linux开发没有区别。可以在硬件生产厂家或者Internet上寻找驱动程序,也可以根据相近的硬件驱动程序来改写,这样可以加快开发速度。实现一个嵌入式Linux设备驱动的大致流程如下。(1)查看原理图,理解设备的工作原理。一般嵌入式处理器的生产商提供参考电路,也可以根据需要自行设计。(2)定义设备号。设备由一个主设备号和一个次设备号来标识。主设备号惟一标识了设备类型,即设备
25、驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设备驱动程序解释,区分被一个设备驱动控制下的某个独立的设备。(3)实现初始化函数。在驱动程序中实现驱动的注册和卸载。(4)设计所要实现的文件操作,定义file_operations结构。(5)实现所需的文件操作调用,如read、write等。(6)实现中断服务,并用request_irq向内核注册,中断并不是每个设备驱动所必需的。(7)编译该驱动程序到内核中,或者用insmod命令加载模块。(8)测试该设备,编写应用程序,对驱动程序进行测试。,模块化驱动程序设计,在探讨模块之前,有必要先看一看内核模块与应用程序之间的区别。一个
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式 ppt 课件

链接地址:https://www.31ppt.com/p-1413643.html