[研电赛技术支持] GD32实战8__DMA

[复制链接]
 楼主| 梅花香自123 发表于 2022-1-28 17:12 | 显示全部楼层 |阅读模式
引子
​ 在前面的串口例子中,我们可以看如果要通过串口发送一个字符串,需要CPU把每个字符一个一个的发送出去,整个数据传输的过程都需要CPU的参与。可以想象如果传输的数据量较大,那么CPU大部分时间都忙于数据的传输了,然而,我们希望CPU能去做其他更重要的事情,那么数据的传输有没有更好的办法呢?

​ 有,就是DMA(直接存储器访问)一个可以实现数据在存储器和外设或存储器和存储器之间直接传输,而不需要CPU参与的功能,通称DMA控制器。

​ 因此,如果我们设计一个DMA,可以这么做。假设CPU大哥有批货(数据)需要从杭州运到上海,那么可以招一个快递员(DMA小弟),告诉他收货地址、发货地址、货物大小和紧急程度,如果有多批货需要运到不同的城市,那就多招几个快递员,并成立一个快递公司管理。

​ 上面的例子中,快递公司可以看做是DMA控制器,DMA通道可以看做是快递员,收货地址是数据目的地址,发货地址是数据源地址,货物大小是数据长度,紧急程度是软件优先级,快递员编号是硬件优先级。

 楼主| 梅花香自123 发表于 2022-1-28 17:13 | 显示全部楼层
GD32的DMA管理
​ DMA不是Cortex-M3的内核的一部分,都是厂家自己设计的。如图,GD32 MDA1支持7通道,并和CPU共用系统总线,因此,和CPU是存在竞争关系的,只是总线仲裁比较偏心CPU,保证CPU至少有一半的总线带宽。
 楼主| 梅花香自123 发表于 2022-1-28 17:14 | 显示全部楼层
 楼主| 梅花香自123 发表于 2022-1-28 17:15 | 显示全部楼层
DMA的配置步骤:
  1. 1. 配置外设地址
  2. 2. 配置存储器地址
  3. 3. 配置传输数据总数
  4. 4. 配置软件优先级,传输方向,模式类型,数据尺寸和中断类型
  5. 5. 使能DMA
 楼主| 梅花香自123 发表于 2022-1-28 17:16 | 显示全部楼层
这些配置中,大部分在引子里已经说明了,理解不难,重点说下,优先级、模式类型和中断类型
 楼主| 梅花香自123 发表于 2022-1-28 17:18 | 显示全部楼层
优先级:

优先级分两个层次,软件优先级和硬件优先级。软件优先级高于硬件优先级。

软件优先级又分4个等级
硬件优先级是固定的,就是通道号,如下图,通道编号越小,优先级越高。
 楼主| 梅花香自123 发表于 2022-1-28 17:19 | 显示全部楼层
 楼主| 梅花香自123 发表于 2022-1-28 17:20 | 显示全部楼层
模式类型:

​ 循环模式和普通模式
 楼主| 梅花香自123 发表于 2022-1-28 17:21 | 显示全部楼层
中断类型:

​ 每个通道都有专门的中断,中断事件只有三个:传输完成,传输完成一半和传输错误。如下图,
 楼主| 梅花香自123 发表于 2022-1-28 17:21 | 显示全部楼层
 楼主| 梅花香自123 发表于 2022-1-28 17:22 | 显示全部楼层
代码配置
  1. static VOID UART1_DmaRxConfig(IN U8 *buf, IN U32 len)
  2. {
  3.     DMA_InitPara DMA_InitStructure;
  4.    
  5.     DMA_Enable(DMA1_CHANNEL5, DISABLE);
  6.    
  7.     /* USART1 RX DMA1 Channel (triggered by USART1 Rx event) Config */
  8.     DMA_DeInit(DMA1_CHANNEL5);
  9.     DMA_InitStructure.DMA_PeripheralBaseAddr = (U32) &(USART1->DR);
  10.     DMA_InitStructure.DMA_MemoryBaseAddr = (U32)buf;
  11.     DMA_InitStructure.DMA_DIR = DMA_DIR_PERIPHERALSRC;
  12.     DMA_InitStructure.DMA_BufferSize = len;
  13.     DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
  14.     DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
  15.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PERIPHERALDATASIZE_BYTE;
  16.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MEMORYDATASIZE_BYTE;
  17.     DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
  18.     DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
  19.     DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
  20.     DMA_Init(DMA1_CHANNEL5, &DMA_InitStructure);
  21.     DMA_Enable(DMA1_CHANNEL5, ENABLE);
  22. }
 楼主| 梅花香自123 发表于 2022-1-28 17:24 | 显示全部楼层
代码路径
https://github.com/YaFood/GD32F103/tree/master/TestUART
https://gitee.com/YaFOOD/GD32F103/tree/master/TestUART
您需要登录后才可以回帖 登录 | 注册

本版积分规则

101

主题

1215

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部