DSP/BIOS 设备驱动的结构和使用
1 设备驱动双层模型
随着DSP实时系统复杂性的提高及新技术的出现,外围设备的种类和数量也在增长。这些外围设备的设备驱动的编写和使用已经成为一种依赖于具体硬件和操作系统的必须的任务。有时为了满足一些系统的约束条件,如存储器空间、响应时间和功率管理等,这些设备驱动的开发又将成为一项艰巨的任务。
一种将设备驱动从机能上分为硬件无关层和硬件相关层的双层模型,为驱动开发者提供了很大便利。每层都使用各自通用的接口,这使得相似设备驱动程序的主要部分可以复用,简化了驱动的开发过程。这种设备驱动软件的分层称为“类/微型驱动模型”。
类驱动(class driver):类驱动一般提供对线程I/O请求的串行化和同步,另外还负责设备实例的管理。在典型的实时系统中,最多只需要几类必须的类驱动用于代表不同类型外围设备的驱动,其中包括异步I/O类、字符I/O类和视频类。
微型驱动(mini-driver):类驱动使用一个具体设备特有的微型驱动来对一个特定的设备进行应用程序软件所需要的操作。
微型驱动的开发者必须具有将一个特定设备有效地呈现给类驱动的能力,例如一个视频显示设备可能要拥有一个由应用程序分为其分配的帧缓冲区来有效的执行所需要的I/O操作。并且一个视频类驱动可能需要使用一系列不连续的帧缓冲区来代表一个发往微型驱动的I/O请求-这些不连续的帧缓冲区可能用于存放RGB或YUV分量-这样才能使下层的微型驱动能够有效地与视频硬件互动。
一个有效的驱动模型应该能够采用I/O请求包的形式来有效地代表一个发往微型驱动的I/O请求,即将请求信息包含在驱动开发者定义的一个架构体中。
1 应用程序结构概述
DSP/BIOS目前定义了三种类型的类驱动,分别是PIP/PIO、SIO/DIO和GIO。对于PIP/PIO和SIO/DIO类驱动,应用程序调用的API函数就是DSP/BIOS中现有的PIP/SIO函数,这些API与相应的适配器(PIO或DIO)进行交互,而适配器则直接与微型驱动进行通信。使用GIO类驱动时,应用程序则调用一套新的GIO/API函数直接与微型驱动通信。
在一个应用程序中可能同时存在多种类型的类驱动,应用程序开发者可以选择在一个系统中使用一种或是多种类型驱动。而类型驱动程序开发人员不必编写类驱动,每个微型驱动都提供一套标准的微型驱动接口函数,供类驱动使用以访问该外围设备,以及供DSP/BIOS使用来管理设备驱动。微型驱动利用芯片支持库CSL来访问外围设备寄存器、存储器和中断源。一些微型驱动还可以根据需要包含一个特有的子驱动。
2 设备实例和通道实例
双层设备驱动模型包括两种类型的对象实例:
设备实例:这是对于实际的外围设备(如一个音频codec或视频端口)的抽象。设备实例需要被注册到DSP/BIOS的设备表中。应用程序通过设备实例的逻辑名称来引用它们。如果配置了多个设备实例,那么在设备表中每一个实例都具有一个唯一的逻辑名称。
通道实例:这是对应用程序与设备实例之间通信路径的抽象。通过调用微型驱动的mdCreateChan函数可以创建通道实例。
2设备驱动数据流
1. 通道实例句柄
在应用程序和设备之间的通信开始之前,应用程序必须得到一个由微型驱动的mdCreateChan函数返回的通道实例句柄。
根据应用程序所使用的类驱动,一个通道句柄所指向的通道实例可以代表一个点到点的数据传输流(SIO)或管道(PIP)。不管是那种情况,通道实例句柄都代表了应用程序与微型驱动之间唯一的一条通信路近,所有后续和该驱动的交互操作都会使用到这个通道句柄。
每个通道实例占用的资源数量(如存储器空间)取决于微型驱动以及适配器对该通道的实现方式。一个通道对象通常会维护一些与通道模式、I/O请求队列和驱动状态信息有关的数据域。因此每个通道实例所需存储空间的总量会由于适配器以及微型驱动实现方式的不同而有所不同。
3 类驱动概述
DSP/BIOS支持两种数据传送模型:一种是由SIO模块实现的流传输模型,另一种是由PIP模块实现的管道模型。这两种传输模型具有以下几个特点:
l 都要求只具有一个读取线程和一个写入线程。
l 都是通过复制指针而不是复制数据来实现缓冲区传输。
l 都是为了管理异步I/O而设计的。
这两种传输模型都可以通过相应的适配器和IOM微驱动模型进行连接。
3.1 SIO适配器(DIO)
SIO适配器亦称DIO,是为了方便地将流和IOM微型驱动结合起来而设计的。两者之间的通信和同步是以最小的开销和复杂度实现的。DIO适配器使用以下两种基本类型的函数进行应用程序和微型驱动之间的通信。
回调函数(callback functions) :回调函数是微型驱动和适配器之间的信号传递接口。在设备通道创建的过程中,适配器会告知微型驱动在其完成缓冲区处理后应该调用哪个函数作为回调。
传输函数(transfer function) :传输函数会调用微型驱动的mdSubmitChan函数。而mdSubmitChan函数会从适配器端接收到一个缓冲区,然后通过通道对象将该缓冲区的信息传递给相应的ISR。
3.2 PIP适配器(PIO)
DSP/BIOS PIP模块提供了一种“数据管道”服务来管理异步I/O。每个管道对象都维护着一个被划分为多个大小相同的帧的缓冲区。管道对象里帧的数量和大小可在DSP/BIOS配置工具里进行设置。尽管每个帧大小固定,但应用程序实际放入的数据也可以小于帧的大小。
一个管道有两个端口:写入端(程序向管道里写入数据帧)和读取端(程序从管道里读出数据帧)。典型情况下其中一端是一个调用某I/O设备的函数。
数据通知函数用于对数据传输进行同步,当一帧数据写入管道或从管道读取后都会触发通知函数以通知PIP的另一端有一个满帧或空帧可用。
4 使用DSP/BIOS设备驱动
4.1 注册微型驱动
为在DSP/BIOS应用程序中注册并使用一个IOM微型驱动,用户必须配置应用程序使用该微型驱动。该配置过程是静态完成的,通过DSP/BIOS配置工具或者通过一个DSP/BIOS TextConf 脚本驱动。
4.2 GIO模块
GIO模块实现了GIO类驱动,为应用程序提供了一个阻塞性(同步)读/写API接口。特点有:
l 提供阻塞性(即同步)读写API函数。
l 使用IOM接口与具体设备的微型驱动通信。
l 支持多设备驱动。
l 支持双向通道。
l 允许用户配置阻塞函数
l 可以扩展API函数支持新的应用领域。
对GIO接口的扩展还能够被更“友好”和有效地用于视频捕获及显示驱动。例如这种扩展可以满足视频设备存储区分配(如专门的帧缓冲区)的需要。另外,在提供了视频驱动和应用程序之间的视频数据同步机制之后,这种扩展也能够允许使用一个单独的调用来“交换”视频缓冲区。
GIO模块的一个重要特点是能够扩展额外的API函数以支持新的应用领域。本节将给出为支持视频应用而实现的一个GIO类驱动API扩展的示例。和使用现有的SIO或PIP API函数相比,该扩展更有效地满足了一个实时环境下视频API接口的要求。该视频API接口特别地针对视频信息逐帧捕获和逐帧显示的需要而进行扩展。通过简单的使用GIO API 函数的宏定义,可以创建生成一个完成的基于帧的视频模块(FVID),并且不用添加任何新的代码到应用程序中。视频帧捕获和显示还包括以下要求:
1 API函数应该易于理解和使用。通过最小化或者消除应用程序中对设备特有控制调用的需要,使得代码的复用性和可读性得到增强。
2 处理应用程序和设备驱动之间的帧缓冲区的同步。例如,一个视频显示驱动必须始终显示视频数据,直到应用程序给它另一帧视频数据去显示,它才会将上一帧缓冲区返回给应用程序。执行这种同步最有效的方式就是定义一个单独的API调用来负责缓冲区交换。同样一个视频捕获驱动必须始终返回最新捕获的视频数据,这要求驱动在下一次缓冲区交换发生之前至少保留一个帧缓冲区。
3 进行帧缓冲区管理:根据视频设备硬件情况,缓冲区可以从系统存储器中或者从设备存储器中分配。一些视频设备拥有自己的视频RAM且应用程序可以用它作为视频帧缓冲区。另外,驱动API的用法不应该随着帧缓冲区的分配位置而改变。