davinci的DMA介绍

本文详细介绍了DM642中的EDMA(Enhanced Direct Memory Access)结构,包括其支持的64个独立通道、优先级队列、传输模式等特性,并深入分析了EDMA性能优化的方法,例如合理分配高、低优先级队列任务,考虑DMA传输发起模式,以及注意事项如数据对齐、与缓存交互等。

DM642中EDMA结构及优化

DMA(Direct Memory Access)是DSP中至关重要的一个部分,DMA可以在不需要CPU的干预的情况下,在后台执行数据的高速传输,系统效率的高低很大程度上取决与DMA的使用好坏与否。DM642是目前公司内使用最多的DSP,其运行效率的高低决定着大部分产品的性能。下面就DM642上的DMA性能做一个简单的介绍和分析。

DM642中的DMA称为EDMA(Enhanced Direct Memory Access),其EDMA控制器支持64个相互独立的DMA通道,每个通道都可以接受系统外设事件的触发或者CPU的指令的触发,不同DMA传输之间还可以进行连接,构成各种复杂的DMA操作,在600MHz主频时可以提供2.4GB/秒的数据吞吐量。具备的1维、2维传输模式,非常适合图像的处理。系统结构如图所示:

对于EDMA的结构,可以参考相关的数据手册,这里不做详细的说明,主要侧重DMA效率的优化。

要想用好EDMA,需要很好的理解EDMA的传输过程。EDMA内部划分为4个优先级,分别是Q0(Urgent)、Q1(High)、Q2(Medium)和Q3(Low),顾名思义,从0-3由高至低,4个优先级分别对应4个队列,每个队列可容纳16个传输请求,每个队列都可以被CPU和外设使用,且每个部分占用的队列单元个数可以手动设置。每个队列都是FIFO结构,先提交的传输先执行传输操作,队列后面的操作必须等待前面的操作完成后才能够被执行,但是各个队列之间的传输可以按照优先级并行操作,当某个操作处于阻塞、等待状态时,其它队列中的任务可以得到执行。

从这个基本操作模式可以看出合理的对EDMA资源进行分配很重要,目前DM642系统中的处理如下:

1、 高优先级的队列中执行传输数据少但时间要求最紧迫的任务,比如CACHE操作和CPU访问操作,因为这类操作如果得不到快速的响应,会造成CPU的阻塞,严重影响CPU的性能。

2、 低优先级队列中执行紧迫性不高且数据量大的传输。比如编解码的传输,预览、缩放的传输。因为数据量的传输会很长时间的占用DMA操作和外部总线操作,如果将其放在高优先级队列中,会使那些数据量本来很少的操作因为优先级低而长时间得不到响应,造成浪费。

3、 系统图像输入、图像处理和编解码同样都要求大量的数据传输,对于这些传输的安排,把编解码的优先级放为最低。因为大多数用户追求预览的实时和流畅,而编解码的操作对用户来说不直接可见,我们只要求实时即可,同时图像的输入和处理是编解码的前提,这两部分的操作如果无法按时完成,编解码器的优先级再高也没有意义,同样无法保证实时。

4、 除了软件直接发起的DMA操作之外,还要统计哪些外设需要用到DMA操作。在现有的系统中,这些外设主要包括:McASP,音频输入、输出;VideoPort,视频输入、输出;PCI,和主机的数据交换。这些外设的数据量同样非常大,不可以忽略。

5、 优先级确定之后,还要考虑合理的在各个优先级队列中分配操作,除了最高级别的队列要绝对保证之外,对于其它3个队列,尽量做到均衡的分配任务,避免过多的传输集中在某一个队列之中。

关于DMA传输的发起,有三种模式:

1、 外设通过事件发起。在音视频的输入和输出中,通过软件配置外设和EDMA,之后通过DSP内部的EDMA事件,将外设和EDMA关联起来,外设启动后,通过事件自动触发DMA传输,无需软件干预,在某帧视频或音频传输完成后,通过中断通知。

2、 手动触发模式,在现有系统中,利用CSL库,将常用的EDMA操作做了封装,比如1D->1D,1D->2D,2D->1d,2D->2d的传输,在向DMA提交传输请求之后,等待信号量,发起传输的任务进入挂起状态,等操作完成之后,在DMA中断中,释放信号量,唤醒等待的任务。

3、 QDMA模式。TI提供的系统库中把QDMA封装到了DAT模块中,可以直接使用。QDMA并不是独立的DMA,其数据传输仍然是基于EDMA,只是QDMA操作的效率较普通EDMA高。

模式2和3是软件中主要使用DMA的方式,按照不同的机制,使用的时候需要注意:

在手动触发模式下,依靠任务调度来完成等待传输的过程,每次DMA操作都包含任务的切换,中断的处理,适合做较多数据的传输,同时软件的操作较简单,由操作系统负责调度,不会浪费CPU时间来等待传输的完成。但不适合做数据量小且非常频繁的操作,因为数据量很少时,DMA传输很快,相比之下,任务切换、中断处理的操作就显得有些得不偿失了,在过于频繁的使用时,会对系统效率造成影响。

而QDMA的传输发起和传输等待过程独立执行,其等待完成过程无需任务调度,不需要中断处理,只是简单的采用CPU轮询的方式实现,在数据没有完成的情况下,等待DMA传输完成会极大的浪费CPU资源。因此QDMA的使用适合于对数据的处理时间大于DMA传输时间的场合,QDMA还有一个优势:通过优化DMA队列长度,可以按照流水的方式提交多个请求,在进行数据运算和处理时,可以使用QDMA在后台执行一些复杂的操作。

其它的一些注意事项:

1、 注意数据对齐,包括每次传输数据的长度是否对齐和数据的起始地址是否对齐,按照4对齐和8对齐的传输效率最高,当数据非对齐时,DMA的效率会成倍的下降。

2、 和Cache相关的一些操作,由于EDMA在对L2操作时,可以自动执行CACHE操作,当从L2到外部SDRAM传输时,EDMA会自动将L1内的数据写回到L2;相反,当从外部SDRAM到L2传输时,EDMA也会自动将L1内部的相关部分清除。利用这个特点,有些场合用EDMA比直接操作数据更方便,因为不必操心cache一致的问题。

3、 不是所有的操作都要依赖DMA,比如在DMA已经十分繁忙的情况下,如果传输的数据很少,也可以直接用CPU来访问,或者将两者配合使用来达到最好的效果。



Ti 64xDSP的EDMA基本概念

1. 基本概念

元素传输(Element transfer):在1D传输中,从源到目的的单个数据元素的传输,每个同步事件触发一个元素的传输。

帧(Frame):在1D传输中,一组元素组成一帧,元素可以连续也可以有间隔(通过元素索引),一个同步事件可以触发一帧的传输。

数组(Array):在2D传输中,一组连续的元素组成一个数组。一个事件可以触发一个数组的传输。

块(Block):一组数组或帧构成一个数据块,对于1D传输,块由帧构成,对于2D传输,块由数组构成。

一维传输(1D transfer):帧组成的1D数据块的传输,FRMCNT指明帧数,ELECNT指明组成帧的元素个数。

二维传输(2D transfer):帧组成的2D数据块的传输,FRMCNT指明数组个数,ELECNT指明组成数组的元素个数。

2. 传输方式:

基于元素(Element)同步的1D1D传输:FS = 0,一个事件触发一个Element的传输。整个块完毕(FRMCNT = 0且ELECNT = 1)产生传输完毕中断。除最后一次传输结束外其它每次事件触发传输一次时产生Alternate Transfer Complete中断。

基于帧(Frame)同步的1D1D传输:FS = 1,一个事件触发一个Frame的传输。整个块完毕(FRMCNT = 0)产生传输完毕中断。除最后一次传输结束外其它每次事件触发传输一次时产生Alternate Transfer Complete中断。

基于数组(Array)同步的2D2D传输:FS = 0,一个事件触发一个Array的传输。整个块完毕(FRMCNT = 0)产生传输完毕中断。除最后一次传输结束外其它每次事件触发传输一次时产生Alternate Transfer Complete中断。

基于块(Block)同步的2D2D传输:FS = 1,一个事件触发整个Blcok的传输。整个块完毕(FRMCNT = 0)产生传输完毕中断。不产生Alternate Transfer Complete中断。

基于数组(Array)同步的1D2D传输:FS = 0,一个事件触发一个Array的传输。注意在这个方式,一维源的帧(Frame)必须是连续的。整个块完毕(FRMCNT = 0)产生传输完毕中断。除最后一次传输结束外其它每次事件触发传输一次时产生Alternate Transfer Complete中断。

基于块(Block)同步的1D2D传输:FS = 1,一个事件触发整个Block的传输。注意在这个方式,一维源的帧(Frame)必须是连续的,不能有间隔。整个块完毕(FRMCNT = 0)产生传输完毕中断。不产生Alternate Transfer Complete中断。

基于数组(Array)同步的2D1D传输:FS = 0,一个事件触发一个Array的传输。注意在这个方式,一维目的的帧(Frame)必须是连续的。整个块完毕(FRMCNT = 0)产生传输完毕中断。除最后一次传输结束外其它每次事件触发传输一次时产生Alternate Transfer Complete中断。

基于块(BLCOK)同步的2D1D传输:FS = 1,一个事件触发整个Block的传输。注意在这个方式,一维目的的帧(Frame)必须是连续的。整个块完毕(FRMCNT = 0)产生传输完毕中断。不产生Alternate Transfer Complete中断。

3. EDMA的传输效率:

对于一个给定的传输任务,按2所说,可能有多种传输方式可以实现要求传输任务,但是效率(传输速度)可能大大不一样,总线利用率相差非常巨大,这一点必须注意,比如下表:

表一:元素的尺寸与总线带宽利用率的关系

元素宽度

传输的数据长度(字节)

读操作

写操作

传输带宽(Mb/sec)

利用率

传输带宽(Mb/sec)

利用率

32-bit

4

400

50%

400

50%

32-bit

16

800

100%

800

100%

32-bit

128

800

100%

800

100%

16-bit

4

143.9

18.0%

200

25.0%

16-bit

16

85.1

10.6%

105.3

13.2%

16-bit

128

74.0

9.3%

100.6

12.6%

8-bit

4

50.0

7.0%

55.6

7.0%

8-bit

16

42.1

5.3%

51.9

6.5%

8-bit

128

38.4

4.8%

50.2

6.3%

可见字节传输效率最低

表二:EDMA地址更新模式(增量、减量、索引、固定)与总线带宽利用率的关系(以L2到EMIF为例)

SUM

DUM

传输周期(CPU周期)

传输带宽(Mb/sec)

利用率(%)

L2: Any

EMIF: Increment

96

800

100

L2: Any

EMIF: Fixed

96

800

100

L2: Any

EMIF: Decrement

144

533.3

66.7

L2: Any

EMIF: Index

379

202.5

25.3

EMIF: Increment

L2: Any

96

800

100

EMIF: Fixed

L2: Any

96

800

100

EMIF: Decrement

L2: Any

108

715

89.4

EMIF: Index

L2: Any

495

155

19.4

可见Index传输效率最低

<think> 我们正在讨论Davinci MCU(微控制器单元)中配置DMA(直接内存访问)的方法。根据引用内容,DMA是一个独立控制器,可以执行数据搬运操作而无需CPU干预,完成后通过中断通知CPU。用户希望了解如何在Davinci MCU模块中配置DMA。 由于不同的MCU系列(如Davinci)可能有不同的寄存器和配置步骤,我们需要提供一般性的配置步骤,并尽可能贴近Davinci MCU的典型配置流程。通常,配置DMA包括以下步骤: 1. 初始化DMA:使能DMA时钟(如果有时钟控制)。 2. 配置DMA通道:选择可用的DMA通道。 3. 配置DMA传输参数:包括源地址、目标地址、传输数据量、数据宽度、传输模式(外设到内存、内存到外设等)、地址增量模式等。 4. 配置中断(可选):如果需要传输完成中断,则配置中断优先级并使能中断。 5. 启动DMA传输:使能DMA通道,开始传输。 由于用户提到了“SPI-DMA”配置,我们可以以SPI使用DMA为例进行说明。但是用户的问题是关于“davinci MCU模块配置DMA的方法”,所以我们需要提供更通用的配置方法,同时可以以SPI为例。 由于没有具体的Davinci MCU型号,我们假设其DMA配置类似于常见的MCU。下面提供一个一般性的配置步骤: 步骤1:使能DMA时钟 在大多数MCU中,使用外设(包括DMA)前需要使能其时钟。例如,在STM32中,我们使用RCC寄存器来使能DMA时钟。在Davinci MCU中,可能类似。 步骤2:配置DMA通道 每个外设(如SPI、UART)通常有固定的DMA通道(或请求线)。需要根据外设选择正确的通道。 步骤3:配置DMA传输参数 设置源地址(如果是外设到内存,则源地址是外设数据寄存器地址;如果是内存到外设,则目标地址是外设数据寄存器地址)、目标地址、传输方向、数据大小、传输模式(单次或循环)等。 步骤4:配置中断(如果需要) 使能传输完成中断、半传输中断等,并设置中断优先级,编写中断服务函数。 步骤5:使能DMA通道 将配置好的DMA通道使能,准备传输。 步骤6:在外设中使能DMA请求 例如,在SPI中,我们需要使能SPI的DMA发送请求和/或接收请求。 下面以SPI使用DMA发送数据为例,给出伪代码(具体寄存器名称需要根据Davinci MCU的手册确定): ```c // 假设我们要使用SPI1的发送DMA(内存到外设) // 1. 使能DMA时钟(假设DMA控制器是DMA1) RCC->AHBENR |= RCC_AHBENR_DMA1EN; // 2. 选择DMA通道(假设SPI1_TX使用DMA1通道3) DMA_Channel = DMA1_Channel3; // 3. 配置DMA传输参数 DMA_Channel->CPAR = (uint32_t)&(SPI1->DR); // 外设地址(SPI数据寄存器) DMA_Channel->CMAR = (uint32_t)buffer; // 内存地址(要发送的数据数组) DMA_Channel->CNDTR = buffer_size; // 传输数据量 // 配置控制寄存器:方向为内存到外设,内存地址递增,外设地址不变,数据宽度为8位(根据实际情况) DMA_Channel->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 使能内存地址递增,方向为内存到外设,并使能传输完成中断 // 4. 配置中断 NVIC_SetPriority(DMA1_Channel3_IRQn, 0); // 设置优先级 NVIC_EnableIRQ(DMA1_Channel3_IRQn); // 使能中断 // 5. 使能DMA通道 DMA_Channel->CCR |= DMA_CCR_EN; // 6. 在SPI中使能DMA发送请求 SPI1->CR2 |= SPI_CR2_TXDMAEN; ``` 注意:以上代码为通用伪代码,具体寄存器名称和位定义需要参考Davinci MCU的技术手册。 此外,在DMA传输完成中断服务函数中,需要清除中断标志位,并执行后续操作(例如,关闭DMA通道,通知主程序传输完成等)。 由于Davinci MCU的具体型号未知,建议用户查阅相关型号的参考手册,以获取准确的寄存器配置信息。 如果用户有更具体的需求(如使用哪个外设,传输方向等),可以进一步细化。 §§相关问题§§ 1. 如何配置Davinci MCU中UART的DMA传输? 2. Davinci MCU的DMA支持哪些传输模式? 3. 在Davinci MCU中如何判断DMA传输是否完成? 4. 如何优化Davinci MCU的DMA传输性能? </think>### Davinci MCU模块配置DMA方法 在Davinci MCU中配置DMA(直接内存访问)主要涉及以下关键步骤: #### 1. **DMA时钟使能** ```c RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 使能DMA1时钟 ``` #### 2. **DMA通道配置** ```c DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR); // 外设地址(SPI数据寄存器) DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)txBuffer; // 内存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 传输方向:内存->外设 DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE; // 传输数据量 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址固定 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 普通模式(非循环) DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 通道优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 禁用内存到内存模式 DMA_Init(DMA1_Channel3, &DMA_InitStructure); // 初始化通道 ``` #### 3. **外设DMA请求使能** ```c SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); // 使能SPI的TX DMA请求 ``` #### 4. **DMA中断配置(可选)** ```c DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE); // 使能传输完成中断 NVIC_EnableIRQ(DMA1_Channel3_IRQn); // 使能NVIC中断 ``` #### 5. **启动DMA传输** ```c DMA_Cmd(DMA1_Channel3, ENABLE); // 启动DMA通道 ``` #### 关键注意事项: 1. **地址对齐**:确保内存和外设地址符合DMA要求(通常是4字节对齐) 2. **数据一致性**:使用`__align(4)`或内存屏障指令保证缓存一致性 3. **传输模式**: - 单次传输:`DMA_Mode_Normal` - 循环传输:`DMA_Mode_Circular` 4. 完成回调处理: ```c void DMA1_Channel3_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC3)) { DMA_ClearITPendingBit(DMA1_IT_TC3); // 清除中断标志 // 添加传输完成处理逻辑 } } ``` > 实际配置需参考具体型号的《Davinci MCU技术参考手册》,不同外设(SPI/UART/ADC等)的DMA请求通道映射可能不同。DMA作为独立控制器完成数据搬运任务,大幅减轻CPU负担[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值