ATSAME51 DMAC内存转内存传输出现通道传输错误排查
ATSAME51 DMAC内存到内存传输TERR错误排查与修复
核心问题分析
你的代码触发DMAC传输错误(TERR位置位),主要有两个关键原因:
1. 描述符地址设置错误
ATSAME51的DMAC描述符中,SRCADDR和DSTADDR字段存储的是传输完成后的源/目标地址,而非起始地址。当前直接传入数组起始地址,会导致DMAC访问超出数组范围的内存,触发总线错误。
2. 描述符未按要求对齐
SAM系列芯片的DMAC要求描述符必须按32字节边界对齐,否则会引发总线访问错误。你的描述符数组未显式指定对齐属性,编译器可能未按要求分配内存。
修复后的代码
#include "sam.h" #include <drivers/io.h> // 显式指定32字节对齐,符合DMAC描述符要求 __attribute__((aligned(32))) DmacDescriptor descriptorDmac[32]; __attribute__((aligned(32))) DmacDescriptor writeBackDmac[32]; uint8_t destArr[3]; uint8_t srcArr[3] = {0xAA, 0xBB, 0xCC}; int main(void) { ioSetPinDirOut(PORTB, LED_PIN); ioPinOutClr(PORTB, LED_PIN); DMAC->DBGCTRL.reg = 1; DMAC->BASEADDR.reg = (uint32_t)&descriptorDmac; DMAC->WRBADDR.reg = (uint32_t)&writeBackDmac; DMAC->CTRL.reg |= DMAC_CTRL_LVLEN0; DMAC->Channel[0].CHCTRLA.reg = DMAC_CHCTRLA_TRIGACT_TRANSACTION | DMAC_CHCTRLA_TRIGSRC_DISABLE | DMAC_CHCTRLA_RUNSTDBY; descriptorDmac[0].BTCTRL.reg = DMAC_BTCTRL_BEATSIZE_BYTE | DMAC_BTCTRL_VALID | DMAC_BTCTRL_DSTINC | DMAC_BTCTRL_SRCINC; descriptorDmac[0].BTCNT.reg = 3; // 设置为传输完成后的地址:起始地址 + 传输字节数 descriptorDmac[0].SRCADDR.reg = (uint32_t)(&srcArr[3]); descriptorDmac[0].DSTADDR.reg = (uint32_t)(&destArr[3]); // 先清除通道中断标志,避免干扰 DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTFLAG_TERR | DMAC_CHINTFLAG_TCMPL; DMAC->CTRL.bit.DMAENABLE = 1; DMAC->Channel[0].CHCTRLA.bit.ENABLE = 1; DMAC->SWTRIGCTRL.reg = DMAC_SWTRIGCTRL_SWTRIG0; // 使用宏定义更清晰 // 验证传输结果 if(destArr[0] == 0xAA && destArr[1] == 0xBB && destArr[2] == 0xCC) { ioPinOutSet(PORTB, LED_PIN); } else { // 传输失败,可添加额外调试逻辑 } while (1) { } }
额外注意事项
- 确保
io.h中的LED_PIN定义正确,避免调试逻辑干扰排查 - 调试时可先单独验证描述符对齐问题:添加对齐属性后如果错误消失,说明对齐是主要原因之一
- 每次触发传输前建议清除通道的中断标志位,避免旧的标志状态影响判断
内容的提问来源于stack exchange,提问作者Alex Jegers
相关产品推荐
相关产品推荐

