CPU跑腿神器DMA浅谈(一)

任何事物都应当充分发挥其卓越品质,CPU的职业特长是做数据运算或者响应中断,然而在硬件产品的开发中,我们发现我们交给CPU更多的“跑腿业务”,最常见的就是我们把许多数据转移工作都交给CPU去做了,这样的跑腿业务占据了CPU宝贵的资源,使得数据运算或者响应中断变得缓慢,这样我们就想谁能做CPU的“跑腿经纪人”呢?

要想了解DMA的职业,首先得知道CPU做数据转移的过程。其过程简单举例:ADC外设采集土壤水分等等这样的数据,CPU先花时间把ADC外设的寄存器的数据读取回内存,也就是我们程序里面设定变量去存储这些数据,然后CPU花时间对变量进行运算处理。问题在于我们怎样不让CPU花时间在把ADC外设的寄存器的数据读取回内存这个过程上。

DMA的意义真的有那么明显吗?在硬件的世界里,CPU(内核)、外设、内存(SRAM)、总线的重要性不必多言,而数据经常要在内存和外设之间转移或者外设A转移到外设B,这样的事情交给DMA就OK了!这样说来,CPU离开了DMA就等于失去了一条腿啊!

在STM32中,DMA是以外设的身份被添加到Cortex内核之外的。这个我们最好从STM32的系统结构图中感受一下吧。

这个图是不是看起来挺简单呢?其实不见得简单呀!在这里面总线矩阵协调着硬件结构“和谐共处”,没有总线那可就乱套了,世界需要和谐,资源需要和平使用,数据转移这个事情就经过总线矩阵的批准才能上路。

继续看图说话。假如没有DMA,内核Cortex就得通过DCode经过总线矩阵协调,使用AHB把外设ADC采集的数据读取到内核Cortex中,然后内核Cortex再通过DCode经过总线矩阵协调,把数据再存放到SRAM中。想想这个过程多浪费CPU呀!有了DMA可就美妙了,DMA控制器的DMA总线与总线矩阵协调,使用AHB把外设ADC的数据经过DMA通道存放到内存SRAM中。这个过程根本不需要内核的参与,数据转移的同时CPU该干嘛干嘛,此时的CPU已经告别了中转站的身份。DMA直接存储器存取中的“直接”就体现在点到点的数据转移,绝非浪得虚名。

下面以利用DMA方式使用串口发送数据同时内核点亮LED为例进行简单的说明。先看一下主函数吧。

main函数首先调用了USART1_Config()、DMA_Config()及LED_GPIO_Config()分别配置好了串口、DMA、及LED外设。这个程序要说明的就是在进行DMA传输的过程中CPU还在控制着点亮LED的过程。怎么证明呢?利用串口调试工具软件显示PC端接收串口数据,如果PC端数据还没接收完的时候,板子上的LED1就被点亮,在数据接收完成时LED1被关闭,就可以说明内核的确在DMA传输的过程中同时进行了其它工作。

需要特别主意的是,USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE)是库函数。调用这个库函数就实现了允许串口外设向DMA发出请求,请求DMA传输数据。调用这个函数之后,DMA开始响应串口的请求,根据我们的DMA配置,把数组中的数据一个个地转移到串口数据寄存器,并由串口向外发送这些数据。

接下来就得分析串口的DMA初始化配置了。虽然是串口的DMA初始化配置,但是DMA还是主角,串口反而是参数配角而已,因为不仅仅串口可以用DMA。下面我摘录了一个DMA初始化配置程序进行详细说明。

这段程序其实就是为了开启外设的DMA时钟,填充要进行DMA传输的初始化结构体,使能DMA功能。在这段代码里面外设地址是数据寄存器的地址,通过DMA把内存数组里的数据转移保存到这个数据寄存器中,串口直接按照串口协议自动发送这个数据寄存器接收到的数据。这里需要注意的是外设地址需要算出来进行宏定义的,但是地址不需要自增,而内存地址往往是一个数组名,这样就需要进行自增设置。在使能DMA中选择通道不是随便选择,需要根据映射图配置。外设在需要使用DMA前需要向DMA控制器发送请求信息,DMA在接收到请求后才会根据DMA配置进行数据转移。

通过上图可知,我们用的是串口1的发送数据DMA功能,所以配置的是通道4,如果有一天我们用串口1的接收数据DMA功能,那就得配置的是通道5了。总结一下就是:DMA被配置为 :数据传输方向从内存(数组SendBuff)到USART1外设的数据寄存器(USART1_DR_Base),要传输的数据总量为SENDBUFF_SIZE(5000)个字节,并且传输时内存地址自增,外设地址固定,DMA模式为非循环模式,DMA通道为DMA1的CHANNEL4。

说好的要通过DMA传输完后关闭LED呢?来吧,该中断服务函数上场了!

大家看到没有,这里函数名可是配置的通道4的中断服务函数奥!这是个组合拳,打这个拳之前需要一个典型的前奏动作,那就是中断配置!大家以后想起中断,一定得想起“组合拳”哈!

由于笔者水平有限,只能抛砖引玉,希望对刚接触DMA的小伙伴们有点用,最后感谢读者耐心读完。

笔者:Armstrong

2017/2/6