(完整)VxWorks驱动开发笔记

上传人:雨水 文档编号:148400298 上传时间:2020-10-19 格式:PDF 页数:295 大小:15.23MB
返回 下载 相关 举报
(完整)VxWorks驱动开发笔记_第1页
第1页 / 共295页
(完整)VxWorks驱动开发笔记_第2页
第2页 / 共295页
(完整)VxWorks驱动开发笔记_第3页
第3页 / 共295页
亲,该文档总共295页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《(完整)VxWorks驱动开发笔记》由会员分享,可在线阅读,更多相关《(完整)VxWorks驱动开发笔记(295页珍藏版)》请在金锄头文库上搜索。

1、VxWorks驱动开发笔记 普通应用软件的开发,客户都会提出很明确的需求如功能、用户界面、外部接口以及开发周期经费等等要求,这 些要求一般都相对直观且容易理解。但是对于驱动程序的开发开说,开发周期以及经费这些需求往往都比较容易理解, 可是对于功能、用户界面以及外部接口等需求就很难描述了,因为这需要对底层操作系统的理解,否则就无法提出适宜 的需求来,而对底层操作系统的理解才是驱动程序开发之所以困难的主要原因。 1.1 驱动程序的结构 驱动程序有两大基本特征:一是它实现了对硬件设备的访问( 最根本目的 ) ,二是它实现了一系列与硬件设备无关 的的访问接口。通过这些接口,上层软件在控制此类硬件设备时

2、无需对硬件进行详细的了解就可以进行访问,此外,当 硬件设备更换时,只需要修改设备驱动的硬件相关的部分,而上层软件无需做任何更改。这两个基本特征也正好决定了 驱动程序的主体结构。如图1.1 所示,图中的阴影部分为设备驱动程序。 图 1.1 驱动程序的结构 1.2 驱动程序的工作流程 不同设备在操作系统中完成的工作是不同的,但是就是工作流程来说,大致可以分为两个阶段。 第一个阶段是初始化阶段,在初始化阶段,驱动程序主要完成硬件以及设备驱动相关数据结构的初始化。 第二个阶段是硬件的访问阶段,根据设备工作模式的不同,可以分为中断模式和轮询模式,无论何种模式都可以 通过与硬件设备无关的通用接口进行硬件设

3、备的访问。 2.1 串口驱动原理 串口因为调试简单在许多数据量不大的场合依然较为流行,可以借助串口对目标机中操作系统的运行情况进行监 控等等。下图为Tornado 开发软件通过串口对目标机上运行的VxWorks操作系统进行监控的结构原理图。 图 2.1 Tornado 通过串口对 vxWorks 操作系统进行监控 设备的驱动程序分为与硬件相关部分和硬件无关部分,而硬件相关部分则负责具体的硬件实现,硬件无关部分实 现了一系列通用的数据接口,其中硬件无关部分实现是create 、remove、open、close 、read、write 、ioctl等 7 个通 用的函数接口。使用这7 个基本的函

4、数,不但能够访问串口,而且还能够对网络、磁盘文件等多类设备进行访问。 这 7个函数的原型在文件ioLib.c中进行定义。分别为: int creat(const char *name,int flag) :该函数创建了一个文件描述符fd。其中 name为一个抽象文件的文 件路径,这个抽象可以指硬盘上保存的一个文件,也可以是一个以字符串表示的一个设备,当文件描述符创建完毕后自 动以参数 flag打开该文件。 STATUS remove(const char *name):移除文件, name表明文件路径。 int open(const char *name,int flags,int mode)

5、;打开文件,准备访问。 name为文件路径 ,flags为打开 方式如只读、只写、读写以及不存在可创建等,mode为打开模式只有在NFS文件系统下才有效。打开成功后返回文件描 述符。 STATUS close(int fd) ;关闭文件。 fd 为文件描述符。 int read(int fd,char *buffer,size_t maxbytes) ;从文件描述符 fd 指定的文件中读取最多maxbytes 个字 节,保存在 buffer指定的位置。可能会由于文件长度的原因,实际读取的字节数小于maxbytes,函数返回实际读出的 字节数。 int write(int fd,char *bu

6、ffer,size_t nbytes) ;向文件描述符 fd 指定的文件中写入nbytes 个字节的数 据,原数据保存在 buffer只能的内存中。可能会由于buffer空间等原因,实际写入的字节数小于nbytes ,函数返回实 际写入的字节数。 int ioctl(int fd,int function,int arg) ;控制函数,主要用于设置或读取设备的工作方式等特性。 上述这 7 个通用接口,也就是串口驱动的一个最根本的需求,即通过这几个函数就可以实现对串口控制芯片i8250 的操 作。 而函数库 iosLib中则是上述各个接口的较为底层的实现。它首先根据访问设备类型的不同(普通磁盘文

7、件和硬件 设备)而将其分为两类,并用不同的数据结构描述,这里主要对结构DRV_ENTRY进行分析。如图 2.3 。 图 2.3 iosLib库提供的数据结构结构 数组 drvTable 的每个元素 drvTablei对应一类设备,因此其下表i 将是不同类型设备之间区分的一个重要的参 考。 由于 0通常表示无效,因此 drvTable0为空, 不代表任何设备。图 2.4 给出了 ioLib 提供的通用函数和结构DRV_ENTRY 的基本关系。图中的箭头表示调用关系,有调用者指向被调用者。 图 2.4 ioLib库与 iosLib库的内部关系 由于数组 drvTable 的每个元素 drvTabl

8、ei对应一类设备,如果要使用某一类设备中的一个,如系统中两个串口 的一个,就必须指明是哪个串口。在函数库ioLib中的 7 个通用函数中都有一个重要的参数name ,表明文件的路径或者 设备的名称,该名称具有唯一性,也就是一个name指向唯一一个文件或者唯一一个设备。下面要引入的数据结构是设 备描述符,如图2.5 所示,它在函数库iosLib中定义。 图 2.5 设备描述符 基本的设备描述符的数据结构为DEV_HDR,它描述了一些最为基本的信息, 数组 decTable 的下标 devnum和设备名 称 name ,该设备序号即是ioLib库中使用的文件描述符fd 。 综合起来设备描述符DRV

9、_HDR、结构 DRV_ENTRY以及 7个通用函数库的关系可以用图2.6 来描述。 图 2.6 DRV_HDR、DRV_ENTRY及通用接口之间的关系 上述通用接口可以满足网卡、 串口等外围设备的需要, 对于具体的外部设备, 则需要对图 2.6 所说的通用接口进行扩展, 如图 2.7 所示,这个扩展主要采用了两种手段,一是继承,即通过对结构DEV_HDR 进行继承得到如串口、终端以及网卡 等特殊类型的设备;而是多态,也就是对一个通用的接口,根据具体设备的不同而采取不同的函数。C不是面向对象语 言,没有明确的类、继承和多态的概念,但是可以灵活地使用C达到同样的目的。 图 2.7 通用接口通过多

10、态和继承得到扩展 图 2.8 则更为详细地描述了VxWorks操作系统对多个设备的管理。对每类设备的操作函数,系统创建了一个 DRV_ENTRY结构数组来描述,每个DRV_ENTRY结构变量对应一类设备的操作函数,对某类设备的具体操作方式的设置则 是通过设定 DRV_ENTRY结构变量中个函数指针来实现的; 对于同一类的设备,系统为其从 DEV_HDR 派生了一个数据结构, 而每个结构变量则是对应该类设备中的每一个具体的设备,不同的设备通过双向链表链接在一起。 图 2.8 VxWorks对系统中多个设备的管理结构 2.3 串口驱动程序函数库分析 为了进一步加深对IO 设备管理数据结构的理解,本

11、节将分别对函数库ioLib 、iosLib进行分析。 2.3.1 函数库 ioLib ioLib库为上层提供了 7 个基本的函数接口:creat(), remove(), open(), close(), read(), write()以及 ioctl()。上层用户只需要对这7 个函数进行操作就能够完成对硬件的访问。下面一次分析ioLib库中各个函数库的功 能。 1. int creat ( const char *name, int flag ) 该函数提供了一个与设备无关的通用接口,用于创建一个文件(可以是普通的磁盘文件也可以是抽象的设备文件), 该文件的路径为name ,创建完毕后自动打

12、开,打开的参数为flag 。该函数的正常返回值为文件描述符,否则将会返回 ERROR。 对照图 2.8 ,该函数根据设备的名称,从链表中找到该设备对应的设备号drmNum (该数值即为函数返回的文件描 述符),然后以此为下标就可以找到该类设备的de_create 函数指针,从而找到该设备的create 函数。 2. int open ( const char *name, int flags, int mode ) 该函数打开一个文件以方便进行读、写或者更新,打开后返回该文件的文件描述符。open() 函数的参数为文件名 以及访问方式: l O_RDONLY (0) 以只读方式打开 l O_W

13、RONLY (1) 以只写方式打开 l O_RDWR (2) 以读写方式打开 l O_CREAT (0 x0200) 如果文件不存在,就创建一个文件并打开。 3. LOCAL int ioCreateOrOpen ( const char *name, int flags, int mode, BOOL create ) 这个函数其实是函数create()和 open() 函数的实现主体。 create()和 open() 函数只是根据参数create 简单调用 函数 ioCreateOrOpen() 而已,真正的实现在函数ioCreateOrOpen() 中。 4. STATUS unlin

14、k ( char *name ) 该函数主要是和 posix 兼容,它的功能与remove完全相同。 5. STATUS remove ( const char *name ) 调用函数 iosDelete来删除文件。如果有符号链接,则需要沿着符号链接直接找到文件并删除。 6. STATUS close ( int fd ) 调用函数 ioClose 函数关闭文件。 7. int rename ( const char *oldname, const char *newname ) 修改文件名。 并不是所有的设备都支持重命名操作,比如通常的dosFS和 rt11FS 都是支持重命名操作的,而n

15、etDrv 和 nfsDrv 则不支持,因此在使用这个函数前需要明确设备是否支持重命名操作。 重命名操作主要通过调用函数ioctl (fd, FIORENAME, (int) newname) 完成。 注意:调用函数 ioctl (fd, FIORENAME, (int) newname) 重命名前需要先打开文件open() 。 8. int read ( int fd, char *buffer, size_t maxbytes ) 调用函数 iosRead 实现读操作, maxbytes 为读取的最大字节数, 读取之后存放在 buffer指定的地址空间, 不过可 能由于文件中字节数的限制等

16、因素,实际读取的字节数可能会小于maxbytes,因此需要在最终的返回值中返回实际读取 的字节数。 9. int write ( int fd, char *buffer, size_t nbytes ) 调用函数 iosWrite向指定的文件中写入数据, nbytes 为期望写入的字节数, 但是实际上可能会由于文件本身的限 制导致实际写入的字节数小于nbytes ,因此需要在返回值中记录实际写入的字节数。 10. int ioctl ( int fd, int function, int arg ) 直接调用函数 iosIoctl实现对文件的控制操作。 11. int lseek ( int fd, long offset, int whence ) 设定一个文件的读写指针,下次读写操作将从设定的位置开始。 参数 whence有三个数值: l SEEK_SET (0) 设定到相对于文件起始位置偏移offset位置。 l SEEK_CUR (1) 设定到当

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 中学教育 > 其它中学文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号