5.1. DMA - RAM间数据搬运

本 demo 基于 DMA,方向为 memory to memory 模式,进行数据的搬运。

5.1.1. 硬件连接

5.1.2. 软件实现

  • 软件代码见 examples/dma/dma_m2m

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#define BSP_USING_DMA0_CH0

#if defined(BSP_USING_DMA0_CH0)
#ifndef DMA0_CH0_CONFIG
#define DMA0_CH0_CONFIG \
{   \
.id = 0, \
.ch = 0,\
.direction = DMA_MEMORY_TO_MEMORY,\
.transfer_mode = DMA_LLI_ONCE_MODE, \
.src_req = DMA_REQUEST_NONE, \
.dst_req = DMA_REQUEST_NONE, \
.src_width = DMA_TRANSFER_WIDTH_32BIT , \
.dst_width = DMA_TRANSFER_WIDTH_32BIT , \
}
#endif
#endif
  • 使能 BSP_USING_DMA0_CH0 并配置 DMA 设备配置,见 bsp/board/bl706_iot/peripheral_config.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
dma_register(DMA0_CH0_INDEX, "DMA");

struct device *dma = device_find("DMA");

if (dma)
{
    device_open(dma, 0);
    device_set_callback(dma, dma_transfer_done);
    device_control(dma, DEVICE_CTRL_SET_INT, NULL);
}
  • 首先调用 dma_register 函数注册 DMA 设备的一个通道,当前注册 DMA_CH0

  • 然后通过 find 函数找到设备对应的句柄,保存于 dma 句柄中

  • 最后使用 device_open 以默认模式来打开 dma 设备,调用 device_set_callback 注册一个dma通道0中断回调函数,调用 device_control 开启dma传输完成中断

1
2
dma_reload(dma,(uint32_t)dma_src_buffer,(uint32_t)dma_dst_buffer,8000);
dma_channel_start(dma);
  • 调用 dma_reload 函数对dma 通道0的配置进行补充,DMA0_CH0_CONFIG 中已经补充了一部分配置,这边主要补充源数据地址和目标数据地址以及传输总长度

  • 调用 dma_channel_start 开启dma传输

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
void dma_transfer_done(struct device *dev, void *args, uint32_t size, uint32_t state)
{
    uint32_t index=0;

    if(!state)
    {
        MSG("dma transfer task done\r\n");

        for(index=0;index<8000;index++){
            if(dma_dst_buffer[index]!=0xff){
                MSG("dma transfer error\r\n");
            }
        }

        MSG("dma transfer success\r\n");
    }

}
  • 在中断函数中判断数据传输是否正确

5.1.3. 编译和烧录

1
2
 $ cd <sdk_path>/bl_mcu_sdk
 $ make BOARD=bl706_iot APP=dma_m2m

5.1.4. 实验现象

dma_src_buffer 数组中的数据通过 DMA 通道 0 ,以源 32 位宽、目标 32 位宽传输到 dma_dst_buffer 数组中,数据传输完成并完整,串口打印 dma transfer success