广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
3.3 时钟
系统时钟是操作系统运行的基础,时钟驱动的修改需要首先完成。
3.4 串口驱动
3.4.1 概述
vxWorks的串行设备的驱动不同于一般的设备的驱动。一般的设备都是在系统初启的时候调用xxDrv()来安装DriverTable。然后,调用xxDevCreate来将该设备描述符xx_DEV加入到DeviceTable中。在应用层使用设备的时候,直接通过fd?device list?DriverTable的顺序调用相应的驱动函数即可。他们的层次关系是:应用?I/O system ??Driver。层次关系很明确。然而串行设备的层次关系就不完全是这样子的。基于许多因素的考虑,vxworks的串行设备的驱动分成了如图3.3所示的几层:
图3.3串行设备驱动代码的分层结构
从图中可以看出:系统中的串行设备驱动总共有3层。其中,usrConfig.c和ttyDrv(包括tyLib)提供了一些对串行设备的一些通用操作。sysSerial.c中一些对不同开发板(系统)中串行设备有关的一些数据结构进行初始化。所以,称之为Implementation specific code。最后,的xxDrv.c当然是包括了一些具体设备相关的驱动/操作。(比如读写数据,设置等)
包含了串行设备的系统的总体的一个模型:
图3.4 系统的模型
从图3.4看出串行设备的驱动xxDrv并不是直接和I/O system交互的。中间存在一个ttyDrv(包括tyLib)。实际上,在DriverTable中安装的不是xxDrv的函数而是ttyDrv/tyLib移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
11
广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
提供的函数。另外,Target Agent可以和xxDrv交换,方便系统的调试。
ttyDrv(包括tyLib):可以称之为一个虚拟的设备驱动。因为他只是介于I/O与底层的具体设备的driver之间,为系统提供的统一的串行设备的界面。另外,还可以调用具体硬件的管理驱动。总之,ttyDrv给系统提供的是一些通用的管理函数(缓冲管理,互斥等)。所以,ttyDrv往往就可以管理多个设备。图3.5表明ttyDrv在系统中的位置:
图3.5 ttyDrv在系统中的位置
xxDrv:给ttyDrv和target agent提供支持。具体的内容在下面叙述。 3.4.2 ttyDrv(包括tyLib)
从概述中知道ttyDrv(tyLib)是一个虚拟的驱动,既管理着和I/O的交互,又管理着和底层硬件驱动的交互。他在和I/O交换的时候所作的工作主要有: ? ? ? ? ? ? ? ?
I/O System requirements (such as adding entry inDriver Table and creating device descriptor andadding it to the system Device List)
Handling all I/O system entry routines, e.g. ttyOpen,ttyIoctl, tyRead, tyWrite. Manages selectLib calls
Manages command line editing (see ioctlfunctionality in tyLib man page) Manages data buffering
Manages task sychronization on full or empty buffers Manages mutual exclusion on buffers
其中,ttyDrv负责着ttyOpen、ttyIoctl的接入,而tyLib负责着tyRead、tyWrite的接入。图3.6给出一个更加细致的系统的数据的流向图:
移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
12
广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
图3.6 ttyDrv的数据流图
从图中,系统的层次关系就很清楚了。应用层往往调用通用的ioLib中的函数read、write、ioCtrl等。这些函数从输入的fd中找到相应的设备描述符,然后找到了driver table。调用driver table中的函数。而driver table中的函数则是第二层的东西了(ttyDrv/tyLib(tyWrite、tyRead等))。ttyDrv/tyLib和真正的设备(xxDrv)打交道。第二层和底层的通讯是通过回调函数(callback)来实现。具体的说就是:ttyDrv提供两个函数负责输出时候底层驱动可以从buffer中的到数据,输入时候底层驱动可以将接受到的字符填入到buffer中。tyLib给提供的回调函数的格式如程序清单3.10:
程序清单3.10 tyLib 回调函数
STATUS tyIRd (
TY_DEV_ID pTyDev, /* ptr to tty device descriptor */ char inchar /*输入的缓存指针 */ ) STATUS tyITx (
TY_DEV_ID pTyDev, /* pointer to tty device descriptor */ char * pChar /* 从缓存中得到的字符 */ )
下面我们来对从上到下的各个函数进行说明:
1. ttyDrv()
他调用iosDrvInstall()将ttyDrv和tyLib中的函数安装的driver table中。此函数是在系统启动的时候由usrRoot()调用。此函数在不INCLUDE_TYCODRV_5_2即自动的被调用。
2. ttyDevCreat() 他主要完成如下的工作: ?
Allocates and initializes a device descriptor
移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
13
广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
? ? ? ? ? ? ?
Initializes tyLib by calling tyDevInit( ): selectLib initialization
Creates input and output ring buffers Creates semaphores
Calls iosDevAdd( ) to add the device to the device list
Installs tyLib routines as input and output callbacks(给底层的设备安装回调函数。) Starts the device in interrupt mode.
此函数也是在系统启动的时候由usrRoot()调用。 3. write( )? tyWrite( )? xxDrv
ttyDrv将tyWrite安装到了driver talbe中。然后,tyWrite就对所有的串行设备做同样的事情: ? ? ? ?
如果ring buffer满则阻塞
从用户的buffer中读数据到ring buffer中
在一定的情况下激活xxDrv开始传数据周期(一个传输周期首先传送数据到设备,等待设备给出一个中断来表示继续传送下一个数据)。 xxDrv用tyITx()来从输出ring buffer中读数据
4. read( )? tyRead( )? xxDrv
ttyDrv将tyRead安装到了driver talbe中。然后,tyRead就对所有的串行设备做同样的事情: ? ? ? ? ?
如果ring buffer空则阻塞
从ring buffer读数据到用户的buffer中 处理X-on/X-off
如果输入ring buffer中还有字符使所有的阻塞的进程启动
xxDrv用tyIRx()来将设备读到的字符写入到输入ring buffer中
5. ioctl()
ioctl将函数传递到xx ioctl(),如果设备驱动没有实现此功能,则将控制转移到tyIoctl。他们的关系如图3.7所示:
图3.7 ioctl控制的流向
总之,ttyDrv和tyLib之所以要独立称为一层可能主要是因为从代码可复用和统一界面两个角度来考虑的。代码可重用,是因为所有的串行设备都有一些同样的管理工作(缓存的管理,信号的管理等)。同样为了给I/O提供统一界面,ttyDrv在driver table中安装了统一的驱动函数。这样I/O和串行设备的交互就被屏蔽了。最后,图3.8给出一个ttyDrv和tyLib在系统中所做工作的概括图:
移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
14
广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
图3.8 ttyDrv和tyLib
3.4.3 xxDrv驱动的实现
要编写串行设备的驱动主要需要做以下几个方面的工作: ? ? ? ? ? ?
初始化:确定系统要支持的串行通道的个数 初始化设备的描述符 写设备的初始化代码 编写entry point函数
编写设备中断服务程序(ISR)
修改sysSerial.c文件(下一节介绍)
1. 初始化过程的概述
要编写设备的初始化代码,首先我们看看系统初始化的大概顺序,如图3.9:
图3.9系统初始化串行设备顺序
上图中sysSerialHwInit()是BSP中要编写的函数(sysSerial.c)。xxDevInit()在入口点函数中编写。SysSerialHwInit2()同样是在BSP中编写。有关sysSerial.c中的函数在下一节叙述。TtyDrv不用说了。而sysSerialChanGet()也是在sysSerial.c所提供的。
在这里,我们首先要做的就是根据具体的串行设备定义出自己的设备描述符xx_DEV结构。这也是编写串行设备驱动的第一步。 xx_DEV结构是加在device list中的所以他们和一个DRV_HEAD,然后包含这一些设备相关的成员将构成一个”设备“。对于串行设备这个移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
15
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库vxWorks_BSP移植笔记(4)在线全文阅读。
相关推荐: