EDMA中断

mu03029827   2007-7-31 08:43 楼主
大家好:
  我想问一下,我的EDMA中断服务程序里面的代码太长执行时间太长,这样相应其他中断就不及时了所以我想把中断服务程序里数据处理部分移植到主函数中,然后在EDMA中断服务程序里判断来了中断给出标志,然后主函数里判断标志位进行操作,我想问一下在中断服务程序里应该判断哪个寄存器呢?另外在EDMA与MCASP通信是不是一定要用到中断

回复评论 (19)

有点没有看懂.
>>然后在EDMA中断服务程序里判断来了中断给出标志
中断服务程序执行了就表示产生了中断, 为什么要根据某个寄存器做出判断呢. 难道好几个中断都是一个中断服务程序?

以前好像说过的,一般这种中断服务太长的问题都是用DSP/BIOS的HWI, SWI和Task解决。
点赞  2007-7-31 09:26
嗯知道的,但是现在我们还不能用BIOS来控制。我想问问你我现在接收发送各一个事件,然后MCASP使用EDMA的 ping pong buffer 来接收和发送数据,我现在发送和接收分别对应得TCC为12/15,有点迷惑的是发送和接收的TCC只需要设定其中一个就可以正常进入中断服务程序操作,为什么呢?
  还有一种现象我在配置时设置发送端:
EDMA_Config   cfgEdmaXmt={              
               EDMA_OPT_RMK(                                                                  
               EDMA_OPT_TCINT_YES - Indication enabled         
               EDMA_OPT_TCC_OF(12), )
           } 
  接收端EDMA_OPT_TCINT_NO
               EDMA_OPT_TCC_OF(0)//本来应该是15
  这种情况下在中断服务程序里只清除接收端EDMA_intClear(edmaChaAREVT);程序照样正常运行,我迷惑的是为什么中断完成码设置的是发送的,清中断时清的是接收端的还能够正常运行?还是我理解有误呢?我配置的是帧同步。
点赞  2007-8-1 01:35
关于你问的这些问题建议仔细阅读EDMA文档。

例如第二个问题:
当进入中断,CIPR的第12位为1,你却清除第15位,这样第12位的值不变,根据文档的下述段落:
After any write to CIPR, if the bitwise AND of the CIPR and CIER is nonzero,
the interrupt flag is set in the interrupt flag register (IFR) of the CPU.

将会立即产生一个新的EDMA中断。这样你的程序就会不停的在中断中产生新的中断。但是这些中断应该是不正常的,不知道你是否能正确听到声音。
点赞  2007-8-1 05:19
这个问题我也觉得很奇怪,觉得这样设置应该不正确,但是却能够听到正确的声音。我觉得应该分别在接收和发送配置端都设好TCC中断完成码,然后进入中断服务程序再清除
EDMA_intClear(edmaChaAREVT);
EDMA_intClear(edmaChaAXEVT);
你觉得对吗?但是为什么会出现我上面引用的那种情况还能正常输出声音呢?

关于邮件给你的文档,我改为放到main函数里出现的问题是噪声输出,不知道为什么?我有什么地方改错了吗?
点赞  2007-8-1 06:39
先解决前面的问题2
根据我的分析,你那样做会产生很多中断,你设置一个长整型计数器,看看如果你“在中断服务程序里只清除接收端EDMA_intClear(edmaChaAREVT)“的话,5秒钟之内产生多少次中断,和实际应有的中断数是否符合。
因为我看你的程序就只是从输入缓存复制到输出缓存,所以可能能够正确出声。

你在main中的复制缓存部分设置断点,看看是否运行了复制程序。
点赞  2007-8-1 08:16
对不起,问个很弱的问题。
  我现在对中断理解的意义不深,我想问问你,正常情况下我该怎么确定多长时间来一次EDMA中断?测量5秒钟之内产生多少次中断是不是就是在中断服务程序里设置计数变量,但是这个5秒时间该怎么衡量,另外5秒内实际应有的中断数我不知道应该怎么计算。是不是需要使用定时器中断呢?
点赞  2007-8-2 03:06
我在主函数复制部分设置断点,是可以正常进入的,但是输出的声音明显不对
点赞  2007-8-2 03:20
我只是举个例子。
你可以在中断中设置一个计数变量,自己看着秒表,让程序运行5秒钟,看看产生了多少次中断。
或者用profile中的clock测量两次中断之间的间隔。多测量几个。

1秒钟正常产生多少次中断,取决于你的取样频率和pingpong缓存的大小。

另外你的中断服务程序直接清除两个TCC也好像不对。我这边的程序是这么写的:
也就是说,必须输入DMA和输出DMA都完毕之后,才运行处理程序。
Int16 xmtdone=0, rcvdone=0;
void EDMAIsr(){
       
        if(EDMA_intTest(XEdmaTcc)){
                EDMA_intClear(XEdmaTcc);
                xmtdone=1;
        }
       
        if(EDMA_intTest(REdmaTcc)){
                EDMA_intClear(REdmaTcc);
                rcvdone=1;
        }
       
        if(xmtdone && rcvdone){
                lastpingpong=pingpong;
                SWI_post(&processBufferSwi);  // post a SWI to process lastpingpong buffer
                pingpong=!pingpong;
                xmtdone=0;
                rcvdone=0;
        }
}
点赞  2007-8-2 04:16
像这种MCASP通过EDMA传输数据一定得使用到EDMA中断吧?
这个接收和发送是由EDMA事件触发的吧?
点赞  2007-8-2 08:32
引用:
 写道:
像这种MCASP通过EDMA传输数据一定得使用到EDMA中断吧?
这个接收和发送是由EDMA事件触发的吧?
EDMA不产生中断的话,DSP无法知道一块缓存是否传输完毕。
通常输入输出都采用pingpong缓存。
当某个输入缓存满,并且其对应的输出缓存空时,把输入缓存的内容复制到输出缓存。其中可以加上声音处理。因此应该在接收和发送事件都触发之后,进行上述处理。
点赞  2007-8-2 09:22
我调试的时候
for(;
    {
   
            if(symbol==1)
            {
   此处设置断点 symbol=0;
               if(ping==1)
                     {         pong=1;
             ............................
第一次进入断点处,count=2,以后每进入一次上面所示的断点count增加2,我觉得应该是对的呀,但是为什么我的程序声音输出还是杂音呢?中断服务程序详见上一个帖子。
点赞  2007-8-4 03:54
这个问题只有慢慢调试了,很难说具体是什么问题。
你现在把复制部分放到中断中能正确运行么。
点赞  2007-8-4 04:37
复制部分放到中断内部是可以的
点赞  2007-8-4 05:50
你把完整的程序发给我,我看看.
不会是在main里面每次复制之前某些变量没有初始化吧,我看你那个main函数中的j,k变量可是没有每次初始化为0。不过你的main函数也不完整,所以不好说。
点赞  2007-8-4 06:47
呵呵。谢谢呀,一语点破梦中人,果真是j,k没有初始化,我真是太笨了,没有去检查这些简单的问题。多谢呀。
  现在已经成功了,但是还有些小地方我不太理解,现列举如下,请帮我解决一下:
1、我觉得我只需要EDMA接收中断,而不需要设置发送中断,也就是说只需要设置接收的TCC=15。原因是我从MCASP接收到的数据存到数组中,然后需要接收中断来提取数组中的某些数输出,然后直接发送出去,所以我觉得没有必要配置发送完成码进行发送,你觉得呢?
2、在配置MCASP时有一步语句,如下所示:
     /* Verify all transmit buffers are serviced                      */
//    while(!MCASP_FGETH(hMcasp0,XSTAT,XDATA));
为什么我不注释掉的话就执行不下去,显然不满足while中的条件,但是我觉得我没写错。
点赞  2007-8-4 07:39
果然是这个问题.

如果你的输入输出都是使用的pingpong缓存的话,最好输入输出都产生中断之后再进行处理,也就是保留现在的程序不要改动。我看过的和我写的程序都是这么做的,因为这样才能确保是输入缓存满,输出缓存空的时候进行操作。你去掉一个中断也应该能够运行,但是日后出了什么问题可不好调试。

至于
while(!MCASP_FGETH(hMcasp0,XSTAT,XDATA));
应该是
while(MCASP_FGETH(hMcasp0,XSTAT,XDATA));
吧,这句话是用来检测DMA是否将数据复制到XBUF中,如果XBUF满了,XDATA变为0,退出while循环。具体说明请看MCASP文档。
点赞  2007-8-4 08:10
欧,我还想问问,我的ping pong 操作是这样运行的,你看对不对:
1 接收时:
源地址 EDMA_SRC_RMK(MCASP_getXbufAddr(hMcasp1))
目的地址 ping:数组B0
     pong:数组B1
2 发送时:
源地址  ping:数组A0
     pong:数组A1
目的地址 EDMA_DST_RMK(MCASP_getXbufAddr(hMcasp0))

说明:EDMA操作时,接收到数据,应该是接收中断后进行数组B向A的数据提取拷贝,如果设置发送终端的话,进入中断服务程序时证明已经接收发送完成,那么在拷贝数据不就没有意义了嘛?整个通信过程又是怎样的呢?不太理解了。

还有就是MCASP配置寄存器时都有读回GBLCTL的操作,我都是用类似这样的语句完成的
while(!(MCASP_FGETH(hMcasp1,RGBLCTL,RSMRST)));
的确有那个!的操作,别的都没有问题,为什么到了
while(!MCASP_FGETH(hMcasp0,XSTAT,XDATA));会有问题呢?
点赞  2007-8-4 08:28
我想你对pingpong缓存的用法有些不明白吧。
0. 按照你的假设
B0 B1 输入
A0 A1 输出

1. 初始化A0, A1,都填充0

2. 让输入DMA写B0, 输出DMA输出A0的内容。

3. 输入DMA完毕,中断,此时我们知道B0满了。输入DMA自动开始写B1

4. 输出DMA完毕,中断, 我们知道A0的数据已经全部输出了。输出DMA自动开始读A1

5. 复制B0->A0

6. 输入DMA完毕,中断,此时我们知道B1满了。输入DMA自动开始写B0

7. 输出DMA完毕,中断, 我们知道A1的数据已经全部输出了。输出DMA自动开始读A0

8. 复制B1->A1

第7步中开始输出的A0里面就是前面第5步复制过去的值了,整个系统的延时是A0+A1的长度。

如果你不等输出DMA中断,那么在你复制B->A的时候,输出DMA可能还没有输出完毕,这样的话,就会听到po po的声音了。

while(!(MCASP_FGETH(hMcasp1,RGBLCTL,RSMRST))); 是正确的, 但是XSTAT的XDATA的含义不一样,还是看文档:
7) Verify that all transmit buffers are serviced. Skip this step if the transmitter
is not used. Also, skip this step if time slot 0 is selected as inactive (special
cases, see Figure 3
点赞  2007-8-4 08:46
我明白了,应该是处理ping时的中断的时候,转存数据进入pong所对应的数组,反之亦然,对吗?谢谢啦。

点赞  2007-8-4 09:18
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复