使用DMAC实现存储器与存储器之间的高速数据传输
- 实验目的
本节实验目的为通过DMAC(直接内存存取控制器),实现内存之间数据传输。这一节计划采取使用DMAC来实现内存之间的数据传输。计划实现功能为:定义一个源数组和一个目标数组,将源数组中赋初始值,然后通过dmac将源数组中的数据传输到目标数组,之后通过调试串口打印目标数组中的数据,看是否与源数组中赋的值一致,从而判断DMAC传输数据是否成功。
- 实验准备
1)、带UART的K210开发板一块,用于实践并查看实验现象;
2)、官方裸机编程指导手册:kendryte_standalone_programming_guide,用于查阅SDK中接口说明。
- 实验原理
DMAC,全称Direct Memory Access Controller,即:直接内存存取控制器,主要用于外设与存储器之间,以及储存器与存储器之间的高速数据传输。使用dmac,可以在无需CPU操作的情况下通过DMA快速移动数据,从而提高CPU的使用效率。
- 硬件设计
使用前面的UART电路
- 软件设计
软件流程图如下:
- 软件实现
根据硬件设计和软件设计可知,本节应用实现步骤如下:
1)、初始化数据源,如下图:
2)、DMAC初始化,如下图:
3)、等待DMA进入空闲状态,如下图:
4)、设置单路DMA参数
5)、等待DMA完成工作
6)、打印目标数组
根据上述实现步骤,最终代码如下:
#include <stdio.h>
#include <dmac.h>
#define MAX_DATA_LEN 5
int main()
{
char src_buf[MAX_DATA_LEN] = {0x11, 0x22, 0x33, 0x44, 0x55};
char dst_buf[MAX_DATA_LEN] = {0};
dmac_init();
dmac_wait_idle(DMAC_CHANNEL0);
dmac_set_single_mode(DMAC_CHANNEL0, src_buf, dst_buf, DMAC_ADDR_INCREMENT,
DMAC_ADDR_INCREMENT, DMAC_MSIZE_4, DMAC_TRANS_WIDTH_8,
MAX_DATA_LEN);
dmac_wait_done(DMAC_CHANNEL0);
for(int i=0; i < MAX_DATA_LEN; i++)
printf("dst_buf[%d]:0x%.2x\r\n", i, dst_buf[i]);
return 0;
}
- 编译
1)、同上一节类似,在SDK中创建dmac文件夹,在新建的文件夹中创建一个main.c文件,然后将本节代码输入到main.c文件中,如下图:
2)、同上一节的编译方式类似,打开vscode终端,在终端中进入上一节创建的build文件夹,然后输入:cmake ../ -DPROJ=dmac -G "MinGW Makefiles" ,生成makefile文件,如下图:
3)、生成makefile文件后,输入:make ,开始编译,如下图:
4)、编译完成后,会在build目录下生成烧录文件:dmac.bin,如下图:
- 烧录
同上一节的烧录方式类似,注意:Firmware那一项选择我们刚编译出的dmac.bin文件。
- 实验现象
烧录完成之后,弹出串口工具,打印出目标数组的值,如下图:
从打印的值我们可以看出:目标数组中的值已于源数组中的值一致,这证明已经将源数组中的值拷贝到了目标数组,从而证明了DMAC已将数据从源数组传送到了目标数组。
- 实验总结与注意事项
1)、由于DMAC只需CPU启动DMA,便可直接通过DMA在外设和内存以及内存和内存之间传输数据,所以,使用DMAC可以提高CPU的使用效率
2)、本节仅演示了DMA内存和内存之间的数据传输,除此之外,还常用于外设与内存之间进行数据传输,例如:UART和内存、I2C和内存等,后面有机会再补上外设和内存之间的数据传输;