打印

GD32实战__DMA(转载)

[复制链接]
635|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wiba|  楼主 | 2019-6-21 14:27 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
引子
​        在前面的串口例子中,我们可以看如果要通过串口发送一个字符串,需要CPU把每个字符一个一个的发送出去,整个数据传输的过程都需要CPU的参与。可以想象如果传输的数据量较大,那么CPU大部分时间都忙于数据的传输了,然而,我们希望CPU能去做其他更重要的事情,那么数据的传输有没有更好的办法呢?

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

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

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


使用特权

评论回复
沙发
wiba|  楼主 | 2019-6-21 14:27 | 只看该作者
GD32的DMA管理

​        DMA不是Cortex-M3的内核的一部分,都是厂家自己设计的。如图,GD32 MDA1支持7通道,并和CPU共用系统总线,因此,和CPU是存在竞争关系的,只是总线仲裁比较偏心CPU,保证CPU至少有一半的总线带宽。


使用特权

评论回复
板凳
wiba|  楼主 | 2019-6-21 14:27 | 只看该作者

DMA的配置步骤:

1. 配置外设地址

2. 配置存储器地址

3. 配置传输数据总数

4. 配置软件优先级,传输方向,模式类型,数据尺寸和中断类型

5. 使能DMA

这些配置中,大部分在引子里已经说明了,理解不难,重点说下,优先级、模式类型和中断类型


使用特权

评论回复
地板
wiba|  楼主 | 2019-6-21 14:28 | 只看该作者

优先级:

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

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


使用特权

评论回复
5
wiba|  楼主 | 2019-6-21 14:28 | 只看该作者

模式类型:

​        循环模式和普通模式

中断类型:

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


使用特权

评论回复
6
wiba|  楼主 | 2019-6-21 14:29 | 只看该作者
代码配置
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);
}


使用特权

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

本版积分规则

77

主题

3305

帖子

3

粉丝