ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

英飞凌 AURIX TC3xx DMA 入门(一):软件触发实现内存数据搬运

英飞凌 AURIX TC3xx DMA 入门(一):软件触发实现内存数据搬运 1. 前言在汽车嵌入式开发中DMADirect Memory Access直接存储器访问是一个非常常用的模块。像 ADC、DSADC、SPI、SENT 等外设在高频采集数据时如果全部依赖 CPU 中断读取数据再通过软件将数据复制到 Buffer 中会占用一定的 CPU 时间。DMA 的作用就是在不需要 CPU 逐个参与数据搬运的情况下由 DMA 硬件完成数据在不同地址之间的传输。对于刚开始学习 TC3xx DMA 的同学我个人比较推荐先从最简单的软件触发 DMA 搬运开始。因为软件触发暂时不涉及外设请求源SRC 路由DMA 硬件握手外设触发条件请求丢失中断链路这样可以先把 DMA 最核心的几个概念搞清楚Source AddressDestination AddressTransfer CountMove Size地址自增DMA Channel软件请求本文主要通过一个简单实验使用 TC3xx DMA通过软件触发的方式将一段 Source Buffer 搬运到 Destination Buffer。2. 实验目标本次实验目标如下定义两个 Bufferuint32 Dma_SourceBuffer[8]; uint32 Dma_DestinationBuffer[8];初始化 Source BufferDma_SourceBuffer[0] 0x11111111U; Dma_SourceBuffer[1] 0x22222222U; Dma_SourceBuffer[2] 0x33333333U; Dma_SourceBuffer[3] 0x44444444U; Dma_SourceBuffer[4] 0x55555555U; Dma_SourceBuffer[5] 0x66666666U; Dma_SourceBuffer[6] 0x77777777U; Dma_SourceBuffer[7] 0x88888888U;Destination Buffer 初始化为 0Dma_DestinationBuffer[0] 0U; Dma_DestinationBuffer[1] 0U; Dma_DestinationBuffer[2] 0U; Dma_DestinationBuffer[3] 0U; Dma_DestinationBuffer[4] 0U; Dma_DestinationBuffer[5] 0U; Dma_DestinationBuffer[6] 0U; Dma_DestinationBuffer[7] 0U;然后通过 DMA 软件请求将Dma_SourceBuffer ↓ DMA ↓ Dma_DestinationBuffer最终希望得到Source[0] 0x11111111 Destination[0] 0x11111111 Source[1] 0x22222222 Destination[1] 0x22222222 Source[2] 0x33333333 Destination[2] 0x33333333 ...3. DMA 软件触发到底是什么意思这里有一个很容易混淆的地方。所谓DMA 软件触发并不是 CPU 通过软件自己执行 memcpy。真正的数据搬运仍然是由 DMA 硬件完成。CPU 做的事情只是CPU | | 发起 Software Request ↓ DMA Channel | | DMA开始执行搬运 ↓ Source Address | ↓ Destination Address也就是说软件触发只是 DMA 请求的来源是软件。而 DMA 的搬运过程本身依然由 DMA 硬件完成。后续如果使用 DSADC、EVADC、SPI 等外设触发 DMA本质上只是Software Request换成Peripheral Hardware RequestDMA 后面的搬运逻辑并没有发生本质变化。4. DMA 搬运需要解决的几个核心问题在真正开始配置 DMA 之前先不要急着看几十个 DMA 寄存器。对于最基础的数据搬运只需要先回答下面几个问题。4.1 从哪里搬也就是Source Address例如Dma_SourceBuffer[0]4.2 搬到哪里也就是Destination Address例如Dma_DestinationBuffer[0]4.3 每次搬多少 Byte例如8 bit 16 bit 32 bit 64 bit如果这里使用uint32那么一次 Move 可以配置成32 bit即4 Byte4.4 一共搬多少次例如uint32 SourceBuffer[8];如果每次搬运一个 uint32一次 Move 4 Byte那么一共需要8 次 Move这就是 Transfer Count。4.5 地址搬完以后是否自动递增如果连续搬运数组SourceBuffer[0] SourceBuffer[1] SourceBuffer[2] SourceBuffer[3]那么 Source Address 必须自动递增。Destination 同样需要DestinationBuffer[0] DestinationBuffer[1] DestinationBuffer[2] DestinationBuffer[3]因此Source Address递增 Destination Address递增5. 软件触发 DMA 的整体数据流整个过程可以理解成CPU | | 配置 DMA Channel | | SADR | DADR | Move Size | Transfer Count | Address Increment | ↓ Software Request | ↓ DMA Channel | ↓ 读取 Source Data | ↓ DMA Bus Transfer | ↓ 写入 Destination Address | ↓ Transfer Count -- | ↓ 直到 Transfer Count 0 | ↓ DMA 搬运完成理解这张数据流图以后再去看寄存器会容易很多。6. DMA 中几个关键寄存器对于最基础的软件触发搬运我个人建议先重点关注以下几个寄存器。寄存器主要作用SADRSource AddressDADRDestination AddressCHCFGRChannel ConfigurationADICRAddress and Interrupt ControlTSRTransaction StateCHCSRChannel Control/Status不同 TC3xx 型号、手册版本以及驱动实现中部分字段名称可能存在差异因此实际项目中还是建议结合对应芯片 User Manual 确认。下面主要从使用角度理解这些寄存器。7. SADR —— 源地址SADR 用于配置 DMA 的源地址。例如Dma_SourceBuffer[0]地址可能是0x7000xxxx那么 DMA 的 Source Address 就需要指向Dma_SourceBuffer[0]可以简单理解SADR 数据从哪里读取例如DMA_SADR (uint32)Dma_SourceBuffer[0];实际代码需要根据具体寄存器定义进行调整。8. DADR —— 目标地址DADR 用于配置 Destination Address。例如DMA_DADR (uint32)Dma_DestinationBuffer[0];可以简单理解DADR DMA最终把数据写到哪里因此一个完整的数据路径就是SADR ↓ DMA ↓ DADR9. CHCFGR —— DMA Channel 配置CHCFGR 是 DMA Channel 中非常重要的配置寄存器之一。对于基础 DMA 搬运需要重点关注两类信息。9.1 Move SizeMove Size 决定DMA 一次搬多少数据。例如8 bit 1 Byte 16 bit 2 Byte 32 bit 4 Byte假设uint32 Dma_SourceBuffer[8];那么通常可以配置Move Size 32 bit每次 DMA Move 搬4 Byte9.2 Transfer Count假设uint32 Dma_SourceBuffer[8];总大小8 × 4 Byte 32 Byte如果Move Size 32 bit那么Transfer Count 8整个关系可以理解成总搬运数据量 Move Size × Transfer Count例如4 Byte × 8 32 Byte10. ADICR —— 地址变化方式ADICR 主要和地址控制以及中断相关配置有关。在最基础的数组搬运实验中非常重要的一点就是Source Address 和 Destination Address 搬运后如何变化。如果我们的数据是SourceBuffer[0] SourceBuffer[1] SourceBuffer[2] SourceBuffer[3]那么期望地址变化SourceBuffer[0] ↓ 4 Byte SourceBuffer[1] ↓ 4 Byte SourceBuffer[2]Destination 同理。因此通常需要配置Source Address Increment Destination Address Increment如果这里配置错误就可能出现一种典型现象Source地址一直不变最终变成Destination[0] Source[0] Destination[1] Source[0] Destination[2] Source[0] Destination[3] Source[0]或者 Destination 地址不递增Source[0] → Destination[0] Source[1] → Destination[0] Source[2] → Destination[0]最后 Destination[0] 只保留最后一次搬运的数据。所以地址递增配置是 DMA 调试中非常值得检查的一项。11. DMA 软件触发前面的参数都配置完成以后就可以通过 Software Request 启动 DMA。软件请求可以理解为CPU告诉DMA Channel X现在执行一次请求。然后 DMA 根据当前 Channel 配置SADR DADR Move Size Transfer Count Address Increment开始进行搬运。这里需要注意Software Request 本身并不包含“数据搬到哪里”等信息。这些内容在 DMA Channel 初始化阶段就已经配置好了。Software Request 做的事情只是触发这个已经配置好的 DMA Channel12. 下面我给大家分享一个简单的软件触发代码供大家参考此处我使用DMA_CH22通道进行示例代码演示#include IfxDma_reg.h #define DMA_CH22_DADR (*(volatile Ifx_DMA_CH_DADR*)0xF00122CCu) uint32 u32_Source_Data 0x11111; uint32 u32_Dadr_Data 0; void DMA_SoftTriggerTestDemo(void) { /*搬运的源地址*/ DMA_CH22_SADR.B.SADR (uint32)(u32_Source_Data); /*搬运的目标地址*/ DMA_CH22_DADR.B.DADR (uint32)(u32_Dadr_Data); /*设置一次搬运的Size*/ DMA_CHCFGR022.U (0x02 21); /*关闭DMA硬件请求*/ DMA_TSR022.U | (0x0117); } void DMA_StartSoftTrig(void) { /*软件触发DMA搬运的开关触发一次搬运一次注意需要此处不支持连续搬运只是单次搬运的demo*/ DMA_CHCSR022.U |(132) }13. 实验结果验证DMA 触发之前u32_Source_Data : 0x11111Destination0x00000000执行 DMA Software Request 以后u32_Dadr_Data : 0x11111说明 DMA 搬运成功。14. 调试 DMA 时我一般先看什么如果 DMA 没有正常工作我一般建议按下面这个顺序排查。SADR ↓ DADR ↓ Move Size ↓ Transfer Count ↓ Address Increment ↓ Channel Enable ↓ Software Request ↓ Channel Status ↓ Destination Buffer而不是一上来把 DMA 所有寄存器都翻一遍。14.1 检查 SADR首先确认DMA读取地址到底是不是自己想要的地址Debugger 中检查SADR再和Dma_SourceBuffer[0]进行对比。14.2 检查 DADR同理检查DADR是否等于Dma_DestinationBuffer[0]14.3 检查 Move Size假设定义uint32 Buffer[8];如果 Move Size 配成8 bit虽然不一定完全不能搬但整个 Transfer Count 和地址变化的理解都会不同。因此最好保证数据类型和Move Size对应起来。14.4 检查 Transfer Count这个地方非常容易理解错误。Transfer Count 通常理解的是执行多少次 Move。而不是直接填写多少 Byte。例如32 Byte数据如果Move Size 32 bit那么Transfer Count 8而不是Transfer Count 3214.5 检查地址是否递增如果发现Destination Buffer里面全是同一个值可以优先怀疑Source Address Increment是否配置正确。如果Destination只有一个位置发生变化可以检查Destination Address Increment是否配置正确。15. 软件触发和硬件触发的区别理解软件触发以后后面的硬件触发其实就比较容易理解。软件触发CPU ↓ Software Request ↓ DMA ↓ RAM16. 从软件触发继续往后学习软件触发只是 DMA 最基础的一步。后面可以继续按照下面的顺序学习DMA软件触发 ↓ 理解SADR/DADR ↓ Move Size ↓ Transfer Count ↓ Address Increment ↓ DMA中断 ↓ Hardware Request ↓ SRC ↓ DSADC DMA ↓ EVADC DMA ↓ SPI DMA ↓ DMA循环Buffer这样学习起来会比直接从复杂的外设 DMA 入手清晰很多。18. 总结本文主要通过一个最简单的软件触发实验理解 TC3xx DMA 的基础工作流程。一个 DMA 搬运本质上需要解决几个问题数据从哪里来 ↓ SADR 数据到哪里去 ↓ DADR 一次搬多少 ↓ Move Size 搬多少次 ↓ Transfer Count 地址怎么变化 ↓ Address Increment 什么时候开始搬 ↓ Software / Hardware Request如果把这几个问题真正理解清楚后续再学习 DSADC、EVADC、SPI 等外设结合 DMA 使用时就会容易很多。下一篇准备继续整理TC3xx DMA 硬件触发机制从 SRC 请求到 DMA Channel 的完整链路。大家有实际遇到的问题欢迎来交流讨论。
返回列表