DSP中DMA操作的无阻塞请求实现
DMA在DSP应用中至关重要,本文给出了DMA操作非阻塞的请求方法,针对TMS320C620x,实现了与CSL中DAT接口一致的驱动模块QDAT,并指出了EDMA相关的高级特征。
在DSP中,DMA控制器实际是一个外设,与其他集成的串口、主机接口、片外内存接口等都在系统外设总线上,也与其他外设一样有一组相关的控制/状态/数据寄存器,CPU可以访问。
非常重要的一点是,DMA通道能够用于内存之间的数据传送。这里内存都是统一编址的,包括:片上内存,程序和数据分立;接在EMIF上的片外内存,如SDRAM;外设的寄存器也都是内存映射的(memory-mapped),所以DMA通道也可以用于外设和内存之间,进行外设数据接收与发送。
在DSP的处理模型中,所有数据应位于片上供CPU处理,不鼓励CPU直接访问片外数据,因为CPU访问片外资源的时间较长,周期数也不确定,对于实时性和确定性不利。片上内存有时也能够配置成为缓存(cache),缓存控制器会根据一定策略、使用DMA方式切换片外的数据进出缓存,最终使得用户能够在片上访问数据,这个过程对用户是透明的。正因为缓存的机制是透明的,所以也是很难控制的。比如,一段调用频率很高的代码很可能被不常用的部分清出缓存,因为它们映射相同,但随后又很快被调入,这样会造成局部的效率降低。
所以,如果能够明确掌握程序流或数据流的运转特征,不使用缓存模式,用户通过DMA进行自定义的调度,可能提高效率。有的处理器不具备缓存控制器,不支持片上内存作为缓存,如C6205的片上数据内存就不能够配置为缓存,所以主动使用DMA移动数据不可避免。
DSP的DMA功能一般也都较为强大,TI C6000系列的DMA通道支持1D-1D、1D-2D、2D-1D以及常用的2D-2D数据传送,对DMA的合理使用可能替代相当的编程效果,如排序、采样或裁剪。
TI的CSL(Chip Support Library,芯片支持库)对于使用DMA给出了很好的支持,有专门的DMA模块,便于对DMA的各个寄存器进行控制。还有一个DAT模块,使用DMA进行内存数据传送,函数DAT\_copy()和DAT\_fill()就像常用的内存操作memcpy()、memset()一样,只需要在API接口指出源地址、目的地址和长度,或者其他的维数属性等即可,不需要再去管具体的寄存器,非常方便。
视频处理实例分析
DAT模块易用,但因为是在CSL中,所以只能将DMA控制器直接的功能表达出来。对于灰度图像处理(先不考虑将算法处理后的结果传回片外的情况),在下面的处理框架中,每次DMA执行操作时,CPU在前台还可以做算法处理任务。
...
task=DAT_copy(...);//启动头一个DAT任务
...
while(not_finished){
DAT_wait(task); //本次task完成
task=DAT_copy(...); //启动下一次的DMA
pingpong_alg_process(...); //对本次传送的数据处理
}
当视频为4:2:0 YUV图像(planar模式)序列,需要处理某一区域时,实际上是在相同时机处理Y、U、V三块数据,通常它们并不连续,也就是说,将会同时使用三个DMA操作。
这里可能可以同时启动多条DMA通道,但有一些限制:
1. 有的处理器支持同时启动的DMA通道数有限,有些DSP有4条通道,但寄存器集只能完整地支持两条;
2. 由于共享总线和某些接口,同时工作的DMA通道数过多将可能增加访问冲突,降低系统性能;
3. 有时多条通道又必须同时使用,比如系统视频、音频采集进入的数据必须占用独立的通道。
所以,上面的任务能够尽量使用一个DMA通道完成,不失一般性,DAT模块的所有操作实际上是在一条打开的通道上完成的。
那么,对于YUV图像,处理程序框架类似上面,可能如下,
...
taskY = DAT_copy(...);
taskU = DAT_copy(...);
taskV = DAT_copy(...);
...
while(not_finished){
DAT_wait(taskY);
DAT_wait(taskU);
DAT_wait(taskV);
taskY = DAT_copy(...);
taskU = DAT_copy(...);
taskV = DAT_copy(...);
YUV_pingpong_process(...);
这时问题出现了:C620x的DMA通道一次只能接受一个传送请求,也就是说,每次请求必须等到该通道空闲时才可能真正提交上去,这样taskY和taskU在后台操作时,前台无法进行taskU和taskV的启动,即实际上前台没有什么处理任务可做,浪费了效率。而这三个dat任务绑定在一起,启动时机很难拆开。显然,如果能够允许DMA请求连续地提交,将提高效率。
DMA通道请求非阻塞提交的方法
把DMA通道看作一个单处理单元,每个DMA操作作为一个任务,这就形成了一个单处理多任务的模型,任务调度就是FIFO。不妨定义:
1. DMA通道请求上下文是一个数据结构,它包含启动一次DMA传送所需要设定的寄存器参数集合,如源、目的、长度、index寄存器(维数)等等;
2. DMA通道请求上下文队列,一个DMA请求上下文的队列用以缓存DMA请求;
DMA通道的使用和请求非阻塞的提交应有以下两条原则:
a. 应用程序的使用DMA通道的方法:
提交DMA通道请求(无阻塞),获得此次任务的id;在需要使用某任务的目标内存时,应检查该id任务状态直到完成;如果完成,即可进行相应的处理。
b. 无阻塞提交DMA通道请求的实现:标志此次DMA传送任务正在进行;如果DMA通道空闲,设置寄存器启动DMA操作,标志DMA通道正在工作;如果DMA通道正在工作,则将此次DMA请求插入上下文队列。
3. DMA中断服务程序(注:DAT模块不使用ISR,只是查询对应标志,确定DMA传送是否完成):标志此次DMA传送任务完成;如果DMA请求上下文队列为空,标志DMA通道空闲;如果DMA请求上下文队列非空,则从队列中取出头一个DMA请求上下文,用以设置相应的寄存器启动DMA操作。
QDAT:一个非阻塞的DMA模块实现
在TI C620x DSP上,一个非阻塞的DMA模块QDAT根据以上原理得以实现。
QDAT的API与DAT模块的基本一致,优点是使用上述的YUV图像处理应用程序中,不会发生DMA请求阻塞;
QDAT与DAT模块功能相似,但属于驱动程序层次的实现,基于:CSL的DMA模块;CSL的IRQ模块;以及DSP/BIOS的QUE模块。
不过实现十分简便、轻盈。
该模块独立于应用和算法,已经在基于TI C620x DSP上的多个项目中使用,效果十分理想,特别是因为QDAT任务中的DMA操作经过了串行化,也大大降低了在EMIF上访问内存时的冲突。
EMDA的先进特征
这些项目向新的TI DM642媒体处理器上移植时,以上的操作将利用EDMA的先进特征, 因为TI C6x1x 和 C64x DSP开始使用EDMA,值得注意的是,EDMA通道控制器(EDMACC)有专门的PRAM(parameter RAM)来缓存DMA请求参数,EDMA事件参数表中有标志以及LINK address,用来指示本次DMA传送结束后, 是否有新的DMA请求参数需要重载入操作寄存器; 如果有,LINK address所指就是新的参数在PRAM的位置。 显然因为这样的链表机制,使用该通道连续两次传送之间无需中断处理程序(CPU)介入队列管理,效率将提高。 对于频繁的内存数据传送,如DAT操作一般使用QDMA, 它由CPU直接将传送请求(TR)提交给传送控制器(EDMATC),TC中有四个优先级队列,每个TR都将进入其对应(已指定)的一个队列。 对于不同的请求源,队列的长度可编程,每个队列最多可以接收7个QDMA请求。 如果队列有空,TR就可以进入;若满了,CPU将会停止(stall)几个EDMA周期等待TC的执行,队列随即空出一个位置。
|