DMA控制器三大核心机制:调试模式、电源管理与FIFO缓冲详解

发布时间:2026/7/19 8:41:12
DMA控制器三大核心机制:调试模式、电源管理与FIFO缓冲详解 1. 项目概述深入理解DMA控制器的三大核心机制在嵌入式系统开发尤其是涉及高速数据流处理如音频采集、图像传感器数据搬运、网络包转发的场景里直接内存访问控制器DMA的性能和稳定性直接决定了整个系统的效率上限。很多开发者对DMA的认知可能还停留在“配置源地址、目的地址和传输长度”的层面一旦遇到数据传输错乱、系统功耗异常或调试时DMA行为“失控”的问题往往无从下手。实际上一个成熟的DMA控制器远不止是一个简单的“数据搬运工”。它内部集成了精细的状态机、复杂的仲裁逻辑以及多种服务于系统级需求的辅助机制。最近在调试一个基于TI某款MCU的高速数据采集项目时我就深刻体会到了深入理解DMA调试、电源管理和FIFO缓冲机制的重要性。项目初期我们遇到了DMA在调试器单步执行时数据丢失、系统低功耗模式下DMA无法唤醒以及在高带宽数据流切换时产生额外延迟等问题。解决这些问题的过程实际上就是对DMA控制器这三个“非核心”但至关重要的功能模块进行一次彻底的摸底。本文将结合TI官方技术手册中的核心描述以一名嵌入式工程师的视角拆解DMA控制器的调试模式行为、电源管理策略以及FIFO缓冲区的工作原理。我会重点分享这些机制在实际项目中如何配置、会产生什么影响以及我们踩过哪些坑、总结出哪些调试和优化技巧。无论你是正在评估芯片选型还是已经深陷DMA相关问题的调试泥潭希望这些从一线项目中提炼出的经验能为你提供清晰的思路和实用的解决方案。2. DMA调试模式详解让数据搬运过程“可视化”调试嵌入式系统时最让人头疼的莫过于那些在后台默默运行、状态难以捕捉的模块DMA就是典型代表。当你的应用出现数据错位、丢失而CPU代码逻辑又看似无误时问题很可能出在DMA传输的中间状态。这时DMA控制器提供的调试模式就成了我们定位问题的“手术刀”。2.1 四种挂起行为控制调试的“暂停点”根据手册描述该DMA控制器在调试挂起模式下支持四种可配置的行为。这不仅仅是“暂停”和“继续”那么简单不同的行为适用于不同的调试场景理解其差异是有效调试的第一步。1. 在DMA通道仲裁边界立即停止这是最“强硬”的停止方式。当调试器发出挂起信号时DMA控制器不会等待当前的数据单元Element传输完成而是会在完成当前正在进行的总线事务后立刻在通道仲裁边界停下。什么是仲裁边界简单说就是DMA完成一个通道的当前传输任务准备决定下一个服务哪个通道的决策点。手册中的Table 8-2和Table 8-3定义了不同模式下的仲裁边界。在非旁路模式下仲裁发生在FIFO为空时在旁路模式下仲裁可以发生在单个数据元素粒度。选择此模式你能获取到DMA刚完成一次传输、即将切换通道时的精确快照适合检查通道调度顺序和优先级逻辑是否正确。2. 完成当前帧传输后停止帧传输是DMA的一种工作模式通常一个帧包含多个数据块。选择此模式后DMA会继续运行直到当前活跃通道的整个帧传输完毕才会进入挂起状态。这非常有用比如当你需要确保一个完整的数据包例如一帧图像数据、一段完整的音频采样被完整地搬运到内存后再检查内存内容是否正确。它避免了在帧传输中间暂停导致的数据结构不完整便于进行整体校验。3. 完成当前块传输后停止块传输是比帧更小的粒度。在此模式下DMA会完成当前正在传输的数据块然后挂起。这比“完成帧传输”的粒度更细允许你在一个帧内部的某个逻辑块传输完成后进行检查适用于调试复杂的数据流分段处理逻辑。4. 忽略挂起顾名思义即使调试器发出了挂起请求DMA也完全无视继续像在正常功能模式下一样工作。这个模式主要用在需要持续监控数据流、同时又不想打断DMA操作的场景比如配合观察点Watch Point功能在特定内存地址被访问时再触发调试事件而不是主动暂停。实操心得模式选择策略在实际调试中我通常这样选择排查通道调度问题用“模式1”验证某个完整数据段如一帧的传输结果用“模式2”精细分析数据流内部处理逻辑用“模式3”。切忌一直使用“模式4”否则你可能永远抓不到DMA的瞬时状态。一个常见的坑是在IDE中默认的调试配置可能不会主动设置DMA的调试行为导致你以为单步执行时DMA会停其实它还在跑数据已经变了。务必在调试前通过对应的调试控制寄存器确认或设置好所需模式。2.2 挂起期间的内部状态与观察点机制当DMA进入挂起模式忽略模式除外有一个关键细节控制器会持续采样外部的硬件DMA请求但通道挂起寄存器的状态会被冻结不再更新。这意味着所有在挂起期间到达的请求都会在挂起结束后一次性反映到挂起寄存器中。这个机制保证了请求不会丢失但调试时需要注意你读到的挂起寄存器状态可能不是“实时”的而是挂起开始前那一瞬间的快照加上结束后新请求的集合。为了更精准地调试DMA提供了观察点寄存器和观察掩码寄存器。这堪称DMA调试的“断点”功能。你可以配置它们来监视一个特定的地址或者一个地址范围。当DMA的访问地址匹配了你设定的观察条件例如目的地址到达了某个缓冲区末尾DMA会立即冻结其所有内部状态并向主机CPU发出一个调试请求信号。此时你可以从容地检查DMA的所有寄存器、FIFO内容以及相关的内存数据。避坑指南观察点的使用技巧地址对齐确保你设置的观察点地址与DMA访问的地址对齐方式一致如32位对齐。不对齐的地址可能永远不会被触发。范围设置用观察掩码寄存器可以设定一个范围。例如掩码设置为0xFFFFF000观察点设为0x20001000那么任何访问0x20001xxx地址区的操作都会触发。这对于监视一片缓冲区非常有效。结合调试器触发调试请求后需要你的调试器如JTAG/SWD能够捕获这个信号并暂停CPU。请确认你的调试工具链支持这种外设触发的调试事件。性能影响频繁触发观察点可能会影响DMA的实时性仅建议在问题定位阶段使用。3. DMA电源管理在性能与功耗间寻找平衡在电池供电或对功耗敏感的嵌入式设备中每一个模块的功耗都需斤斤计较。DMA控制器虽然效率高但其内部时钟、逻辑和总线接口在运行时也会消耗可观的能量。因此其电源管理机制直接关系到系统的整体功耗表现。3.1 运行模式与睡眠模式该DMA控制器提供了两种主要的电源管理模式运行模式和睡眠模式。运行模式DMA完全上电所有功能可用随时响应请求。这是高性能数据传输时的状态。睡眠模式这是一个智能的节能状态。当DMA检测到没有待处理的通道在等待服务即挂起寄存器为空且没有正在进行的传输时它会自动进入睡眠模式关闭大部分内部电路以降低功耗。一有新的DMA请求无论是硬件还是软件触发到达DMA会立即唤醒并恢复正常操作。这种设计非常巧妙它使得DMA在空闲时几乎不耗电而在需要时又能做到“零延迟”响应。3.2 系统级低功耗模式交互更复杂的是DMA与整个系统低功耗模式的交互。当系统模块例如电源管理单元发出一个全局低功耗模式请求时比如让芯片进入STOP或SLEEP模式DMA需要做出响应。其规则是如果DMA没有未决的请求它会向系统模块回复一个“确认”表示“我准备好了可以进入低功耗”。系统收到所有必要模块的确认后才会真正关闭时钟或降低电压。这里有一个至关重要的警告手册中用NOTE特别强调当DMA处于全局低功耗模式时其时钟是停止的。这意味着它根本无法检测任何外设产生的DMA请求。这是一个常见的系统设计陷阱。例如你希望系统在低功耗模式下通过UART接收一个字节来唤醒并配置了UART的DMA请求。如果系统进入了关闭DMA时钟的深度睡眠模式那么这个UART DMA请求将永远无法唤醒DMA进而无法唤醒系统。正确的做法是要么使用不关闭DMA时钟的低功耗模式要么使用其他能在无时钟下工作的唤醒源如GPIO边沿中断先唤醒系统和DMA时钟然后再处理数据。电源管理配置经验评估业务场景如果你的应用是间歇性爆发数据传输如传感器定时采集那么睡眠模式的节能效果会非常显著。如果是持续流式数据传输则睡眠模式可能很少被触发。注意唤醒链路在设计低功耗流程时务必画出一个“唤醒链路图”。确认从最底层的唤醒事件如定时器、引脚中断到模块时钟开启再到DMA启动这条路径是通的。DMA的睡眠模式唤醒是自动的但全局低功耗模式的唤醒需要系统级设计。寄存器保持通常进入睡眠或低功耗模式不会改变DMA的配置寄存器内容。但为了保险起见在初始化DMA后如果功耗模式切换非常频繁建议在关键配置完成后读取回关键寄存器如通道控制包验证其未被意外修改。4. FIFO缓冲区机制数据流平滑与性能的关键FIFO是DMA控制器内部一个经常被忽视但极其重要的组件。它不仅是数据的临时中转站更是协调源端和目的端速度差异、优化总线利用率和降低通道切换延迟的核心。4.1 FIFO基础结构与状态根据手册此DMA的FIFO深度为4级宽度为64位。这意味着它最多可以缓存4个64位的数据。其主要作用有两个数据打包和解包。例如当源端是8位外设而目的端是32位内存时DMA可以先将4个8位数据读入FIFO打包成一个32位数据再一次性写入内存这能显著减少总线事务数量。FIFO只有两种状态空和满。空FIFO内没有数据。满FIFO已被填满或者需要传输的元素计数已归零。在“满”状态下读操作必须停止对于源FIFO或写操作必须停止对于目的FIFO。一个关键规则是DMA通道的切换只能在FIFO为空时进行。这决定了通道仲裁的时机——仲裁逻辑只会在一个通道的传输任务将FIFO清空后才去决定下一个服务哪个通道。这保证了数据在通道间的隔离性避免了一个通道的数据“污染”下一个通道。4.2 旁路模式用灵活性换取实时性FIFO虽好但有时我们却需要绕过它。DMA提供了旁路模式通过配置端口控制寄存器中的对应位即可启用。当旁路模式开启时FIFO的深度被限制为仅能容纳一个数据元素。也就是说DMA每从源端读取一个元素就会立即启动向目的端的写入几乎不缓冲。旁路模式的核心价值在于最小化通道间的切换延迟。因为通道切换只能在FIFO为空时发生在旁路模式下FIFO几乎总是“读一个就空”从而允许仲裁器更快地响应其他通道的请求。这对于需要快速响应多个低延迟、小数据量传输请求的应用例如快速切换多个SPI从设备进行少量数据交换非常有用。然而手册也明确指出了旁路模式的代价无法最优地利用总线带宽。我们来看手册中的Table 8-2和Table 8-3它清晰地对比了非旁路和旁路模式下不同读写元素大小时DMA控制器在仲裁前能执行的最大读写事务数。以源端读元素为8位目的端写元素为32位为例非旁路模式FIFO深度为464位相当于8个8位元素。DMA可以连续读取8个8位数据在FIFO中组合成2个32位数据然后执行2次32位写操作。所以在仲裁发生前它执行了8次读2次写表8-2中对应位置为“8 read 1 write”这里1 write是针对64位目的对于32位目的8个8位源数据正好组成2个32位数据因此是2次写。表格是按64位FIFO宽度计算的需结合具体元素大小理解其打包过程。旁路模式FIFO深度为1个元素。DMA读1个8位数据就需要尝试写。但目的端是32位1个8位数据不足以构成一次32位写。因此它必须等待凑齐4个8位数据。实际上旁路模式下为了完成一次32位写它需要连续进行4次8位读但每次读后FIFO不为空不能切换通道直到凑齐4次然后进行1次32位写。从通道切换的粒度看它需要完成这“4读1写”的整体操作后才能切换。表格8-3中对应位置为“4 read 1 write”这反映了完成一次有效“传输单元”所需的事务数而这个“传输单元”就是通道切换的边界。结论就是旁路模式牺牲了通过大FIFO进行批量打包/解包带来的总线效率换来了更细粒度的通道切换能力从而降低了高优先级请求的响应延迟。FIFO与旁路模式选型建议默认用FIFO对于大多数大数据量、连续传输的场景如内存到内存拷贝、ADC连续采样保持FIFO启用是最佳选择它能最大化总线带宽利用率。考虑旁路模式当系统中有多个需要极低延迟响应的外设。每个DMA传输的数据量都很小小于或等于总线位宽。通道切换频率非常高且对切换延迟敏感。混合使用在一些复杂的DMA控制器中可以为不同端口独立配置是否旁路。例如从高速外设如摄像头接口读取数据到内存的端口启用FIFO以优化吞吐而从内存发送控制命令到多个低速外设的端口启用旁路以降低切换延迟。5. 通道链式触发与内存保护机制除了上述三大核心机制手册中还提到了两个高级功能通道链式触发和内存保护。它们在构建复杂、健壮的DMA应用时扮演着重要角色。5.1 通道链式触发构建自动化数据流通道链式触发允许一个DMA通道在完成传输后自动触发另一个或一组通道开始工作而无需任何外部硬件请求或CPU软件干预。这就像设置了一个多米诺骨牌启动第一个后续的传输流程会自动依次进行。实现方式是通过配置通道控制寄存器中的Chain[5:0]字段。例如你可以将通道1设置为由通道0链式触发。当通道0完成其传输任务一帧或一块取决于其触发类型配置后通道1的请求会自动被置入通道挂起寄存器等待仲裁服务。手册中的例子很说明问题假设CH1、CH2、CH4、CH5被同时触发而CH3被链式连接到CH1。尽管CH3是由CH1触发的但它仍然需要遵循仲裁规则。最终的服务顺序可能是 CH1 - CH2 - CH3 - CH4 - CH5。链式触发影响的是“触发”的时机而不是“仲裁优先级”。被链式触发的通道会像普通通道一样进入挂起队列按其自身的优先级参与调度。这个功能非常强大可以用于实现复杂的数据处理流水线。例如通道0负责从ADC搬运原始数据到缓冲区A完成后链式触发通道1由通道1将缓冲区A的数据进行搬移或预处理到缓冲区B再链式触发通道2将处理后的数据发送出去。整个过程完全由DMA自主完成CPU只需在流水线末端等待完成中断即可。链式触发配置要点提前使能手册强调所有参与链式触发的通道其通道控制寄存器必须在第一个DMA请求被触发前就完成配置和使能。不能在通道0运行过程中才去配置通道1的链式触发这可能导致触发失败或行为不可预测。避免循环链严禁配置成A链BB又链A或更长的循环。这会导致DMA进入死循环无法服务其他通道。理解触发类型链式触发依赖于源通道的完成事件。务必清楚源通道的触发类型是“帧完成”还是“块完成”这决定了链式触发发生的时刻。5.2 内存保护为系统稳定性加装护栏DMA控制器通常拥有访问整个设备地址空间的权限。这是一个强大的能力但也伴随着风险一个错误配置的DMA通道如地址指针溢出可能会覆盖关键代码区、栈空间或其他外设的寄存器导致系统崩溃且这种错误极难追踪。该DMA控制器提供了内存保护机制允许软件定义最多四个受保护的内存区域并为每个区域设置不同的访问权限完全访问、只读、只写、禁止访问。当DMA试图以违反权限的方式访问受保护区域时控制器会停止该通道并可以产生一个中断通知CPU。配置流程如下定义区域通过DMAMPRxS和DMAMPRxE寄存器对x为0-3分别设置每个保护区域的起始和结束地址。设置权限在DMAMPCTRL寄存器中为每个区域配置访问权限。使能中断在DMAMPCTRL中使能保护违规中断。处理违规当违规发生时DMAMPST状态寄存器中的标志位会被置起相应通道被停止。在中断服务程序中可以读取状态寄存器确定是哪个区域发生了何种违规并采取恢复或错误上报措施。手册还特别提醒了一个重要规则如果定义的保护区有重叠则编号小的区域如Region 0的权限优先级更高。这在划分复杂的内存保护地图时需要仔细规划。内存保护实战技巧保护关键数据至少应将中断向量表、操作系统内核数据区、栈顶区域设置为“禁止访问”。保护只读区域将存放常量、代码的Flash区域设置为“只读”防止DMA误写。用于调试在调试疑似内存越界的DMA问题时可以故意将疑似被破坏的内存区域设置为“禁止访问”。一旦DMA触犯立刻会触发中断并停止你就能精准定位到是哪个通道、在访问哪个地址时出了问题。性能考量内存保护检查会增加一点点访问延迟。在对延迟极度敏感的场景需评估其影响。6. 奇偶校验与RAM初始化确保数据完整性在要求高可靠性的系统中数据在传输和存储过程中的完整性至关重要。该DMA控制器内置了对控制包RAM的奇偶校验支持这为检测因噪声、辐射或硬件故障导致的单比特错误提供了有力工具。6.1 奇偶校验工作原理控制器对控制包RAM实施按字节的奇偶校验。这意味着存储在RAM中的每一个字节数据都对应有一个奇偶校验位。校验的规则偶校验或奇校验由一个位于系统模块中的4位全局密钥统一控制确保整个芯片内使用奇偶校验的模块行为一致。复位后默认为奇校验。在DMA模块内部可以通过奇偶控制寄存器独立地启用或禁用校验功能。当执行读操作时无论是DMA状态机读取还是CPU读取硬件都会根据读出的数据实时计算奇偶值并与存储在奇偶校验位中的正确值进行比较。一旦发现不匹配就会产生一个奇偶错误中断并且出错的地址会被捕获并锁定在DMAPAR寄存器中直到被主机读取这为调试提供了关键线索。错误处理取决于访问者DMA读取控制包RAM出错DMA将不会执行该请求所要求的传输。CPU读取控制包RAM出错CPU仍然能读到数据但会同时产生奇偶错误中断。这意味着软件能感知到错误但拿到的数据可能是错的。6.2 奇偶测试与RAM初始化为了验证奇偶校验功能本身是否正常工作控制器提供了测试模式。通过设置奇偶控制寄存器中的TEST位奇偶校验位存储区会被映射到特定的地址空间。此时软件可以手动写入错误的奇偶值然后读取对应的控制包数据观察是否能正确触发奇偶错误中断。这是一种自检机制。一个至关重要的步骤是RAM初始化。上电后RAM包括数据位和奇偶校验位的内容是随机的、不确定的。如果不进行初始化第一次读取RAM时随机的奇偶校验位几乎必然与随机数据计算出的奇偶值不匹配导致一上电就触发大量奇偶错误。初始化有两种方法软件初始化在启用奇偶校验功能前由软件向控制包RAM写入已知的数据。写入时硬件会自动计算并更新对应的奇偶校验位。这是最常用的方法。硬件自动初始化某些芯片的架构支持在上电或复位时由硬件自动将片上SRAM初始化为全0。如果采用这种方式需要根据全局选择的奇偶校验规则奇/偶确保硬件计算的奇偶校验位是正确的。通常全0数据的奇校验位是1偶校验位是0。奇偶校验配置与排错清单上电后先初始化RAM在使能任何DMA通道或开启奇偶校验前务必先向所有DMA控制包RAM写入确定值通常是0或某种已知模式。再使能奇偶校验初始化完成后再通过奇偶控制寄存器使能校验功能。理解错误处理策略根据ERRA位的配置决定发生奇偶错误时是仅报告错误并停止传输还是彻底关闭DMA。在关键任务系统中可能选择后者以防止错误扩散。测试模式验证在产品出厂测试或系统自检中加入奇偶测试模式的检查确保该安全机制本身有效。地址锁定发生错误时DMAPAR寄存器锁定的地址是定位问题的关键。结合代码查看是哪个通道的控制包地址出错能快速定位到是哪个DMA任务配置出了问题。7. 核心寄存器精讲与实战配置示例理解了原理最终都要落到寄存器配置上。手册中列出了数十个寄存器这里我们聚焦几个最核心、最易出错的并结合实际代码片段讲解。7.1 全局控制与调试寄存器GCTRL (全局控制寄存器偏移 0h)这是DMA的总开关和调试行为控制中心。DMA_EN (位16)DMA总使能位。任何通道操作前必须置1。DEBUG_MODE (位9-8)这就是我们前面讲的调试模式选择位。00: 忽略挂起01: 完成当前块传输后停止10: 完成当前帧传输后停止11: 在仲裁边界立即停止DMARES (位0)软件复位位。写1复位DMA状态机和所有控制寄存器注意控制包RAM内容不会被复位。这是一个重要的安全操作在DMA配置出现混乱时可以先复位再重新配置。DCTRL (调试控制寄存器偏移 180h) WPR/WMR (观察点/掩码寄存器)这些寄存器用于实现更高级的调试功能。DCTRL可能包含控制调试请求生成、单步等更细致的位域具体需参考完整手册。WPR和WMR则用于设置我们之前讨论的观察点地址和掩码。7.2 通道使能与优先级寄存器HWCHENAS / HWCHENAR (硬件通道使能置位/复位寄存器)SWCHENAS / SWCHENAR (软件通道使能置位/复位寄存器)这是两对“置位-复位”寄存器用于独立控制每个通道的硬件触发和软件触发使能。例如向HWCHENAS的bit5写1就使能了通道5的硬件DMA请求响应。向HWCHENAR的bit5写1则禁用它。这种设计方便原子操作。CHPRIOS / CHPRIOR (通道优先级置位/复位寄存器)用于设置通道的优先级高/低。DMA内部通常有两个仲裁队列高优先级和低优先级。仲裁器会优先服务高优先级队列中的待处理通道只有在高优先级队列为空时才会服务低优先级队列。同一优先级队列内部通常采用轮询或固定优先级调度。7.3 一个完整的DMA传输配置流程示例假设我们要配置通道2从ADC数据寄存器外设地址0x40038000传输100个16位数据到内存数组adc_buffer地址0x20001000采用硬件请求ADC转换完成触发使用标准FIFO模式。// 1. 定义控制包数据结构通常位于特定RAM区域 typedef struct { volatile uint32_t srcAddr; volatile uint32_t dstAddr; volatile uint32_t transferCount; // 低16位为元素数量 volatile uint32_t control; // 包含元素大小、地址增量、触发类型等 } DMA_ControlPacket_t; // 假设控制包基地址为 0x2000C000 #define DMA_CP_BASE ((DMA_ControlPacket_t *)0x2000C000) // 2. 初始化控制包 (通道2的控制包假设在基地址偏移处) DMA_ControlPacket_t* cp DMA_CP_BASE[2]; cp-srcAddr 0x40038000; // ADC数据寄存器地址 cp-dstAddr (uint32_t)adc_buffer; // 目标内存地址 cp-transferCount 100; // 传输100个元素 cp-control (0x1 0) // 使能通道 | (0x1 1) // 源地址固定外设 | (0x0 2) // 目的地址递增 | (0x1 4) // 源数据宽度16位 | (0x1 6) // 目的数据宽度16位 | (0x0 8) // 使用块传输模式TTYPE | (0x1 12); // 硬件触发模式 // 3. 配置DMA请求分配将ADC的硬件请求线映射到通道2 // 假设ADC的DMA请求线编号是5 volatile uint32_t* DREQASIx (uint32_t*)(DMA_BASE 0x54); // DREQASI0寄存器地址 // 需要根据通道2所在的寄存器DREQASI0或DREQASI1等和位域进行配置 // 此处为示意假设通道2的分配位在DREQASI0寄存器的[13:8] *DREQASIx ~(0x3F 8); // 清零通道2的分配位 *DREQASIx | (5 8); // 将请求线5分配给通道2 // 4. 使能通道的硬件触发 volatile uint32_t* HWCHENAS (uint32_t*)(DMA_BASE 0x14); *HWCHENAS | (1 2); // 使能通道2的硬件触发 // 5. 可选设置通道优先级 volatile uint32_t* CHPRIOS (uint32_t*)(DMA_BASE 0x34); *CHPRIOS | (1 2); // 将通道2设为高优先级 // 6. 全局使能DMA volatile uint32_t* GCTRL (uint32_t*)(DMA_BASE 0x00); *GCTRL | (1 16); // 置位DMA_EN // 此后当ADC转换完成并发出DMA请求时传输将自动开始。寄存器操作避坑指南顺序很重要务必先配置好控制包和请求分配再使能通道最后开启全局使能。顺序错乱可能导致不可预知的行为。“置位-复位”寄存器对HWCHENAS和HWCHENAR操作的是同一个物理寄存器的不同逻辑视图。向HWCHENAS写1置位向HWCHENAR写1清零。读取任何一个返回的都是当前使能状态。不要混淆。传输计数transferCount寄存器通常包含元素数量有时还包含帧数量。务必仔细阅读手册确认其格式。写错会导致传输量不符预期。控制字段位control寄存器中的TTYPE触发类型、AIM自动初始化等位对DMA行为影响巨大。例如如果希望ADC连续循环采样可能需要设置AIM位并在传输计数归零后自动重载控制包。