直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传 输。无须CPU干预。这是手册上的原话,个人理解为"外包",数据转运的活交给别的,不用CPU。这里的外设就是外设存储器。
DMA是在存储器之间进行数据转运的,具体可以看存储器映像
那么上一节说过,库函数本身就是对外设寄存器读写进行的封装,那么其也是对寄存器进行读写数据,这不过这些寄存器填入数据后会对外围电路有功能性控制,究其本质就是对存储器进行数据的写入和读出,和DMA是一样的,从某个地址拿出数据移动到另一个位置。
看上面的图,左侧就是M3内核和DMA,这实际上是主动单元,右边的外设寄存器(存储器),SRAM,Flash等,本质都是存储器,是被动单元,左侧的可以访问右侧的,但是右侧的只能被左侧的读写。
这样对DMA的理解就更加直观了,独立于CPU以外,能够主动对存储器进行访问。
这里可以看到DMA,含有很多通道,可以设定转运数据的源地址和目的地址等,那么如何设定?可以看到DMA是AHB从设备,这实际上又是CPU对DMA的访问,所以DMA是AHB总线上的被动单元。那么到这里,CPU和DMA的关系可以理解成皇帝和宰相的关系。
接下来讲解DMA的各种细节。
1.仲裁器
这个好理解,因为DMA有多个通道,但是同一之间只能有一个通道被占用,多个通道之间就要安排优先级,和中断类似,并且这个优先级可以软件设定,也有硬件优先级。
2.DMA通道
每个通道都可以在有固定地址的外设寄存器和存储器地址之间执行DMA传输,这个不难理解,就是源地址和目标地址。
3.DMA请求
这里的EN是控制位,就是使能位,当M2M=0,硬件触发 ;M2M=1,软件触发,此时实际上没有靠外设的触发源,多用在存储器到存储器之间。看左边可以发现,每个硬件外设的请求都是在固定通道上的,也就是说如果想使用某个硬件触发源,就必须使用它所在的通道。
4.数据宽度
传输的数据和接收的数据宽度(位数)要进行合适的匹配,看手册的图,可以看到源宽度和目标宽度。当二者相同时,传啥收啥。但是宽度不同时,源的宽度>目标的宽度,高位会被舍弃,看16/8那行;源的宽度<目标的宽度,高位会被补0,看8/16那行;
5.工作模式
从上面的图可以看到DMA的工作模式
左边就是源,包含起始地址和数据宽度,右边是目标处,包含起始地址和数据宽度
两个地址很好理解,一个源,一个终,源向终转运数据,但是这个方向是相对的,也可以左边为终右边为源,个人理解。
数据宽度就是数据的位数,传输的位数和接收的位数要匹配好,这个可以前面介绍过,因为不匹配会造成数据的缺失和高位的0补充。
地址自增就是传输和接受完一个数据,地址加不加1
源地址 | 目标地址 |
p1 | q1 |
p2 | q2 |
这里看这个列表,如果源地址的起始地址是p1,选择自增的话,在传输完毕后,地址会自动加1转到p2,接收同理,目标地址的起始地址是q1,选择自增的话,在接收完毕后,地址会自动加1转到q2。
传输计数器就是设定转运次数的,每转运一次,这个数就会减一,当减到0时,转运就会停止,同时增加的地址会恢复到最开始的起始地址。
自动重装器就是当传输计数器到0时,是否恢复到初值,比如一开始给了5,那么减到0后是否重新填装5。如果不重装,就是单次模式,如果重装,就是循环模式。
再下面就是触发源,包括硬件触发和软件触发,这里的软件触发就是想以最快的速度把传输计数器的数值清零,所以不能和自动重装一起使用。硬件触发就是和外设有关的了,比如定时器计数完,ADC转换完,串口数据接收完等需要特定的时机来转运数据。
注意:如果你们在使用DMA正常模式(也就是传输计数器不自动重装)时,但是想在传输完成再开启DMA传输,一定要在传输完成中断里先失能DMA,然后设置传输计数器的值,再使能DMA,这样DMA就可以再次转运。
6.配置流程
通过前面的介绍和手册描述,使用DMA的流程为:开启DMA的时钟(其挂载在AHB总线上),选择通道,源地址和目标地址的相关配置(地址,数据宽度,是否自增),传输计数器,工作模式,优先级设定,触发源的设定,DMA使能。
参考视频资料