一、DMA简介

1、DMA简介

  DMA(Direct Memory Access:直接内存存取)是一种可以大大减轻CPU工作量的数据转移方式。

  CPU有转移数据、计算、控制程序转移等很多功能,但其实转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,再加上一些控制转移的部件就可以完成数据的拷贝。

  DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作--计算、控制等。

2、DMA的工作原理 

  DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:

  • 外设到内存
  • 内存到外设
  • 内存到内存
  • 外设到外设

  当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,传输的终点就是剩余传输数据量为0(循环传输不是这样的)。换句话说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。  

3、DMA是否影响CPU的运行

  在X86架构系统中,当DMA运作时(假设我们从磁盘拷贝一个文件到U盘),DMA实际上会占用系统总线周期中的一部分时间。也就是说,在DMA未开启前,系统总线可能完全被CPU使用;当DMA开启后,系统总线要为DMA分配一定的时间,以保证DMA和CPU同时运作。那么显然,DMA会降低CPU的运行速度。

  在STM32控制器中,芯片采用Cortex-M3架构,总线结构有了很大的优化,DMA占用另外的总线,并不会与CPU的系统总线发生冲突。也就是说,DMA的使用不会影响CPU的运行速度。

二、STM32的DMA结构

1、DMA的主要特性

● 12个 独立的可配置的通道(请求)DMA1有7个通道,DMA2 有5个通道
● 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过
软件来配置。
● 在七个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),假如在相
等优先权时由硬件决定(请求0优先于请求1,依此类推) 。
● 独立的源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标
地址必须按数据传输宽度对齐。
● 支持循环的缓冲器管理
● 每个通道都有3个事件标志(DMA 半传输,DMA传输完成和DMA传输出错),这3个事件标志
逻辑或成为一个单独的中断请求。
● 存储器和存储器间的传输
● 外设和存储器,存储器和外设的传输
● 闪存、SRAM 、外设的SRAM 、APB1 APB2和AHB外设均可作为访问的源和目标。
● 可编程的数据传输数目:最大为65536

下面为功能框图:

  

2、两个DMA控制器结构

① DMA1 controller

② DMA2 controller

3、DMA寄存器列表

① 中断类

DMA_ISR:   DMA中断状态寄存器

DMA_IFCR:  DMA中断标志位清除寄存器

说明:  DMA1、DMA2分别有一组寄存器。

② 控制传输类

DMA_CCRx:   DMA通道x配置寄存器 

DMA_CNDTRx:  DMA通道x数据数量寄存器

DMA_CPARx:   DMA通道x外设地址寄存器

DMA_CMARx:  DMA通道x内存地址寄存器

说明:

1> 每一个通道都有一组寄存器。

2> DMA_CPARx、DMA_CMARx是没有差别的,它们都可以存放外设的地址、内存的地址。DMA_CPARx、DMA_CMARx只不过起得名字有差别而已。

4、STM32的DMA工作特点

① DMA进行数据传输的必要条件

  • 剩余传输数据量大于0
  • DMA通道传输使能
  • 通道上DMA数据传输有事件请求

  前两者都好理解,对于第三点确实需要详细的解释,请看下边的三条。

② 外设到XX方向的传输

  假设是ADC到存储器的数据传输,显然ADC的DMA传输的源地址是ADC的数据寄存器。并不是说只要DMA通道传输使能后,就立即进行数据传输。只有当一次ADC转化完成,ADC的DMA通道的传输事件有效,DMA才会从ADC的数据寄存器读出数据,写入目的地址。当DMA在读取ADC的数据寄存器时,同时使ADC的DMA通道传输事件无效。显然,要等到下一次ADC转换完成后,才能启动再一次的数据传输。

③存储器对XX的DMA传输

  因为数据是准备好的,不像ADC还需要等待数据到位。所以,不需要对应通道的事件。只要使能DMA数据传输就一直传输,直到达到设定的传输量。

example:

1.内存到内存

  DMA传输请求一直有效

2.内存到串口

  DMA传输请求一直有效

一种解释:

  存储器对存储器的置位,就相当于相应通道的事件有效。 对应通道的事件有效和存储器对存储器的置位,就是传输的触发位。每次传输的事件置位一次,完成一次传输。如果是由外设引发的DMA传输,则传输完成后,相应传输事件会置为无效,而存储器对存储器的传输,则一次传输完成后,相应事件一直有效,直至完成设定的传输量。                摘自:http://bbs.21ic.com/icview-400841-1-1.html

④外设以DMA方式工作时,能否再以软件方式进行操作?

  有一点是肯定的,当外设以DMA方式正在数据传输时,不可能再相应CPU的软件控制命令,否则这不符合逻辑。

  但是,倘若外设仅仅配置成DMA工作方式,但是DMA请求并未产生,数据传输并没有进行。此时,软件控制命令仍然能够对外设进行控制。这是笔者在串口以DMA方式发送数据情形下,所得到的测试结论。

三、STM32的DMA软件编程

1、“内存到内存”模式传输

① 初始化配置

uint8_t SendBuff[SENDBUFF_SIZE];
uint8_t ReceiveBuff[RXBUFF_SIZE];
/**
* @brief USART1 TX DMA 配置,内存到内存
* @param 无
* @retval 无
*/
void DMA_Mem2Mem_Config(void)
{
DMA_InitTypeDef DMA_InitStructure; /*开启DMA时钟*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /*设置DMA源地址*/
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; /*设置DMA目的地址*/
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ReceiveBuff; /*方向:从内存SendBuff到内存ReceiveBuff*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; /*传输大小DMA_BufferSize=SENDBUFF_SIZE*/
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE; /*ReceiveBuff地址自增*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; /*SENDBUFF_SIZE地址自增*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /*ReceiveBuff数据单位*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; /*SENDBUFF_SIZE数据单位*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; /*DMA模式:正常模式*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; /*优先级:中*/
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; /*使能内存到内存的传输 */
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; /*配置DMA1的4通道*/
DMA_Init(DMA1_Channel4, &DMA_InitStructure); /*失能DMA1的4通道,一旦使能就开始传输*/
DMA_Cmd (DMA1_Channel4,DISABLE);
}

② DMA中断配置

/**
* @brief DMA 中断配置
* @param 无
* @retval 无
*/
void DMA_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; /* 配置中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); /* 配置DMA发送完成后产生中断 */
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
}

③启动传输

DMA_Cmd (DMA1_Channel4,ENABLE); 

2、利用DMA实现循环传输

方法1:单次传输模式

  当传输结束时,触发DMA中断,在中断程序中首先失能DMA通道,然后修改该通道的传输数据量。最后重新使能DMA通道,注意只有失能的DMA通道才能成功修改传输数据量。

方法2:循环传输模式

  当传输结束时,硬件自动会将传输数据量寄存器进行重装,进行下一轮的数据传输。

四、再谈STM32的DMA传输是否影响CPU的运行速度

  声明:经过笔者测试,当DMA工作在内存到外设的传输和内存到内存的传输时,都不会影响CPU的运行速度。为了给这种现象一个合理的解释,笔者做以下猜测:

1、S3C2440的DMA传输

  S3C2440的SDRAM是外置的,并且SDRAM的数据线、地址线、控制线总共只有一组。假设DMA传输的方向是内存到外设,当DMA运作时,需要占用SDRAM的三类线才才能实现传输;而与此同时CPU也需要通过这三类线来访问SDRAM来读取程序、读写数据。

  显然,DMA的运行与CPU的运行有交叉点,DMA就会影响到CPU的运行。

2、STM32的DMA传输

  STM32与S3C2440的区别是很大的,S3C2440是微处理器,RAM外置且空间很大;STM32是微控制器,RAM片内集成且空间较小。此时,ST公司就有可能提升DMA的运作效率,使DMA的工作不影响到CPU的运行。

  外设与外设之间的DMA传输,因为与CPU的运行没有交叉点(CPU的数据流注意是在Flash、内存、寄存器中传输),所以不会影响CPU的运行速度。唯一有可能影响的是外设与内存或者内存与内存之间的DMA传输。

  倘若ST公司的SRAM是一个双口RAM,也就是同时可以由两组接口对RAM进行访问,就可以很好的解决速度影响问题。倘若CPU恒定占有一组接口,而另一组接口留给DMA控制器。那么当外设与内存或者内存与内存之间的DMA传输时,由于不与CPU的访问SRAM接口冲突,所以可以解决速度影响问题。

  但其实偶尔还是会影响的,当CPU访问SRAM的空间和DMA访问SRAM的空间相同时,SRAM势必会对这种情况进行仲裁,这可能会影响到CPU的访问SRAM的速度。其实,这种情况的概率也是很小的,所以即使影响CPU的运行速度,也不会很大。

参考资料:《STM32参考手册》

STM32之DMA的更多相关文章

  1. STM32之DMA+ADC

    借用小甲鱼的经典:各位互联网的广大网友们.大家早上中午晚上好..(打下小广告,因为小甲鱼的视频真的很不错).每次看小甲鱼的视频自学都是比较轻松愉快的..我在想,如果小甲鱼出STM32的视频,我会一集不 ...

  2. STM32使用DMA发送串口数据

    1.概述 上一篇文章<STM32使用DMA接收串口数据>讲解了如何使用DMA接收数据,使用DMA外设和串口外设,使用的中断是串口空闲中断.本篇文章主要讲解使用DMA发送数据,不会讲解基础的 ...

  3. STM32的DMA

    什么是DMA?其全称是:Direct Memory Access:根据ST公司提供的相关信息,DMA是STM32中一个独立与Cortex-M3内核的模块,有点类似与ADC.PWM.TIMER等模块:主 ...

  4. STM32 串口DMA方式接收(转)

    STM32 是一款基于ARM Cortex-M3内核的32位MCU,主频最高可达72M.最近因为要在车机上集成TPMS功能, 便开始着手STM32的开发工作,STM32F10x系列共有5个串口(USA ...

  5. STM32 基DMA的DAC波形发生器

    DAC是STM32系列的一个基本外设,可以将数字信号转化成模拟信号,这次我将使用DAC来输出一个特定波形. 首先确定工作方法,由于我目前在做的简易示波器在输出波形的同时还需要显示输入信号,所以不能占用 ...

  6. STM32 UART DMA实现未知数据长度接收

    串口通信是经常使用到的功能,在STM32中UART具有DMA功能,并且收发都可以使用DMA,使用DMA发送基本上大家不会遇到什么问题,因为发送的时候会告知DMA发送的数据长度,DMA按照发送的长度直接 ...

  7. stm32的DMA传输一半中断

    这里本想做一个录音程序 硬件很简单: MIC(麦克风)放大滤波电路---->stm32的ADC----->DMA通道----->一个数组缓存------->通过FATFS的  ...

  8. STM32之DMA实例

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zouleideboke/article/details/75092558 DMA简介: DMA(Di ...

  9. STM32串口DMA接收数据错位——暴力解决方法

    背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6.在调试的过程中发现,一直出现数据错位的问题,接收端尝试 ...

随机推荐

  1. sqrt 源代码

    stap -v -e 'probe process("/usr/local/mysql56/bin/mysqld").function("*@/usr/src/mysql ...

  2. Java调用yahoo!API获取天气数据

    先把代码复制上来,以后再做补充 package com.weather.test; import java.io.InputStream; import java.net.URL; import ja ...

  3. phpcms 源码分析七: 模板引擎实现

    这次是逆雪寒对模板引擎实现的分析: 1 /* 函数 template函数是在global.func.php 里面定义的. 在前面的phpcms 的首页 index.php 里就见到了. 用法: inc ...

  4. springmvc 双亲上下文导致的 No mapping found for HTTP request

    今天搭建spring mvc ,结果发出请求总是No mapping found for HTTP request with URI [******] 于是开始排查了半天,后来在网上搜到了双亲上下文的 ...

  5. Android(java)学习笔记167:Java中操作文件的类介绍(File + IO流)

    1.File类:对硬盘上的文件和目录进行操作的类.    File类是文件和目录路径名抽象表现形式  构造函数:        1) File(String pathname)       Creat ...

  6. 关于C语言中运算符优先级的一次错误

    好久没碰编程了,最近有点闲,又拾起来.做了个简单的网络测试程序,测试的时候发现有条语句老是获取不到结果.如下: if(portnumber=atoi(argv[1])>65535) portnu ...

  7. 在ModelSim波形图中以参数名显示变量

    在ModelSim波形图中以参数名显示变量 在使用Verilog HDL编写有限状态机等逻辑的时候,状态机的各个状态通常以参数表示,但当使用ModelSim仿真的时候,状态机变量在wave窗口中以二进 ...

  8. jQuery 定时局部刷新(setInterval)方法总结

    来自:http://www.jbxue.com/article/8516.html 1.jQuery 定时局部刷新(setInterval),显示时间的代码. <head> <scr ...

  9. JQ 如何设置单选按钮问题

    <input type="radio" name="db_12" value="2" checked="checked/&g ...

  10. jBPM开发入门指南

    http://blog.csdn.net/eric474470/article/details/7665265 工作流虽然还在不成熟的发展阶段,甚至还没有一个公认的规范标准.但其应用却已经在快速展开, ...