DSP

[zz]C64x系列DSP/BIOS中设备驱动程序的设计2

2019-07-13 12:31发布

3 微型驱动的设计和实现     类/微型驱动模型中的微型驱动直接控制外部设备。只要微型驱动创建了规定的函数,应用程序就可以方便地通过DIO适配模块、PIO适配模块或(和)GIO类驱动调用。这些规定的函数包括:通道绑定函数(md—BindDev)、通道创建/删除函数(mdCreateChan/md—DeleteChan)、I/O请求发送函数(mdSubmitChan)、中断服务函数(ISRs)和设备控制函数(mdControlChan)。这些规定的函数将放入微型驱动的函数接口表(IOM_Fxns)中的相应位置,供应用程序通过适配模块或GIO类驱动调用。函数接口表的结构如下: typedef struct IOM_Fxns { IOM_TmdBindDev mdBindDev; IOM—TmdUnBindDev mdUnBindDev; IOM—TmdControlChan mdControlChan; IOM_TmdCreateChan mdCreateChan; IOM_TmdDeleteChan mdDeleteChan; IOM_TmdSubmitChan mdSubmitChan; }IOM_Fxns; 3.1 绑定通道函数       DSP/BIOS设备初始化时将调用每个已注册到微型驱动中的绑定函数(mdBindDev)。绑定函数一般要实现下列功能:根据配置的设备参数和可能存在的全局设备数据初始化外围设备;挂入中断服务函数(ISRs);获得缓存、McBSPs、McASPs和DMA等资源。     如果微型驱动使用多个外部设备,则DSP/BIOS为每个外设调用绑定函数。设备参数devid用来区分设备。如果支持一个设备,则绑定函数必须检查是否已经有设备绑定。     微型驱动如果使用静态数据来减少实时处理的动态数据分配,可以使用输入/输出数据指针(devp)。输入/输出数据指针将传给通道创建函数(mdCreateChan)。 3.2 通道创建/删除函数     从应用的观点出发,在应用程序和外部设备之间必须有一个逻辑交流通道用来交换数据。应用程序通过微型驱动创建一个或多个逻辑通道对象作为应用程序的逻辑通道。通道创建函数(mdCreateChan)根据需要创建通道对象并给通道对象设置初始值。通道删除函数(md—DeleteChan)则删除已创建好的通道对象。虽然每个微型驱动的通道对象数据结构都略有不同,但有些字段是必须的,如通道模式、等待I/O包序列和回调函数。以下是一个常见的通道对象数据结构: typedef struct ChanObj { Bool inuse; /* 如果为TRUE,则通道已打开 */ Int mode; /* 通道模式 */ IOM_Packet *dataPacket; /*I/O包 */ QUE_Obj pendList, /* 等待I/O包序列 */ Uns *bufptr; /* 当前缓存指针 */ Uns bufcnt; /* 未处理的缓存数目 */ IOM_TiomCallback cbFxn; /* 回调函数 */ Ptr cbArg; /* 回调函数参数地址 */ }ChanObj,*ChanHandle; 3.3 I/O请求发送函数     微型驱动中的I/O请求发送函数(mdSubmitChan)用来处理IOM_Packet包中的命令字段。根据不同命令字段,微型驱动将处理命令或返回错误信息(IOM_ENOTIMPL)。     微型驱动支持的命令字段有:IOM_READ、IOM_WRITE、IOM_ABORT和IOM_FLUSH。微型驱动创建的输入通道由IOM_READ命令来执行输入任务,创建的输出通道则由IOM_WRITE命令来执行输出任务。要放弃或者刷新已经发送的I/O请求,可以使用IOM_BORT或IOM FLUSH命令。当放弃时,I/O请求包队列中的所有输入输出请求都将被放弃。当刷新时,所有的I/O输出包顺序执行,而所有的输入I/O包都被放弃。 3.4 中断服务函数     微型驱动的中断功能就是去处理外部设备的触发事件,例如周期性的中断。中断通常是表示外设采样完数据或者处理完数据,也可以用于为DMA提供同步信号,微型驱动必须处理这些中断。通常微型驱动中的中断服务函数ISRs必须完成以下功能: 出列IOM_Packet请求;设置下一次传送或服务请求;调用类驱动的回调函数以保证和应用程序同步,并返回IOM_Packet。 3.5 设备控制函数     微型驱动支持的控制操作因不同的外部设备而异。IOM定义了一些通用的控制代码供驱动程序调用。特定设备独有的控制代码必须自己编写,其特征值必须大于128(IOM_CNTL_USER)。目前IOM支持的通用的控制代码有: IOM_CHAN_RESET:将创建的通道实例重新恢复到初始状态。 IOM_CHAN TIMEDOUT:当应用程序或类驱动超时时,此控制代码将进行超时操作。例如,一个超时的IOM_Packet,如果没执行回调函数,可能会被返回类驱动。 IOM_DEVICE_RESE:外部设备重新恢复到初始状态,它将影响为这个外部设备创建的所有通道实例。     微型驱动支持的控制代码和控制操作必须告诉使用微型驱动的应用程序开发者,特别要注明该代码的针对对象(是针对通道实例还是针对设备实例)。例如:改变外设波特率的控制代码,必须注明是针对某个通道或者所有通道的,否则容易给应用程序带来错误。 4 类/微型驱动模型驱动应用实例——C64x系列DSP/BIOS中PCI设备的驱动 4.1 微型驱动的设计与编写 (1) 设计mdBindDev的部分程序代码: static Int mdBindDev(Ptr *devp,Int devid,Ptr devParams) { …… QUE_new(&device.hiShPrioQue)/*户建立IOM包队列*/ QUE_new(&device.lOwPrioQue); …… hwiAttrs.ccMask=IRQASK_NONE; /*初始化PCI中断*/ hwiAttrs.arg=NULL; IRQ_map(1RQ_EVIDSPINT,intrld); HWI_dispatchPlug(intrId,(Fxn)isr,—1,&hwiAttrs); } (2)设计mdCreateChah的部分程序代码 static Int mdCreateChan(Ptr *chanp,Ptr devp,String name, Int mode,Ptr chanParams,IOM_Tiom Callback cbFxn,Ptr cbArg) { …… chan=MEM_alloc(0,sizeof(ChanObj),0); chan—>queue=&device.hghPrioQue; /*通道初始化*/ …… if(device.openCount==0){ PCI_intEnable(PCI_EVT_PCIMASTER); /*PCI设备中断初始化。*/ …… IRQ_enable(IRQ_EVT_DSPINT); } *chanp=chan; /*返回创建通道*/ } (3)设计mdSubmitChan的部分程序代码 static Int mdSubmitChan(Ptr chanp,IOM_Packet *pPacket) { ChanHandle chan=(ChanHandle)chanp; /*挂载已创建通道*/ …… req=(C64XX_PCI_Request*)packet->addr; /*I/O请求包地址*/ req->reserved=chan; …… /*处理读写请求包*/ if(packet->cmd==IOM_READ‖packet->cmd== IOM_WRITE){ imask=HWI_disable(); QUE_enqueue(chan->queue,packet) …… } ……/*处理其它功能的请求包 */ removePackets(chan,packet->cmd); /*移除已处理的请求包*/ }     中断服务函数(ISRs)和设备控制函数(mdControlChan)的结构与以上I/O请求发送函数(mdSubmitChan)的结构类似,本文不再作叙述。 4.2 在DSP/BIOS中注册微型驱动     打开DSP/BIOS配置工具,如图3所示。右键点击User-Defined Devices图标,选择插入选项,并重新命名为PCICHAN。右键点击PCICHAN,选择属性选项,进行注册,如图4所示。 4.3 编写类驱动     本例的类驱动使用通用输入输出模块,首先右键点击图3中的GIO Manager,选择启动GIO。在应用程序中,GIO_create函数使用微型驱动PCICHAN来创建通道实例,通过调用GIO_submit函数完成应用程序对PCI设备的读写操作等。源代码如下: (1)创建通道 CIO—Handle pciChan; C64Xx_PCI_Attrs pciChanParam; C64XX_PCI_Request pciChanRequest; C64XX_PCI_DevParams pciChanDevParam; GIO_AppCallback pciChanCallBack; pciChan=GIO_create(”/PCICHAN”,IOM_INOUT,&status,NULL,NULL); (2)发送读请求包 pciChanRequest.srcAddr=(Ptr)BitsBuffer; pciChanRequest.dstAddr=(Ptr)m_DspControl.CstartAddr; pciChanRequest.byteCnt=length+20; pciChanRequest.options=PCI_WRITE; pciChanReqSize=sizeof(pciChanRequest); status=GIO_submit(pciChan,IOM_WRITE,&pciChanRe—quest,&pciChanReqSize,NULL);     通过上述三个步骤,PCI设备的DSP/BIOS驱动设计就基本上完成了。应用程序可以通过使用类驱动来复用PCI设备,这样极大地提高了驱动的工作效率,对PCI外设的控制也大为简化了。