浅析DMA

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
简介: DMA全程Direct Memory Access,即直接存储器访问。简单来讲,它的功能是把数据从一个地址搬运到另一个地址。通常有三个传输方向,分别是内存到内存,内存到外设和外设到内存。DMA是开发过程中常用到的,但从个人角度来讲,觉得DMA不是很好学。倒不是说他有多难,只是有些寄存器位的含义可能初学时了解的不深刻,很容易出现问题,这里仅代表个人看法。有的DMA也有一些特殊的传输方式,比如回绕传输,这个在第3小节会有详细介绍。


🎀 文章作者:二土电子
🐸 期待大家一起学习交流!


1、什么是DMA

DMA全程Direct Memory Access,即直接存储器访问。简单来讲,它的功能是把数据从一个地址搬运到另一个地址。通常有三个传输方向,分别是内存到内存,内存到外设和外设到内存。

08853ed296f97e3970b38f2ac953b209_460c52e5e8374c61abb59099882ccc68.png

DMA是开发过程中常用到的,但从个人角度来讲,觉得DMA不是很好学。倒不是说他有多难,只是有些寄存器位的含义可能初学时了解的不深刻,很容易出现问题,这里仅代表个人看法。

有的DMA也有一些特殊的传输方式,比如回绕传输,这个在第3小节会有详细介绍。

2、DMA有什么用

第1小节说到,DMA是开发过程中常用到的,原因在于利用DMA搬运数据不需要CPU干预,可以减少对CPU的占用,提高整个系统的效率。

比如在串口接收或者发送时可以直接利用DMA将接收内容直接搬运到接收数组。或者利用DMA将准备发送的数据搬运到发送的缓冲区。

再或者利用DMA把数据搬运到特定的地址,或者从特定的地址利用DMA搬运数据出来。

总而言之,在平时的开发过程中,DMA是非常常用的。

3、怎么用DMA

3.1 常规的DMA配置

通常配置一个DMA主要需要配置以下内容

  • DMA通道数据源地址
    搬运数据时的数据源地址的首地址

  • DMA通道数据目的地址
    搬运时接收地址的首地址

  • DMA通道数据块最大长度
    对于这个的理解容易出现问题,这个寄存器通常是指启动一次DMA传输时,DMA从数据源拿的数据的个数,设置成200,DMA就会从数据源搬运200个数据。注意是DMA从数据源拿的数据的个数,不是DMA传输到目的地址的数据个数。一个数据宽度受后面的数据源至DMA的传输数据宽度影响。

  • 数据源至DMA的传输数据宽度
    设定数据源至DMA的数据传输宽度,通常有8位,16位和32位

  • DMA至数据目的的传输数据宽度
    设定DMA至数据目的的数据传输宽度

需要注意的是,数据源到DMA的传输数据宽度和DMA到数据目的的传输数据宽度要设置成一样的,否则可能会导致传输数据出现错误。

  • 数据源至DMA控制器的传输数据突发长度
    这个可以理解为每次传输多少个数据给数据目的,也就是每次从数据源拿多少个数据。通常可以设置为1个单位,4个单位,8个单位和16个单位。比如上面DMA到数据目的的传输数据宽度设置的是8位,这里突发长度设置的为4个单位,则每次传输到数据目的的数据为8*4位,也就是4个8位数。

  • 数据传输方向
    配置是内存和内存之间的数据传输还是内存和外设之间的数据传输,是内存传到内存还是内存传到外设或者是外设传到内存。

  • DMA自动重复传输控制
    配置是否在传输完设定的数据量之后自动重新再传输一次。

  • 数据源地址/目的地址自增
    设置数据源地址是否自增,或者数据目的地址是否自增。

  • 关联通道
    通常如果是内存和外设之间的数据传输时,需要将DMA关联到外设。

3.2 回绕传输

除了上述描述以外,还有一种回绕传输的方式。什么叫回绕传输,可以看一下下面的例子。

比如定义两个数组

    uint8 a[8] = {
   
   1,1,1,1,2,2,2,2};
    uint8 b[8] = {
   
   0,0,0,0,0,0,0,0};

利用回绕传输时配置好回绕的起始地址和结束地址,这里利用回绕传输将数组a的值传输到数组b。回绕传输时源地址回绕起始地址设置为数组a的首地址,也就是&a[0],源地址回绕结束地址设置为数组a的最后一位地址,也就是&a[6]。目的地址回绕起始地址设置为数组b的起始地址,也就是&b[0],目的地址回绕结束地址设置为数组b的最后一位地址,也就是&b[3]。这是使能DMA,可以看一下结果

fac8a81da8132a1a39a26f9363d4d460_8555f8f8df9d41a9981659e32766f672.png

画一下图来描述一下整个传输过程

2fd134e498e73606c8fa6db2797ff98a_cb7f729dd73340e9853c622c00321655.png

发现传输时b[0]~b[3]传输结束后会再次从b[0]开始传输,这也就是“回绕”的意思。实际数组a也是,a[0]到a[6]传输完成后会再次从a[0]开始传输。

3.3 DMA中断

通常在使用DMA时也会用到DMA中断,比如做乒乓存储时会使用到DMA传输完成中断,在中断中把目的地址切换到另一个存储区。

有意思的是,DMA并不将Flash中的数据搬运出来。

4、DMA的拓展应用

在使用DMA的过程中有许多发挥空间。

1、比如DMA有一个TCNT寄存器。在初始化完成DMA后,我们配置的DMA通道数据块最大长度的数会被传输到TCNT中,DMA每搬运一个数据TCNT的值就会减1。当TCNT的值减到0时可以认为DMA搬运完成,此时如果开启了DMA搬运完成中断,会进入中断。利用这个可以代替DMA中断,在判断到TCNT等于0时切换存储区实现乒乓存储。此外也可以根据这个值来判断当前搬运了多少个数据了。

2、DMA还有一个寄存器可以指示当前数据源地址或者指示当前数据目的地址。在第一条的基础上,不仅拿到了传输个数,也拿到了当前传输的地址,此时可以做的事情就很多了。

这里举一个小例子,比如我需要ADC采集200个数据,但是在采集过程中我需要对每5个数据计算均值进行判断。

DMA使用的是DMA0,传输200个数据。由于使用的芯片并非常见芯片,这里就不再贴出DMA0的配置程序了,记住配置即可。

设计5个点计算程序时定义一个变量gPreTcnt 记录上一个TCNT值,初始值为200。使能DMA0之后TCNT的值就会随着搬运数据递减,当检测到gPreTcnt 于TCNT的差值大于等于5时说明至少已经搬运完成了5个数据,此时首先将当前的TCNT值赋给gPreTcnt ,然后根据DMA当前数据源地址寄存器的值,往前推5个利用指针来提取数据计算均值。当检测到TCNT等于0,也就代表着200个数据搬运完成了,此时可以在重新初始化一次DMA,同时也需要再给gPreTcnt 重新赋值为200。以下是程序设计。

uint8 gPreTcnt = 200;   // 记录上一个TCNT值的变量

void Five_Point_Mean_Cal(void)
{
   
   
    uint32 *pDmaCurAddr = 0;   //DMA0的当前目的地址指针
    uint32 tempVar = 0;   // 提取数据时的循环变量
    uint32 meanResult = 0;   // 5个点均值计算结果

    // 存储满5个点
    if (gPreTcnt - DMACH0_TCNT >= 5)
    {
   
   
        gPreTcnt = DMACH0_TCNT;   // 更新上一个TCNT值
        pDmaCurAddr = (uint32*)DMACH0_DCUR;   // 获取DMA0当前目的地址

        // 提取0.5ms数据计算均值
        for (tempVar = 1;tempVar <= 5;tempVar ++)
        {
   
   
            meanResult = meanResult + *(pDmaCurAddr - tempVar);
        }
        meanResult = meanResult / 5;
    }

    if (DMACH0_TCNT == 0)
    {
   
   
        重新初始化DMA0
        gPreTcnt = 200;
    }
}
相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
相关文章
|
存储 调度 数据库
STM32--DMA
STM32--DMA
|
4月前
|
存储 芯片
STM32 cubemx配置USART DMA传输
STM32 cubemx配置USART DMA传输
62 0
|
6月前
|
存储 Perl
STM32速成笔记(八)—DMA
本文介绍了DMA的概念,用途。对于STM32F103ZET6的DMA做出了详细地介绍,给出了DMA配置步骤。最后,以配置DMA搬运ADC转换结果为例,给出了DMA的配置和使用方法。
97 0
STM32速成笔记(八)—DMA
|
8月前
|
异构计算 SoC 内存技术
深入理解AMBA总线(九)AHB2SRAM设计
深入理解AMBA总线(九)AHB2SRAM设计
310 0
|
9月前
|
数据处理
STM32实现DMA接收串口数据
STM32实现DMA接收串口数据
220 0
|
11月前
|
存储
11-DMA控制器
11-DMA控制器
|
内存技术
STM32F0 DMA串口接收数据
STM32F0 DMA串口接收数据
222 1
STM32F0 DMA串口接收数据
STM32F0XX DMA串口发送数据
最近在接手一个安排的时候,需要修改之前的一些代码的外设接口,然后发现之前有部分关于USART通过DMA收发数据的部分功能,修改移植的时候发现有些需要注意的事项,以及解释的,做一篇小笔记吧,博主使用的单片机是STM32f071。
186 0
STM32F0XX DMA串口发送数据
|
数据采集
基于DMA的ADC数据采集
嵌入式系统开发经常会遇到采集模拟量的功能需求,这时就会用到ADC,STM32系列MCU提供了强大的ADC功能,其提供的多通道采集和DMA方式极大的方便了ADC相关的开发流程,本文主要记录一下,如何使用ADC实现基于DMA的多通道模拟量采集功能。
447 0