深入解析TI SDMA控制器:从寄存器映射到实战配置指南
1. 项目概述与SDMA核心价值在嵌入式系统开发尤其是涉及多媒体处理、高速数据采集或网络通信的场景里CPU常常被大量、重复的数据搬运任务所拖累。想象一下一个摄像头模块每秒产生数十兆的原始图像数据如果每一帧的每个像素都需要CPU亲自从外设寄存器读到内存再从内存写到显示缓冲区那CPU基本就“废了”什么复杂的图像算法、业务逻辑都别想跑了。这时候DMADirect Memory Access直接内存访问控制器就扮演了“数据搬运工”的角色它能在CPU“打盹”或处理其他任务时独立完成内存与外设之间、或内存不同区域之间的大块数据搬运。德州仪器TI在其许多高性能应用处理器如OMAP、AM系列中集成了其System DMASDMA控制器。这个SDMA可不是一个简单的、只能做线性搬运的DMA它是一个高度可配置、功能强大的数据搬运引擎。它支持多达32个独立的逻辑通道每个通道都可以独立配置源地址、目的地址、传输量、传输模式甚至支持复杂的二维2D寻址、硬件事件同步、通道自动链接Chaining等高级功能。对于驱动工程师和系统架构师而言深入理解SDMA的寄存器映射和配置逻辑是榨干硬件性能、设计出高效稳定系统的关键一步。本文就将带你深入TI SDMA控制器的内部从寄存器地图开始一步步拆解其通道配置、数据传输的原理与实操要点。2. SDMA控制器整体架构与寄存器映射解析要驾驭SDMA这头“猛兽”第一件事就是拿到它的“地图”——寄存器映射表。这份表格定义了软件驱动与硬件SDMA控制器交互的所有接口。2.1 内存映射与实例基地址从你提供的资料中我们可以看到SDMA控制器在MPU主处理器视角下的内存映射。关键信息在于基地址Base Address。对于这个特定的SDMA实例Module Name: SDMA其寄存器空间的起始物理地址是0x4805 6000总大小为4KB。这意味着所有对SDMA的配置和状态查询都通过读写以这个地址为起点的内存区域来完成。这里有一个非常重要的概念偏移地址Offset Address。每个寄存器都有一个相对于基地址的固定偏移。例如全局的版本寄存器DMA4_REVISION的偏移是0x0000 0000那么它的完整物理地址就是0x4805 6000 0x0000 0000 0x4805 6000。对于通道相关的寄存器其偏移地址计算引入了通道索引i0到31。计算公式为0x0000 0080 i * 0x60。为什么是0x60十进制96这并非随意设定它意味着每个逻辑通道拥有一组独立的、连续的寄存器空间这组空间的大小是96字节。这种规整的布局非常有利于通过数组或结构体在软件中进行管理。例如通道10i10的通道控制寄存器DMA4_CCR10的偏移就是0x0000 0080 10*0x60 0x0000 03C0物理地址为0x4805 6000 0x03C0 0x4805 63C0。中断相关的寄存器则使用中断线索引j0到3。例如中断状态寄存器DMA4_IRQSTATUS_Lj的偏移计算为0x0000 0008 j * 0x4。注意在实际驱动开发中我们通常会定义一个指向基地址的指针然后通过“基地址偏移量”的方式来访问寄存器。务必确保你的内存映射ioremap或物理地址直接访问是正确的否则所有的配置都将无效甚至导致系统崩溃。2.2 关键全局寄存器精讲在深入每个通道之前有几个全局寄存器需要优先理解它们掌控着整个控制器的行为和能力。1. DMA4_REVISION (0x4805 6000)这是一个只读寄存器用于获取DMA控制器的版本信息主版本和次版本。在驱动初始化时读取此寄存器可以判断硬件版本以便对不同版本的芯片进行差异化处理或兼容性检查。2. DMA4_SYSSTATUS (0x4805 6028)最重要的位是第0位的RESETDONE。在软件或硬件复位控制器后必须轮询此位直到其变为1表示内部复位流程已完成控制器可以接受配置。在编写初始化函数时这是一个必不可少的步骤。3. DMA4_OCP_SYSCONFIG (0x4805 602C)这个寄存器控制SDMA模块与SoC内部互连OCP的接口行为涉及电源管理和时钟管理。SOFTRESET(位1)写1触发软件复位。硬件会在复位完成后自动清除此位。读操作总是返回0。AUTOIDLE(位0)置1启用OCP接口时钟的自动门控。当接口空闲时时钟可被关闭以节能。在追求极致低功耗的应用中需要开启。SIDLEMODE(位4:3) 和MIDLEMODE(位13:12)分别配置智能空闲Smart-idle和智能待机Smart-standby模式。例如SIDLEMODE0x2Smart-idle意味着只有当所有通道禁用、无挂起的同步请求、所有端口事务完成且无中断待处理时控制器才会响应空闲请求。合理配置这些模式对平衡性能和功耗至关重要。EMUFREE(位5)仿真相关。通常设置为0使得在仿真挂起MSuspend时DMA冻结内部逻辑方便调试。4. DMA4_CAPS_x 系列寄存器 (0x4805 6064 等)这些是能力Capabilities寄存器只读用于查询硬件支持的功能。例如DMA4_CAPS_2查询支持的寻址模式后递增、单/双索引、常量地址。DMA4_CAPS_3查询支持的同步能力元素、帧、块、包同步以及通道链式、交织能力。DMA4_CAPS_4查询支持的中断类型帧结束、块结束、包结束、传输错误等。在编写通用驱动时应先读取这些寄存器来动态适配硬件能力而不是写死配置。5. DMA4_GCR (0x4805 6078) - 全局控制寄存器这个寄存器用于高级资源分配策略。MAX_CHANNEL_FIFO_DEPTH(位7:0)分配给单个逻辑通道的最大FIFO深度。这决定了该通道一次能缓冲多少数据。必须注意此值不能为0且应大于或等于你配置的突发Burst传输大小。如果FIFO深度小于突发大小数据可能无法有效累积并发出导致传输停滞。HI_LO_FIFO_BUDGET(位15:14)在高优先级和低优先级通道之间分配全局FIFO预算。例如设置为0x3表示高、低优先级通道各占50%的FIFO资源。这用于实现服务质量QoS控制。ARBITRATION_RATE(位23:16)调整优先级通道队列和常规通道队列之间的仲裁切换频率。3. 逻辑通道的配置与核心寄存器详解SDMA的强大之处在于其多通道的独立性与灵活性。每个通道都像一条独立的生产线可以并行工作。配置一个通道本质上是配置它的一组寄存器。3.1 通道控制寄存器DMA4_CCRi—— 通道的“大脑”DMA4_CCRi是每个通道最核心的控制寄存器它决定了通道的基本工作模式。关键位域解析ENABLE (位7)通道总开关。重要原则在启用通道写1之前必须确保该通道的CSR状态寄存器和相应的中断状态位已被清除否则可能立即触发意外中断或错误行为。SRC_AMODE / DST_AMODE (位13:12 / 15:14)源和目的地址模式。这是SDMA灵活性的核心。0x0常量地址模式。每次传输后地址不变适用于访问固定寄存器如FIFO。0x1后递增模式。每完成一个元素传输地址自动增加一个元素的大小由DATA_TYPE决定。这是最常用的线性传输模式。0x2单索引模式。用于2D传输。在完成一行帧的所有元素后地址会加上一个“帧索引”值CSEIi或CDEIi跳到下一行的起始位置。0x3双索引模式。同样用于2D传输但更复杂它允许在行内和行间使用不同的索引值通常用于图像旋转等操作。FS / BS (位5 / 位18)帧同步Frame Sync和块同步Block Sync。这两个位组合定义了硬件同步的粒度。FS0, BS0元素同步。每个DMA请求触发传输一个元素。FS0, BS1块同步。每个DMA请求触发传输一个完整的块由多个帧组成。FS1, BS0帧同步。每个DMA请求触发传输一个完整的帧由多个元素组成。FS1, BS1包同步。每个DMA请求触发传输一个数据包。SYNCHRO_CONTROL (位4:0) 与 SYNCHRO_CONTROL_UPPER (位20:19)这7个位共同构成了同步控制字段用于指定该通道绑定到哪个硬件DMA请求线共127个。这里有一个极易出错的细节这个字段是1-based的。也就是说如果你想绑定到S_DMA_REQ_1这个硬件请求需要将这个字段设置为0x2请求号1。设置为0x0表示非同步软件触发传输。SEL_SRC_DST_SYNC (位24)选择同步源。当使用硬件同步时此位决定是由源端如摄像头传感器的请求触发传输还是由目的端如显示控制器的请求触发传输。这决定了数据流的方向控制权在谁手里。READ_PRIORITY / WRITE_PRIORITY (位6 / 位26)设置通道在读写端口仲裁中的优先级。高优先级通道能更快地获得总线访问权适用于实时性要求高的数据流。3.2 通道参数寄存器组 —— 定义传输“任务单”这组寄存器告诉SDMA数据从哪里来到哪里去有多少以什么格式搬运。DMA4_CSDPi (通道源/目的参数)DATA_TYPE(位1:0)数据类型。0x0-8位0x1-16位0x2-32位。这直接影响地址递增的步长。SRC_BURST_EN/DST_BURST_EN(位8:7 / 位15:14)设置读写端口的突发传输大小。支持单次、16字节、32字节、64字节突发。最佳实践为了最大化总线效率在内存到内存的传输中应将此值设置为SoC总线支持的最大值通常为64字节。在外设到内存的传输中需要匹配外设的FIFO深度或突发能力。WRITE_MODE(位17:16)写模式。0x0为非posted写写完成需要响应0x1为posted写无需等待响应更快。0x2是一个折中方案除最后一次传输外都使用posted写最后一次用非posted写可用于确保一系列写操作最终完成。SRC_ENDIAN/DST_ENDIAN(位21 / 位19)端序控制。当源和目的端序不一致时如小端处理器访问大端网络设备SDMA可以在传输过程中自动进行字节交换。地址与数量寄存器DMA4_CSSAi/DMA4_CDSAi源和目的起始地址。DMA4_CENi每个帧要传输的元素数量。DMA4_CFNi每个块要传输的帧数量。DMA4_CSEIi/DMA4_CDEIi源和目的的元素索引用于2D寻址。DMA4_CSFIi/DMA4_CDFIi源和目的的帧索引用于2D寻址或在包同步模式下其低16位用于定义包内的元素数量。一个典型的内存到内存线性传输配置示例假设我们要从地址0x8000 0000传输 1024 个 32-bit 数据到0x9000 0000。CEN 1024(一个帧包含1024个元素)CFN 1(只有一个帧即一个块)CSSA 0x80000000CDSA 0x90000000CSDP.DATA_TYPE 0x2(32-bit)CSDP.SRC_AMODE DST_AMODE 0x1(后递增)CSDP.SRC_BURST_EN DST_BURST_EN 0x3(64字节突发即一次传16个32-bit数据)CCR.FS 0, BS 0(非同步软件触发)CCR.SYNCHRO_CONTROL 0(非同步)3.3 通道链接与中断控制通道链接DMA4_CLNK_CTRLiENABLE_LNK位使能通道链接。NEXTLCH_ID指定当前通道传输完成后自动启用的下一个通道ID。这可以用于创建复杂的传输序列而无需CPU干预。例如可以配置通道0传输一帧YUV图像的Y分量完成后自动启动通道1传输U分量再自动启动通道2传输V分量。中断控制与状态DMA4_CICRi, DMA4_CSRi, DMA4_IRQSTATUS_Lj, DMA4_IRQENABLE_LjDMA4_CICRi通道中断控制寄存器。你可以使能特定事件的中断如帧结束(FRAME_IE)、块结束(BLOCK_IE)、传输错误(TRANS_ERR_IE)等。DMA4_CSRi通道状态寄存器。当事件发生时对应的状态位会被硬件置1。软件需要通过写1来清除这些状态位这是TI SDMA常见的设计模式。DMA4_IRQSTATUS_Lj中断线状态寄存器。它汇总了所有通道在特定中断线j上的中断状态。读取可以知道哪个通道触发了中断通过写1清除对应通道的中断状态位。DMA4_IRQENABLE_Lj中断线使能寄存器。用于屏蔽或取消屏蔽特定通道在中断线j上的中断。重要提示中断处理流程必须是“读取状态 - 处理 - 清除状态”的原子性操作。清除状态通常是通过向状态位写1实现。如果不清除会导致中断被重复触发。同时确保在启用通道中断前已正确配置了MPU的中断控制器将SDMA的中断线映射到正确的CPU中断向量。4. 实战配置一个硬件同步的DMA传输理论讲得再多不如动手配置一次。我们以一个常见的场景为例配置一个SDMA通道用于从MIPI CSI-2接口摄像头搬运图像数据到内存缓冲区采用硬件帧同步。4.1 场景分析与配置规划假设摄像头通过硬件信号线S_DMA_REQ_5在每一帧图像数据准备好时发出DMA请求。我们需要配置SDMA的一个通道例如通道0来响应这个请求。同步源摄像头源端同步所以CCR.SEL_SRC_DST_SYNC 1。同步粒度我们希望每来一个请求一帧有效信号就搬运一整帧图像数据。假设图像格式为RGB565一帧为800x600像素每个像素16-bit2字节。那么一帧有800*600480,000个像素即480,000 * 2 960,000字节。但SDMA以元素为单位DATA_TYPE设为16-bit所以一帧有480,000个元素。因此我们使用帧同步即CCR.FS1, BS0。寻址模式源地址摄像头数据端口通常是固定的FIFO或寄存器所以SRC_AMODE 0x0常量地址。目的地址是内存中的缓冲区需要线性递增所以DST_AMODE 0x1后递增。传输数量CEN 480000一帧的元素数CFN 1先只传一帧或设置为连续传输的帧数。绑定硬件请求使用S_DMA_REQ_5因此SYNCHRO_CONTROL字段应设置为5 1 6。4.2 分步配置流程与代码示意以下是基于C语言的伪代码配置流程假设已通过mmap或类似机制将SDMA寄存器空间映射到指针sdma_base。// 定义寄存器偏移宏以通道0为例 #define SDMA_CH0_OFFSET 0x80 #define REG_CCR(base, ch) (*(volatile uint32_t*)((uintptr_t)(base) 0x80 (ch)*0x60)) #define REG_CSDP(base, ch) (*(volatile uint32_t*)((uintptr_t)(base) 0x90 (ch)*0x60)) #define REG_CEN(base, ch) (*(volatile uint32_t*)((uintptr_t)(base) 0x94 (ch)*0x60)) #define REG_CFN(base, ch) (*(volatile uint32_t*)((uintptr_t)(base) 0x98 (ch)*0x60)) #define REG_CSSA(base, ch) (*(volatile uint32_t*)((uintptr_t)(base) 0x9C (ch)*0x60)) #define REG_CDSA(base, ch) (*(volatile uint32_t*)((uintptr_t)(base) 0xA0 (ch)*0x60)) #define REG_CICR(base, ch) (*(volatile uint32_t*)((uintptr_t)(base) 0x88 (ch)*0x60)) #define REG_CSR(base, ch) (*(volatile uint32_t*)((uintptr_t)(base) 0x8C (ch)*0x60)) void configure_camera_dma_channel(volatile void *sdma_base, int ch_num, uint32_t src_addr, uint32_t dst_addr) { // 1. 确保通道禁用 REG_CCR(sdma_base, ch_num) ~(1 7); // 清除ENABLE位 // 2. 清除可能存在的旧状态和中断标志 REG_CSR(sdma_base, ch_num) 0xFFFFFFFF; // 写1清除所有状态位 // 清除中断线状态假设使用中断线0 *(volatile uint32_t*)((uintptr_t)sdma_base 0x08) (1 ch_num); // 写1清除该通道在IRQSTATUS_L0中的位 // 3. 配置传输参数寄存器先配置这些最后再开启同步和控制 REG_CSSA(sdma_base, ch_num) src_addr; // 摄像头数据寄存器地址 REG_CDSA(sdma_base, ch_num) dst_addr; // 内存缓冲区地址 REG_CEN(sdma_base, ch_num) 480000 - 1; // 元素数量 (注意有些DMA控制器要求填N-1需查手册确认此处假设为实际值) REG_CFN(sdma_base, ch_num) 0; // 帧数 (0表示1帧需确认此处假设为实际帧数减1或直接帧数) // 4. 配置CSDP数据格式、突发、端序等 uint32_t csdp_val 0; csdp_val | (0x1 0); // DATA_TYPE 0x1 (16-bit) csdp_val | (0x3 7); // SRC_BURST_EN 0x3 (64字节突发) - 根据摄像头接口能力调整 csdp_val | (0x3 14); // DST_BURST_EN 0x3 (64字节突发) csdp_val | (0x0 12); // SRC_AMODE 0x0 (常量地址) csdp_val | (0x1 14); // DST_AMODE 0x1 (后递增) -- 注意位域需根据手册精确计算 // 更精确的位操作应使用预定义的位掩码和移位常量 REG_CSDP(sdma_base, ch_num) csdp_val; // 5. 配置中断使能帧结束中断 REG_CICR(sdma_base, ch_num) (1 3); // 设置FRAME_IE位 // 6. 配置CCR同步模式、请求线、使能通道 uint32_t ccr_val 0; ccr_val | (1 24); // SEL_SRC_DST_SYNC 1 (源同步) ccr_val | (1 5); // FS 1 (帧同步) ccr_val | (0 18); // BS 0 ccr_val | (6 0); // SYNCHRO_CONTROL 6 (对应S_DMA_REQ_5) // 注意SYNCHRO_CONTROL_UPPER位可能也需要设置 ccr_val | (1 7); // ENABLE 1 (最后才置位) REG_CCR(sdma_base, ch_num) ccr_val; // 7. 全局中断使能假设通道0映射到中断线0 *(volatile uint32_t*)((uintptr_t)sdma_base 0x18) | (1 ch_num); // 设置IRQENABLE_L0 }4.3 中断服务例程ISR处理当一帧数据传输完成SDMA会触发中断。在ISR中需要读取DMA4_IRQSTATUS_Lj确定是哪个通道产生中断。读取该通道的DMA4_CSRi确认是帧结束(FRAME)事件。处理数据例如通知上层应用一帧数据就绪。关键步骤写1清除CSRi中的FRAME状态位。写1清除IRQSTATUS_Lj中对应通道的状态位。如果需要连续传输重新设置目的地址或使用双缓冲区并可能重新使能通道如果传输完成后通道自动禁用取决于配置。void sdma_isr(int irq_line) { volatile uint32_t *irq_status_reg (uint32_t*)(sdma_base 0x08 irq_line*4); uint32_t status *irq_status_reg; for (int ch 0; ch 32; ch) { if (status (1 ch)) { // 通道ch产生了中断 uint32_t csr REG_CSR(sdma_base, ch); if (csr (1 3)) { // 检查FRAME位 // 一帧传输完成 frame_buffer_ready_callback(ch); // 回调处理函数 // 清除状态位 (写1清零) REG_CSR(sdma_base, ch) (1 3); // 可以为下一帧准备新的目标地址双缓冲切换 // REG_CDSA(sdma_base, ch) new_buffer_address; } // 清除中断线状态位 (写1清零) *irq_status_reg (1 ch); } } }5. 高级功能与性能调优要点5.1 二维传输与图像处理SDMA的双索引模式SRC_AMODE0x3/DST_AMODE0x3非常适合图像操作。例如实现图像裁剪或子区域访问CEN设置为子区域的宽度元素数。CFN设置为子区域的高度行数。CSSA设置为源图像中子区域的起始地址。CSEIi设置为源图像中从一行结尾到下一行开头需要跳过的字节数即(源图像宽度 - 子区域宽度) * 元素大小。CSFIi通常为0除非有更复杂的访问模式。目的端配置类似可以将子区域复制到一块连续的缓冲区。5.2 通道链式与交织链式Chaining通过CLNK_CTRLi寄存器配置。当通道完成当前传输后自动启用NEXTLCH_ID指定的下一个通道。这可以用于实现多阶段、无CPU干预的复杂数据传输流水线。交织Interleaving这不是一个独立的配置位而是一种行为。当多个通道同时使能且优先级相当时SDMA的仲裁器会在这些通道的读写请求间进行交织调度最大化总线利用率。通过合理设置READ_PRIORITY和WRITE_PRIORITY可以控制调度策略。5.3 性能调优与避坑指南对齐与突发确保源地址和目的地址与总线位宽和突发长度对齐通常是32或64字节边界。未对齐的访问会导致性能严重下降因为控制器可能将其拆分成多个单次传输。FIFO深度配置DMA4_GCR中的MAX_CHANNEL_FIFO_DEPTH需要仔细设置。设置过小无法隐藏内存访问延迟影响吞吐量设置过大可能浪费共享的FIFO资源影响其他通道。一个经验法则是将其设置为突发传输大小的2-4倍。内存带宽竞争当多个高优先级DMA通道与CPU激烈竞争内存带宽时可能导致系统卡顿。需要利用HI_LO_FIFO_BUDGET和优先级设置进行带宽分配和仲裁调优。电源管理协调在系统进入低功耗状态前必须确保所有DMA传输已完成并检查DMA4_SYSSTATUS和通道状态。错误地挂起一个正在活动的DMA控制器可能导致数据丢失或总线锁死。影子寄存器访问手册特别指出CSACi,CDACi,CCENi,CCFNi这几个运行时寄存器必须使用32位访问。如果使用8位或16位访问数据可能会损坏。这是因为内部有影子寄存器机制来保持32位值的完整性。在编写驱动程序时务必使用volatile uint32_t*指针来访问它们。调试技巧在调试DMA传输问题时CSACi和CDACi当前地址计数器以及CCENi和CCFNi当前元素/帧计数器是无价之宝。它们可以告诉你传输进行到了哪里。当传输卡住时检查这些寄存器的值是否在变化可以快速定位是请求未到来、总线错误还是配置错误。6. 常见问题排查与实战心得在实际项目中SDMA配置出错是常态。下面是一些典型的“坑”和排查思路。问题1DMA传输完全没启动。检查清单时钟与电源域确认SDMA控制器所在的电源域和时钟域已经使能。这是最容易被忽略的一点尤其在低功耗启动序列中。复位状态读取DMA4_SYSSTATUS的RESETDONE位确保为1。通道使能位确认CCRi.ENABLE已置1。传输数量确认CEN和CFN不为0。同步模式如果是软件触发非同步需要向通道写操作来启动具体方式需查手册有时是写CSR或特定寄存器。如果是硬件同步检查SYNCHRO_CONTROL配置是否正确1-based并用示波器或逻辑分析仪确认硬件DMA请求信号是否已到达芯片引脚并被正确复用Pin Mux。中断屏蔽如果依赖中断判断完成检查CICRi和IRQENABLE_Lj是否已正确使能。问题2DMA传输了错误的数据量或地址错乱。检查清单元素大小与地址模式核对CSDPi.DATA_TYPE。如果你以为是传输字节但配置成了16-bit那么实际传输的字节数会是预期的两倍地址递增步长也是两倍。2D索引计算对于2D传输仔细计算CSEIi和CSFIi或目的端索引。索引值是有符号数可以是负数以实现反向扫描。端序问题如果源和目的端序不一致且未启用ENDIAN转换数据内容会错乱。问题3DMA传输导致系统不稳定或偶尔卡死。检查清单内存区域确保源和目的内存区域是有效的、可访问的。特别是目的地址不能是只读内存或未映射的地址。缓存一致性如果CPU和DMA共享一块数据缓冲区必须处理好缓存一致性问题。在DMA写入数据到缓冲区后、CPU读取之前需要无效InvalidateCPU的数据缓存在CPU写完数据、DMA读取之前需要写回Clean/Flush数据缓存。许多SoC提供硬件缓存一致性互联如CCI但软件上仍需使用dma_alloc_coherent或dma_map_single等API来获取DMA安全的内存。总线错误检查CSRi寄存器中的错误状态位如TRANS_ERR,MISALIGNED_ADRS_ERR。这些错误可能由非法地址或访问权限引起。优先级与仲裁多个高优先级DMA通道可能饿死低优先级通道或CPU访问。调整HI_LO_FIFO_BUDGET和通道优先级。个人心得配置顺序我习惯遵循“先静态参数后动态控制”的顺序。即先配置地址、数量、数据格式等“任务单”寄存器CSSA,CDSA,CEN,CFN,CSDP再配置链接和中断CLNK_CTRL,CICR最后才配置控制寄存器CCR并置位ENABLE。在修改一个正在运行的通道配置前务必先禁用ENABLE0修改完成后再重新启用。防御性编程在驱动中每次配置通道前都读取一下关键能力寄存器CAPS确保硬件支持你要配置的模式。这能提高代码在不同型号芯片间的可移植性。利用监控寄存器在调试阶段将CSACi和CDACi的实时变化打印出来是判断DMA是否“活”着的最直接方法。如果它们不动说明传输未启动或已停止如果它们乱跳说明地址配置错误。TI的SDMA控制器是一个功能极其丰富的模块初次接触可能会被其众多的寄存器吓到。但只要你抓住“通道独立配置、同步事件驱动、寄存器即接口”这几个核心思想从最简单的内存到内存非同步传输开始实验逐步叠加硬件同步、2D传输、链式操作等高级功能就能逐渐掌握其精髓从而在嵌入式系统中设计出高效、可靠的数据搬运子系统。