通过给外部设备编写驱动程序是一种有效的控制外设的方法。随着DSP的应用越来越广泛,DSP实时系统的日趋复杂及新技术的出现,DSP处理器所连接的外部设备也是种类繁多,各不相同,而每一个外设都需要一个特定的驱动程序来支持外设的正常工作,这就要为每一个外设编写驱动程序,这是一项十分繁杂的工作。如何能够使系统开发人员从这些编写繁杂的驱动程序工作中解脱出来,进而能够专心投入到应用程序的开发中呢
TI公司提出了基于DSP/BIOS的设备驱动模型,该模型分为两层:类驱动即与硬件不相关的层和微型驱动即与硬件相关的层。使用这种结构,应用程序只需调用类驱动的API函数,通过类驱动使用微型驱动,用微型驱动来控制外设。这种结构,将驱动程序合理分层,使得驱动程序模块化,可移植性、复用性大大增强,缩短了驱动程序的开发时间。
1 DSP/BIOS设备驱动模型工
1.1 类/微型驱动模型
DSP/BIOS是TI公司所设计开发的一个尺寸可裁剪的实时多任务操作系统内核,通过使用DSP/BIOS提供的丰富的内核服务,开发者能快速地创建满足实时性能要求的精细复杂的多任务应用程序。为了使开发设备驱动更加简单方便,提出了DSP/BIOS DeviceDriver Kit,定义了标准的设备驱动模型,一种将设备驱动分为与硬件无关和与硬件相关的双层结构,这样就使开发驱动程序不像以前那样复杂了,为开发者提供了便利。这两层结构称为“类/微型驱动模型,它们每一层都有各自通用的接口,所以相似设备驱动程序的主要部分可以复用,驱动代码的移植成为可能,使开发驱动的过程大大简化。
与硬件无关的层称为类驱动(Class Driver),它处在应用程序与微型驱动之间,提供对多线程I/O请求的串行化和同步,并且维护设备数据缓冲区,向上提供API接口供应用程序调用,向下通过适配层与微型驱动相连,实现API接口函数到微型驱动层的映射。
与硬件相关的层称为微型驱动(Mini-driver),它处在类驱动与芯片支持库(Chip Support Library)之间,对于类驱动的接口是统一的,即每一个微型驱动都为类驱动和DSP/BIOS设备驱动管理提供了标准接口。微型驱动采用芯片支持库(CSL)管理外围设备的寄存器、内存和中断资源。但由于硬件是千差万别的,所以微型驱动对底层硬件的操作是根据硬件的不同而不同的。对于完成同样功能的不同外设,只需稍加修改微型驱动,而不需重新编写驱动程序,就可以实现驱动程序的移植与复用,使驱动程序的开发过程大大简化。类/微型驱动模型结构如图1所示。
1.2 类驱动
通过将应用软件,驱动程序分层之后,可以看到,位于顶层的应用程序并不直接与微型驱动产生联系,而是通过类驱动与微型驱动连接。每一种类驱动向上层应用程序提供一个API接口,并且与微型驱动接口进行通信。
DSP/BIOS定义了三种类驱动:流输入输出模块(SIO),管道管理模块(PIP),通用输入输出模块(GIO)。其中,SIO和PIP分别需要使用适配器DIO和PIO来与微型驱动进行通信。SIO/DIO是基于流的I/O模型,使用异步方式来操作I/O,对于数据的读写、处理可以同时进行。PIP/PIO是基于管道的I/O模型,每个管道维护着一个被划分为多个大小相同的帧的缓冲区。GIO类驱动采用基于流的同步I/O数据传输模式,适合大流量数据的传输,更适合文件系统。与SIO/DIO和PIP/PIO不同,GIO包含内置的IOM(I/OManager输入输出管理)适配层,可以直接与微型驱动进行通信。
GIO模块与其他两个模块相比,有一个很重要的特性,就是可以扩展API函数支持新的应用领域,这样就实现了对GIO类驱动的扩展。这种可扩展API的特性正好可以用在视频驱动开发方面。例如这种扩展可以满足视频设备存储区的需要。另外,在提供了视频驱动和应用程序之间的视频数据同步机制之后,这种扩展也能够允许使用一个单独的调用来“交换”视频缓冲区。这种交换缓冲区的机制对于实时视频信号的采集与显示是十分重要的。所以,在视频驱动中,我们采用通用输入输出模块GIO。应用程序可以直接地调用GIO API函数和IOM微型驱动程序进行交互,这些GIO API就可以看作是类驱动。GIO类驱动接口如图2所示。
GIO_create会为一个特定的IOM通道实例创建一个GIO对象,这是类驱动使用微型驱动的第一步,首先创建对象及IOM通道,然后在此通道上进行数据传输工作。其结构体类型为GIO_Obj:
1.3 微型驱动 [p]
微型驱动主要通过一些函数来完成对外部设备的直接控制。只要微型驱动创建了规定的函数,应用程序就可以方便地通过DIO适配模块、PIo适配模块或(和)GIO类驱动调用。
例如:GIO_create被调用时,会运行mdCreate-Chan来创建一个通道。
这些微型驱动函数包括:mdBindDev/mdUBind-Dev(绑定/删除通道函数):在程序建立接口时调用,完成设备的初始化硬件设备/在程序结束时调用,卸载设备。mdCreateChan/mdDeleteChan(创建/删除通道):需要在应用程序与设备实例之间创建一个逻辑通信通道,用于交换驱动数据。应用程序可创建一个或多个逻辑通道,微型驱动用通道对象来代表这些通道。这两个函数就是用来分配和释放通道对象。mdSubmitChan(递交I/O请求):该函数处理传递给它的IOM_Pack-et结构体中的命令代码(cmd),根据命令代码,完成相应的处理或返回错误代码。ISR(服务设备中断并完成I/O操作):IOM微型驱动在中断的ISR中将以处理完的IOM_Packet请求出队,启动下一次传输或服务请求,调用类驱动的回调函数与应用程序进行同步,并返回出队的IOM_Packet。mdControlChan(控制设备):用来操作外部设备。
这些微型驱动的函数入口放在接口表(IOM_Fxns)中,供适配模块或GIO类驱动调用。
2 TMS320DM642视频驱动
下面以TMS320DM842芯片为例,介绍有关TMS320DM642视频采集与显示的驱动程序的开发。通过编写驱动程序,完成视频信号的实时采集与显示功能。TMS320DM642是TI公司推出的一款专门用于视频/图像处理的定点数字信号处理器,它基于C64x内核,带有3个可配置的视频端口,与视频采集芯片直接相连,无需外加逻辑电路或FIFO缓存,只需编写相关解编码芯片的驱动程序,就可以完成视频信号的采集与显示。在这里使用的解码、编码芯片分别为PHILIPS SAA7115和SAA7105。
2.1 视频类驱动
在视频驱动程序结构中,为了最大程度地提高视频驱动代码的复用性和通用性,将类驱动又划分为两层结构,其中上层为FVID模型,它是在DSP/BIOS GIO类驱动之上的简单封装,下层是GIO类驱动程序。GIO类驱动提供独立的、一般的API函数集并且为微型驱动提供广泛的服务,而上层的FVID模型向上层的视频采集、显示结构提供定制的API函数。
在视频驱动中,主要是通过调用FVID模块函数来完成类驱动代码的编写工作。FVID主要有以下几个API函数:FVID_create:分配并初始化通道对象;FVID_control:向微型驱动发送控制命令;FVID_al-loc:向应用程序分配视频端口缓冲区;FVID_ex-change:交换缓冲区;FVID_free:释放缓冲区;FVID_delete:删除通道对象。
在配备视频接口的设备驱动时,至少指定它要开设3个以上的视频缓冲区(FVID模型中,默认分配3个缓冲区),帧缓冲区通过FVID_alloc(),FVID_free(),FVID_exchange()三个函数在应用程序与驱动之间交换。
2.2 视频微型驱动
视频微型驱动也分为两层结构,上层为通用视频端口层部分,下层为指定编解码芯片微驱动层部分,它们通过外部设备控制接口(External Device Control,EDC)实现对外围芯片的操作。这种微驱动结构的好处是,当使用不同的芯片时,只需修改指定编解码芯片微驱动那一部分,不需将整个微驱动重新编写,使得驱动的复用性大大增强。
视频驱动程序模型如图3所示。
2.3 TMS320DM642视频驱动设计步骤
2.3.1 注册微型驱动
由于应用程序、类驱动最终都是要通过微型驱动的函数来完成对外部设备的直接控制,所以驱动程序设计的第一步就是要在DSP/BIOS Config中的Input/Output->Device Drivers->Uger-Defined Devices项目添加设备并注册微驱动,进行属性的设置,并指明IOM_Fxns函数表地址和设备参数地址,如图4所示。
DSP/BIOS会在内部维护一个“设备表”,其中包含User-Defined Devices对象进行配置的设备实例。
2.3.2 编写类驱动代码
FVID函数会在设备表中查找已注册的微驱动,并调用微驱动函数完成对外部设备的操作控制。 [p]
通常,首先利用FVID_create函数完成分配并初始化通道对象,返回值为设备实例句柄,这个句柄用于后续其他FVID函数调用这个已经创建的通道。然后调用FVID_control函数向微型驱动发送控制命令,如配置编解码器,发送开始采集或显示图像的控制命令。然后利用FVID_alloc分配缓冲区,接着应用程序将缓冲区的数据进行复制的搬移工作,当应用程序完成对缓冲区数据的采集后,调用FVID_exchange来交换缓冲区,保证视频数据能够实时地、源源不断地供应用程序使用。
过程的流程图如图5所示。
下面是简单的视频采集显示驱动的部分实现代码:
3 结 语
本文介绍了基于TI公司的类/微型驱动模型进行视频驱动设计的原理及主要方法,利用这两层的驱动模型不仅简化了驱动程序的编写过程,缩短了开发时间,而且使代码的复用性和可移植性大大提高,稍加改动相应的底层接口就可以用于其他的DSP系统中,真正使视频驱动的开发过程得到简化。