打印
[研电赛技术支持]

GD32实战8__DMA

[复制链接]
1201|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
引子
​ 在前面的串口例子中,我们可以看如果要通过串口发送一个字符串,需要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. 配置外设地址
2. 配置存储器地址
3. 配置传输数据总数
4. 配置软件优先级,传输方向,模式类型,数据尺寸和中断类型
5. 使能DMA

使用特权

评论回复
5
梅花香自123|  楼主 | 2022-1-28 17:16 | 只看该作者
这些配置中,大部分在引子里已经说明了,理解不难,重点说下,优先级、模式类型和中断类型

使用特权

评论回复
6
梅花香自123|  楼主 | 2022-1-28 17:18 | 只看该作者
优先级:

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

软件优先级又分4个等级
硬件优先级是固定的,就是通道号,如下图,通道编号越小,优先级越高。

使用特权

评论回复
7
梅花香自123|  楼主 | 2022-1-28 17:19 | 只看该作者

使用特权

评论回复
8
梅花香自123|  楼主 | 2022-1-28 17:20 | 只看该作者
模式类型:

​ 循环模式和普通模式

使用特权

评论回复
9
梅花香自123|  楼主 | 2022-1-28 17:21 | 只看该作者
中断类型:

​ 每个通道都有专门的中断,中断事件只有三个:传输完成,传输完成一半和传输错误。如下图,

使用特权

评论回复
10
梅花香自123|  楼主 | 2022-1-28 17:21 | 只看该作者

使用特权

评论回复
11
梅花香自123|  楼主 | 2022-1-28 17:22 | 只看该作者
代码配置
static VOID UART1_DmaRxConfig(IN U8 *buf, IN U32 len)
{
    DMA_InitPara DMA_InitStructure;
   
    DMA_Enable(DMA1_CHANNEL5, DISABLE);
   
    /* USART1 RX DMA1 Channel (triggered by USART1 Rx event) Config */
    DMA_DeInit(DMA1_CHANNEL5);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (U32) &(USART1->DR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (U32)buf;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PERIPHERALSRC;
    DMA_InitStructure.DMA_BufferSize = len;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PERIPHERALDATASIZE_BYTE;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MEMORYDATASIZE_BYTE;
    DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
    DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
    DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
    DMA_Init(DMA1_CHANNEL5, &DMA_InitStructure);
    DMA_Enable(DMA1_CHANNEL5, ENABLE);
}

使用特权

评论回复
12
梅花香自123|  楼主 | 2022-1-28 17:24 | 只看该作者
代码路径
https://github.com/YaFood/GD32F103/tree/master/TestUART
https://gitee.com/YaFOOD/GD32F103/tree/master/TestUART

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

92

主题

1059

帖子

0

粉丝