DSP

dsp EDMA学习与疑问

2019-07-13 10:11发布

EDMA是一种数据传输模式,用EDMA建立无需CPU干预的外部设备与内存之间的直接数据传输通道,节省CPU工作时间。 EDMA控制器主要包含传输控制器和通道控制器两部分。传输控制器包含了将要传输的数据,而通道控制器是通过一个触发事件或者它接收到一个传输请求TR,从而实现进入传输入口的。注意它的传输主要是事件触发的特点。 EDMA有三种触发方法: 1、最主要的通过外部事件来触发一次TR; 2、通过某个指定的传输完成后触发另一个的连锁触发方式; 3、CPU触发,通过往事件设置寄存器ESR中写数,一般调试用。 EDMA有1D和2D两种传输模式。1D的数据组成为块-》帧-》元素,2D的数据组成为块-》数组-》元素。 每个外设都有寄存器,EDMA的寄存器如下: ESEL:设置EDMA事件与通道的映射关系(有些dsp型号是固定映射的); PQSR:表示状态,表示传输寄存器在每个优先级水平上是否为空; CIPR:表示通道中断待定状态; CIER:使能或屏蔽通道中断; CCER:使能或屏蔽通道连锁; ER:表示状态,表示捕获的事件; EER:使能或屏蔽ER中的每一个事件; ECR:清除已触发的事件; ESR:触发传输请求。 另外有个很重要的通道参数RAM,通常称PaRAM,包括OPT通道选项参数、SRC源地址参数、DST目的地址参数、CNT、IDX、RLD等等参数。这个寄存器在程序中是显式配置的,不像前面那些,应该都写成CSL函数了。
程序的流程我通过一个实例来解释了。这个实例将实现,当FIFO满了,触发EDMA把FIFO数据经EMIF-》EDMA读入内存。 硬件上,注意FIFO和dsp EMIF接口的连接,尤其让FIFO的满信号和dsp外部中断引脚相连,这样满信号就能作为外部GPIO触发中断。 软件编程分为以下几部分: 1、初始化部分: (1)CSL的初始化; (2)中断寄存器的初始化,例如设置中断向量、先禁止所有中断源等等; (3)EMIF的初始化,即函数EMIF_config(&myConfig),其中要对myConfig结构体根据EMIF知识点进行配置。 2、设置EDMA中断:
void IRQ_map(Uint32 eventID,int intNumber);//将中断事件和中断号绑定 对于EDMA中断号为8,那么应该写成(中断号依型号而定): IRQ_map(EDMAINT,8); 3、配置并打开EDMA通道: (1)配置前应该清空寄存器并禁止中断: EDMA_clearPram(0x00000000); EMDA_intDisable(7);//GPIO外部触发事件,所以事件号可以为7,对应GPIO事件7/外部中断7 (2)打开通道返回句柄:EDMA_Handle EDMA_open(int chaNum,Uint32 flags); 第一个参数是通道设置的事件号,第二个参数统一为EDMA_OPEN_RESET,一系列的初始化工作。 因为这里是GPIO外部触发事件,事件号为7,因此写成: hEdma7 = EDMA_open(EDMA_CHA_EXTINT7,EDMA_OPEN_RESET); (3)配置EDMA,通过结构体。 注意这个配置函数需要句柄和结构体两个参数:void EDMA_config(EDMA_Handle hEdma,EDMA_Config *config); 那么就需要对该结构体进行配置,共有OPT、SRC、DST、CNT、IDX、RLD六个寄存器,格式同EMIF的配置格式。 (4)使能EDMA传输结束中断,允许一次传输结束后产生中断。 EDMA_intEnable(7); (5)使能EDMA事件号的传输通道及使能EDMA传输。 EDMA_enableChannel(hEdma7); IRQ_enable(EDMAINT); 4、可以编写中断服务程序,表示中断发生的时候干什么。 EDMA_IntHandler EDMA_intHook(int tccNum,EDMA_IntHandler funcAddr); 例如本例可以写为:EDMA_intHook(7,myLed){} 注意这个程序实现的是中断处理函数,即EDMA传输完成后做什么事情,而传输的过程经过事件触发自动完成,不用显示的读写。
注意EDMA整个程序流程的顺序是很讲究的,对中断的设置流程来讲,都是先初始化-》禁止大中断-》禁止小中断-》设置映射等等-》开启小中断-》开启大中断的顺序。以后也要注意中断的写法。
目前对于EDMA还是有很多疑问,比如:
1、在实际配置EDMA时候只显式配置了PaRAM,而其他的没有看到。虽然很明显的一些CSL函数肯定是对某个寄存器某位进行设置,但不确定真的是这样吗?
2、上一节的EMIF程序没有用到EDMA,是不是说明它的读写就是经过CPU的,需要取地址取数据? 等等。
扩展:当需要多组EDMA传输的时候,需要定义多组PaRAM,每组的最后参数linkaddress指向另一个PaRAM,就像一个链表的结构。整个程序多用数组的形式和for循环,参考文档《EDMA使用详解》。
补充:在另一个地方看到软件触发EDMA的函数:EDMA_setChannel(...)