转载自左超的CSDN博客http://blog.csdn.net/henhen2002/article/details/4464166

几天调下来,总感觉TI的文档语焉不详。不过想想也对,250页的文档是谁都要写到郁闷的。而且一个懂了的人给初学者讲东西总会自然的略过一些看似当然的关键。
     这几天遇到的问题就是EDMA可以工作,却不能连续不断的转起来。而问题的所在就在于文档没读清楚。
     文档(SPRU234,下同)在第一章的第一节的图1-2就给出了EDMA的控制块图。现在看到控制块图当然联想到实际的工作流程,但是似乎文档并没有解释EDMA的工作流程。
     在EDMA工作中,总共使用了两个参数表,其中的一个是由EDMA控制器维护的,而另一个是由用户维护的。EDMA控制器维护的参数表规则的排列在整个参数表的开始部分,一个通道一个,谁也不多谁也不少。而用户维护的参数表则被称作Reload channel parameters,随意分布在整个参数表的后半部分。现在看来,能知道EDMA控制器是用了两个参数表就可以很好的理解EDMA的工作方式。
     非连续的工作:
     EDMA可以工作在连续的和非连续的状态。数据非连续的时候可以采用单次的非连续工作状态。这时用户在初始化的时候直接初始化EDMA所维护的参数表就可以了。如下面的例子:
*edmaHandle = EDMA_open(eventId, EDMA_OPEN_RESET);
if(*edmaHandle == EDMA_HINV)
   test_exit(FAIL);

if((tcc = EDMA_intAlloc(-1)) == -1)
   test_exit(FAIL) ;

EDMA_configArgs(
   *edmaHandle,
   EDMA_OPT_RMK(
   EDMA_OPT_PRI_MEDIUM,
   EDMA_OPT_ESIZE_32BIT,
   EDMA_OPT_2DS_NO,
   EDMA_OPT_SUM_NONE,
   EDMA_OPT_2DD_YES,
   EDMA_OPT_DUM_INC,
   EDMA_OPT_TCINT_YES,
  
   EDMA_OPT_TCC_OF(tcc & 0xF),
   EDMA_OPT_TCCM_OF(((tcc & 0x30) >> 4)),
   EDMA_OPT_ATCINT_NO,
  
   EDMA_OPT_ATCC_OF(0),
   EDMA_OPT_PDTS_DISABLE,
  
   EDMA_OPT_PDTD_DISABLE,
   EDMA_OPT_LINK_NO,
   EDMA_OPT_FS_NO
   ),
   EDMA_SRC_RMK(srcAddr),
   EDMA_CNT_RMK(EDMA_CNT_FRMCNT_OF((frameCount - 1)),
   EDMA_CNT_ELECNT_OF(elementCount)),
   EDMA_DST_RMK(dstAddr),
   EDMA_IDX_RMK(EDMA_IDX_FRMIDX_OF((elementCount * 4)),
   EDMA_IDX_ELEIDX_OF(0)),
  
   EDMA_RLD_RMK(EDMA_RLD_ELERLD_OF(elementCount), EDMA_RLD_LINK_OF(0))
);
     在这里,LINK参数是被忽略的,这一点可以从TI给的例子中看到(52页开始)。相对于很多DMA控制器来说,这些参数显得很简单而TI的讲述非常详细。
     连续工作方式:
     非连续的工作方式很好理解,TI也讲得很详细,而TI在讲述连续工作方式的时候却一笔带过。和非连续的方式不同之处在于用户需要初始化两张表,而只能维护其中的一张,另一张是由EDMA控制器自动维护的。其中的EDMA维护的这张表是在EDMA工作期间使用的,而用户维护的这张表是在EDMA开始新工作的时候重载的。
     用户在初始化阶段必须先初始化EDMA通道对应的参数表,之后在参数表的后半部分申请一张空闲的参数表,并将其初始化。如文档中1.16.4.3所示的例子,其中62页示例的就是通道对应的参数表,而63页示例的就是需要重载的参数表。
     EDMA在接受了这样的参数表之后,首先判断是否达成DMA完成条件(参考TI文档),如果未完成,开始将参数表中的ELECNT自减,减到零则 FRMCNT减一,而后从ELERLD参数中重载ELECNT,在开始新的一个Frame。周而复始。当FRMCNT也减完了则从重载表重新装入参数开始新一轮的工作。用户则可以根据工作需要在EDMA控制器重载参数之前对重载参数设置以开始不同的工作。
     下面的例子是TI在例子中给出的一个三张表的例子,根据这些例子,用户甚至可以使用4张表或者更多,最多可以单一通道使用22张表(C64X)。而多通道则可以使用N+21张表。

hEdma = EDMA_open(EDMA_CHA_TINT1, EDMA_OPEN_RESET);

hEdmaPing = EDMA_allocTable(-1);
   hEdmaPong = EDMA_allocTable(-1);

cfgEdma = cfgEdmaPing;

cfgEdmaPing.rld = EDMA_RLD_RMK(0,hEdmaPing);
   cfgEdmaPong.rld = EDMA_RLD_RMK(0,hEdmaPong);
   cfgEdma.rld      = EDMA_RLD_RMK(0,hEdmaPong);


   EDMA_config(hEdma, &cfgEdma);   
   EDMA_config(hEdmaPing, &cfgEdmaPing);
   EDMA_config(hEdmaPong, &cfgEdmaPong);   
下面是Ping和Pong的参数:
EDMA_Config cfgEdmaPing = {  
   EDMA_OPT_RMK(
     EDMA_OPT_PRI_LOW,
     EDMA_OPT_ESIZE_32BIT,
     EDMA_OPT_2DS_NO,
     EDMA_OPT_SUM_NONE,
     EDMA_OPT_2DD_NO,
     EDMA_OPT_DUM_INC,
     EDMA_OPT_TCINT_YES,
     EDMA_OPT_TCC_OF(TCCINTNUM),
     EDMA_OPT_TCCM_OF(0),
     EDMA_OPT_ATCINT_NO,
     EDMA_OPT_ATCC_OF(0),
     EDMA_OPT_PDTS_DEFAULT,
     EDMA_OPT_PDTD_DEFAULT,
     EDMA_OPT_LINK_YES,
     EDMA_OPT_FS_NO
   ),
   EDMA_SRC_OF(&ping_data),
   EDMA_CNT_OF(BUFF_SZ),
   EDMA_DST_OF(ping),
   EDMA_IDX_OF(0x00000004),
   EDMA_RLD_OF(0x00000000)
};                         

EDMA_Config cfgEdmaPong = {
   EDMA_OPT_RMK(
     EDMA_OPT_PRI_LOW,
     EDMA_OPT_ESIZE_32BIT,
     EDMA_OPT_2DS_NO,
     EDMA_OPT_SUM_NONE,
     EDMA_OPT_2DD_NO,
     EDMA_OPT_DUM_INC,
     EDMA_OPT_TCINT_YES,
     EDMA_OPT_TCC_OF(TCCINTNUM),
     EDMA_OPT_TCCM_OF(0),
     EDMA_OPT_ATCINT_NO,
     EDMA_OPT_ATCC_OF(0),
     EDMA_OPT_PDTS_DEFAULT,
     EDMA_OPT_PDTD_DEFAULT,
     EDMA_OPT_LINK_YES,
     EDMA_OPT_FS_NO
   ),
   EDMA_SRC_OF(&pong_data),
   EDMA_CNT_OF(BUFF_SZ),
   EDMA_DST_OF(pong),
   EDMA_IDX_OF(0x00000004),
   EDMA_RLD_OF(0x00000000)
};
     这样的方式很像是运动场的径赛场地,运动员从抽头跑入,然后一圈一圈的不断跑下去。使用这种方式似乎可以很好的避免内存访问冲突,我在调试过程中试图修改EDMA自动维护的表项时导致了很糟糕的内存访问错误。

这是使用BIOS和CSL LIB 作EDMA简单例子. 在CCS BIOS 中需要作 中断--EDMA--edmaHwi 的设置. Spru234 和spra636a 都是有用的参考
解释见注释.
void main()
{
    initEdma(); //Edma 初始化
    
    initHwi(); //中断初始化

EDMA_setChannel(hEdma); //开始EDMA传送
    while (1) {}
}
void initEdma(void)
{
EDMA_Config gEdmaConfig; //EDMA设置表
hEdma = EDMA_open(EDMA_CHA_ANY, EDMA_OPEN_RESET); //
gXmtTCC = EDMA_intAlloc(-1); //分配一个可用的TCC

.... //根据实际需要填写EDMA设置表
EDMA_config(hEdma, &gEdmaConfig); 设置EDMA通道

hEdmaReload = EDMA_allocTable(-1); //得到EDMA重载标实 EDMA_config(hEdmaReload, &gEdmaConfig); //设置EDMA重载通道

EDMA_link(hEdma, hEdmaReload); //设置EDMA重载
EDMA_link(hEdmaReload, hEdmaReload); //设置EDMA重载
EDMA_intClear(gXmtTCC); // 清除可能的EDMA中断
EDMA_intEnable(gXmtTCC); // 打开EDMA中断
EDMA_intHook(gXmtTCC, edmaHwi); //通知系统edmaHwi是中断服务者
}

void edmaHwi(int tcc)  //中断服务
{
。。。。//准备数据
EDMA_setChannel(hEdma); //再次开始EDMA传送
}

昨天搞了一天的EDMA乒乓操作学习,晚上临走的时候没有成功,主要是EDMA_Config cfgEdmaPing = { } 这个结构体不支持变量,今天早上和zz生完气就到实验室调成功了。(她总是因为小事朝我发火!!!)
    首先,从形式上看EDMA的乒乓操作分为两种
    1. 这种用EDMA_Config cfgEdmaPing = { } 构造PaRAM的方法,要求填充结构体的都为常量,适合已知地址的传输,我还有搞清楚VP口A通道的寄存器地址,第一次没有成功。
# EDMA_Handle hEdma;       
# EDMA_Handle hEdmaPing;   
# EDMA_Handle hEdmaPong;   
# EDMA_Config cfgEdma;

#   
# EDMA_Config cfgEdmaPing = {    
#                           };                           
#   
#   
# EDMA_Config cfgEdmaPong = {  
#                           };

#   hEdma = EDMA_open(EDMA_CHA_TINT1, EDMA_OPEN_RESET);    
#   hEdmaPing = EDMA_allocTable(-1);  
#   hEdmaPong = EDMA_allocTable(-1);
   
#   cfgEdma = cfgEdmaPing;  
#   cfgEdmaPing.rld = EDMA_RLD_RMK(0,hEdmaPing);  
#   cfgEdmaPong.rld = EDMA_RLD_RMK(0,hEdmaPong);  
#   cfgEdma.rld     = EDMA_RLD_RMK(0,hEdmaPong);    
#   EDMA_config(hEdma, &cfgEdma);       
#   EDMA_config(hEdmaPing, &cfgEdmaPing);  
#   EDMA_config(hEdmaPong, &cfgEdmaPong);
#   IRQ_enable(IRQ_EVT_EDMAINT);  //默认EDMA中断是关闭的  
#   EDMA_intEnable(TCCINTNUM);           
#   EDMA_enableChannel(hEdma); 
   2. 利用EDMA_configArgs()函数来构造PaRam的方法,我正是用的这个方法
    EDMA_Handle hEdmaTable_Ping;
    EDMA_Handle hEdmaTable_Pong;
   
    *edmaHandle = EDMA_open(eventId, EDMA_OPEN_RESET);
    if(*edmaHandle == EDMA_HINV)
    {
        //for(;;){}
    }   
   
    if((tcc = EDMA_intAlloc(-1)) == -1)
    {
        for(;;){}
    }
   
    hEdmaTable_Ping = EDMA_allocTable(-1);
    hEdmaTable_Pong = EDMA_allocTable(-1);
   
    EDMA_configArgs(
        *edmaHandle,
       
    );
    EDMA_configArgs(
        hEdmaTable_Ping,
       
    );
        EDMA_configArgs(
        hEdmaTable_Pong,
       
    );

EDMA_link(*edmaHandle,hEdmaTable_Ping);
   
    EDMA_link(hEdmaTable_Ping,hEdmaTable_Pong);
    EDMA_link(hEdmaTable_Pong,hEdmaTable_Ping);//父参数->子参数
    *tccNum = tcc;

总结一下:
EDMA传输一次完成之后,参数就会清空,会按照上述方式中kink的语句,将参数内容填充,一旦又有EDMA事件发生,就会按照事先加载的参数进行传输。

EDMA_Handle hEdma;
EDMA_Handle hEdmaTable;
...
hEdma = EDMA_open(EDMA_CHA_TINT1,0);
hEdmaTable = EDMA_allocTable(–1);
EDMA_link(hEdma,hEdmaTable);
EDMA_link(hEdmaTable,hEdmaTable);
  这是手册P161给出的例子,和合众达给出的例子差不多,我不明白为什么来了两个EDMA_link()函数,是不是因为这个没有在PRAM中设置连接,如果在参数中设置好了连接就不需要这两个EDMA_link()函数了。网上搜吧:
http://www.hellodsp.com/bbs/viewthread.php?action=printable&tid=6269
作者: luzhipei    时间: 2008-6-9 15:51     标题: EDMA传输

请问用于EDMA传输的CSL语句EDMA_LINK();的作用是什么?
是不是相当与把EDMA参数表中OPT的LINK位置1使LINK有效啊


作者: fanyu1224    时间: 2008-6-16 08:41

连接下一次工作模式的struct的句柄,
因为每一次一个通道工作完之后,通道的工作方式的配置就会被空
具体的参加SPRU401J的161页


作者: 玉丫子    时间: 2008-6-16 11:25

就是对它本身结构的链接


作者: luzhipei    时间: 2008-6-16 15:25

那么请问,使用了LINK语句后,是不是EDMA一次传输完成以后,如果还有同步事件到来又会触发一次EDNA传输?


作者: zhang4378030    时间: 2008-6-16 21:12

原帖由 luzhipei 于 2008-6-16 15:25 发表 
那么请问,使用了LINK语句后,是不是EDMA一次传输完成以后,如果还有同步事件到来又会触发一次EDNA传输?

你说的对,其实就是传输完了,把下一次的EDMA初始化好,如果在来一个事件就会启动EDMA进行数据传输 不知道我说明白了没有


作者: luzhipei    时间: 2008-6-17 08:55

那这样是不是和把EDMA参数表中OPT的LINK位置1使LINK有效,然后设置LINK的地址的效果是一样的?


作者: luzhipei    时间: 2008-6-19 09:38

我在实验中程序用了EDMA_LINK();但是发现只进了一次EDMA传输完成中断,FIFO不断有快满信号触发EDMA传输,,目的地址的波形可以不断更新显示,但是EDMA有了第一次传输完成中断后就没有进到中断函数中去了。哪位大侠能告诉小弟这是怎么回事啊?


作者: 玉丫子    时间: 2008-6-19 09:51

我在论坛中上传有SEED的EDMA的链接的工程,你可以去下载看看


作者: colortang    时间: 2008-6-19 16:11     标题: 回复 6# luzhipei 的帖子

貌似是这样的。
不过我感觉在传输完成后,这些参数还在,不需要重新设置LINK啊,望高人解答


作者: luzhipei    时间: 2008-6-20 10:28     标题: 回复 8# 玉丫子 的帖子

你好 请问你说的SEED的EDMA的链接的工程
是不是在资料区的合众达6713 EDMA实验例程啊


作者: initial5    时间: 2008-6-20 14:36     标题: 回复 1# luzhipei 的帖子

"This function links two EDMA transfers together by setting the LINK field of the
parent‘s RLD parameter appropriately. Both parent and child handles may be
from EDMA_open(), EDMA_allocTable(), or a combination of both.
parent->child
Note: This function does not attempt to set the LINK field of the OPT
parameter; this is still up to the user."
以上这段话来自于TI SPRU401的161页,意思应该是说EDMA_LINK()这个函数通过设置parent 参数表中的RLD的LINK部分的值为child参数表的地址的低16位将两个EDMA句柄(来源于EDMA_open()或 EDMA_allocTable()的返回值)链接起来。因为LINK操作能够成功的前提是参数表中OPT的LINK位被置位(见TI SPRU234的44页),因此最终能否实现LINK操作,还要由用户自己去配置OPT中的LINK位(置1即允许LINK操作)。


作者: luzhipei    时间: 2008-6-24 09:15

请问怎么样结束EDMA传输啊
是用EDMA_DISABLE()就可以了;还是将EDMA 链接到一个NULL的参数表?


作者: initial5    时间: 2008-6-25 14:56     标题: 回复 12# luzhipei 的帖子

//Stops the EDMA service.
void stopEdma(void)
{
    //Disable interrupts, close EDMA channel before exit of the program
    IRQ_disable(IRQ_EVT_EDMAINT);
    EDMA_RSET(CCER,0x00000000);
    EDMA_disableChannel(hEdma);
    EDMA_intDisable(TCCINTNUM);
    EDMA_intClear(TCCINTNUM);

EDMA_close(hEdma);
        EDMA_resetAll();
        EDMA_RSET(CIPR,0xFFFFFFFF);
        EDMA_RSET(ECR,0xFFFFFFFF);
}

这是TI的一段例程,用于结束EDMA传输,希望能对LZ有帮助,EDMA_DISABLE()不是CSL函数。


作者: whx8880    时间: 2008-6-27 08:46

这种方法很全面,我都是链接到一个空的参数表


作者: ericxl06    时间: 2008-6-27 18:42

很多也不明白,受教了,学习中, 

C6000 EDMA 使用心得总结相关推荐

  1. 【DSP开发】C6000非多核非KeyStone系列DSP中断系统

    C6000系列DSP的中断系统 上一篇介绍了C6455的GPIO系统,最后把GPIO4配置成了中断/事件模式,本文将介绍C6455的中断系统,介绍完基本概念后,给出把GPIO4映射到INT4的代码. ...

  2. C6748对EDMA的操作和通过EMIFA与FPGA传输数据

    EDMA的PSC初始化 PSC即power and sleep controller void PSCInit(void) {// 使能 EDMA3CC_0PSCModuleControl(SOC_P ...

  3. c6000引导加载_C6000DSP的引导方式和bootloader

    C6000DSP的引导方式 C6000DSP的引导方式和bootloader C6000是TI的高端DSP,它有3种引导方式:㈠无引导: ㈡ROM引导: ㈢主机引导 ㈠ – 无引导:CPU直接从地址0 ...

  4. Java EE学习心得

    –Java EE学习心得   1.    称为编程专家的秘诀是: 思考-----编程--------思考------编程--.. 编程不能一步到位,不能一上来就编,必须先思考如何写,怎样写?然后再编程 ...

  5. 测试心得:微图书销售小程序

    测试心得:微图书销售小程序 前言 这个学期差不多也将近结束,经过大半个学期,从项目需求的确认和项目文档的编写,到一步步的设计与实现,现在终于到了测试阶段,但是我们在测试阶段也暴露出了很多bug,但是每 ...

  6. java.lang.OutOfMemoryError:GC overhead limit exceeded填坑心得

    该文章出自:http://www.cnblogs.com/hucn/p/3572384.html 分析工具:http://www.blogjava.net/jjshcc/archive/2014/03 ...

  7. 计算机财务应用实验心得,计算机会计实习心得-20210628124643.doc-原创力文档

    计算机会计实习心得 计算机会计实习心得1 毕业实践环节是大学生在完成全部课程后.走向社会之前最真实的一个模拟实验,对于我们财会专业的学生,平时注意注重理论学习,缺乏实践锻炼,因此实习显得尤为重要.在本 ...

  8. html5考试总结300字,期中考心得300字5

    为了检验学生半个学期所学的知识而进行的一次考试,有利于学生比较正式地检验自己平时的学习水平,根据这个成绩,学生可以及时的调整学习心态和方法,更有效率地进行下一阶段的学习,期中考试主要考察学生前半学期的 ...

  9. Assembly学习心得

    http://blog.csdn.net/etmonitor/ Assembly学习心得 说明: 最近开始准备把学到的.NET知识重新整理一遍,眼过千遍不如手过一遍,所以我准备记下我的学习心得,已备参 ...

最新文章

  1. 如何快速取消所有文件夹共享?进来瞧瞧
  2. 【怎样写代码】参数化类型 -- 泛型(一):泛型概述
  3. 手机吸费软件肆意捞金,通过代码签名证书加以防范
  4. 检查是否已使用jQuery选中复选框
  5. Redis和Memcache的区别总结
  6. 一篇文章带你从认识Python装饰器到熟练使用
  7. python长整型字节数_Python将整数转换为16字节字节
  8. 生产可用:是时候来一个微前端架构了!
  9. HDU- 2973 YAPTCHA(威尔逊定理)
  10. SharePoint 2013 - Sideloading
  11. [react] 请描述你对纯函数的理解?
  12. Redis学习---(10)Redis 集合(Set)
  13. 使用Dockerfile为SpringBoot应用构建Docker镜像
  14. A-AUTOバッチ管理ツール(HOLD之后,如何再次启动)
  15. springboot2 - 坑 - 解决put提交接收不到参数的问题
  16. 学生信息的顺序表存储
  17. 奔跑吧恐龙-JAVA从入门到精通
  18. 手机b站封面提取网站_B端网站SEO优化思路:外链SEO与站内SEO优化结合才有效
  19. apk分包思路(一)meta-data
  20. IDEA打开多个项目

热门文章

  1. 分治法——最近点对问题
  2. 稍微聊聊vue3的函数式编程
  3. 论文阅读——Segmenting Medical MRI via Recurrent Decoding Cell
  4. ModuleNotFoundError: No module named ‘tensorflow.compat.v2‘解决方法
  5. Revit族添加数据的方式
  6. 查看redis当中缓存的内容的命令
  7. java-net-php-python-59jspm职工工作量统计系统计算机毕业设计程序
  8. 华中师范大学心理学专业考研上岸经验分享
  9. 刷脸支付人脸识别技术是一把双刃剑
  10. 一周技术学习笔记(第68期)-像练习硬笔书法那样写代码