跳转至

直接内存访问(DMA)


1、简介

DMA(Direct Memory Access,直接内存访问)是一种不经过CPU而直接进行内存数据存取的技术。DMA方式通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU在数据传送期间不必干预,从而大幅减轻CPU的负担。

CI14LP芯片内置2通道通用DMA控制器(DMA_CHANNEl_0、DMA_CHANNEl_1),特性包括:

  • 支持 M2M(内存到内存)、M2P(内存到外设)、P2M(外设到内存)、P2P(外设到外设)四种传输方向
  • 支持8/16/32bit传输宽度、1~256突发长度(burst)
  • 支持源/目的地址递增控制
  • 支持链表(LLI)传输模式
  • 支持传输完成、链表传输、传输错误三类中断
  • 支持FLASH专用DMA通道配置

支持的外设请求源:

外设 说明
DMA_PERIPHERAL_FLASH FLASH专用SPI
DMA_PERIPHERAL_SPI_TX / SPI_RX 通用SPI收/发
DMA_PERIPHERAL_UART0/½_RX / TX 三路UART收/发
DMA_PERIPHERAL_I2C0/1_RX / TX 两路IIC收/发

2、API

2.1 通道使能与状态

函数名 描述
dma_en DMA控制器使能/关闭
dma_channel_enable DMA通道使能
dma_channel_disable DMA通道关闭
dma_channel_enable_status 查询通道使能状态
dma_channel_halt DMA通道暂停/恢复
dma_channel_left_transfer_size 查询通道剩余传输数据量
dma_clear_translate_flag 清除传输完成标志
dma_wait_translate_flag 等待传输完成(超时参数)
dma_irq_handler DMA中断处理函数(驱动内部实现)

2.2 通道配置

函数名 描述
dma_channel_source_addr 设置源地址
dma_channel_dest_addr 设置目的地址
dma_channel_source_config 源端配置(递增/master/宽度/突发长度)
dma_channel_dest_config 目的端配置(递增/master/宽度/突发长度)
dma_channel_transfer_size 设置传输数据量
dma_channel_flowctrl_config 通道流控配置(外设方向+流控类型)
dma_master_endianmode_config master字节序配置(大端/小端)

2.3 组合传输配置

函数名 描述
dma_m2m_mode_config 内存到内存传输配置
dma_m2p_p2m_mode_config 内存到外设/外设到内存传输配置
dma_p2p_mode_config 外设到外设传输配置
dma_lli_mode_config 链表(LLI)模式传输配置
dma_lli_master_sel 链表master选择
dma_set_lli_control / dma_get_lli_control_value 链表控制寄存器配置/生成

2.4 中断

函数名 描述
dma_channel_irq_mask_config 通道中断屏蔽配置(完成/链表/错误)
dma_get_irq_raw_status 获取原始中断状态
dma_get_irq_mask_status 获取屏蔽后中断状态
dma_clear_irq 清除中断标志

3、关键类型

类型 说明
dma_channel_t 通道选择:DMA_CHANNEl_0、DMA_CHANNEl_1、DMA_CHANNEl_ALL
dma_ahb_master_t AHB master接口:DMA_AHB_MASTER_1、DMA_AHB_MASTER_2
dma_endian_mode_t 字节序:LITTLE_ENDIAN_MODE、BIG_ENDIAN_MODE
dma_increment_t 地址递增:INCREMENT、NOINCREMENT
dma_transfer_width_t 传输宽度:TRANSFER_WIDTH_8B、16B、32B
dma_burst_size_t 突发长度:BURST_SIZE_1、4、8、16、32、64、128、256
dma_irq_t 中断类型:DMA_IRQ_TRANS_DONE(传输完成)、DMA_IRQ_LLI_TRANS_DONE(链表传输)、DMA_IRQ_ERROR(传输错误)
dma_flowctrl_t 传输方向:M2M_DMA、M2P_DMA、P2M_DMA、P2P_DMA
dma_peripheral_t 外设请求源:FLASH、SPI、UART0/½、I2C0/1的RX/TX
dma_lli_config_t 链表配置结构体(源/目的递增、master、宽度、突发、单次传输大小)
dma_lli_transfer_t 链表传输结构体(源地址、目的地址、下一链表地址、控制值)
dma_callback_func_ptr_t DMA完成回调函数指针

4、示例

1) 以下代码使用DMA完成内存到内存的数据搬运:

#include "ci14lp_dma.h"

uint32_t src_buf[256] = {0};
uint32_t dst_buf[256] = {0};

void dma_m2m_demo(void)
{
    int i;
    for (i = 0; i < 256; i++)
    {
        src_buf[i] = i;
    }

    //配置通道0:内存到内存搬运,搬运1024字节
    dma_m2m_mode_config(DMA_CHANNEl_0, (uint32_t)src_buf,
                        (uint32_t)dst_buf, 256 * 4, DMA_AHB_MASTER_1);

    //启动通道
    dma_channel_enable(DMA_CHANNEl_0);

    //等待搬运完成
    if (RETURN_ERR == dma_wait_translate_flag(DMA_CHANNEl_0, 0xffffff))
    {
        mprintf("dma transfer err\n");
    }
}

2) 以下代码使用DMA配合UART0完成发送(内存到外设):

#include "ci14lp_dma.h"
#include "ci14lp_uart.h"

unsigned char buf_send[2048] = {0};

void uart_dma_send_demo(void)
{
    //初始化UART0(DMA模式)
    uart_dma_config(UART0, 115200, UART_DMAWIDTH_BYTE);

    //DMA发送数据(内存到外设)
    dma_m2p_p2m_mode_config(DMA_CHANNEl_0, DMA_PERIPHERAL_UART0_TX, M2P_DMA,
                    (uint32_t)buf_send, UART0_DMA_ADDR, 2048,
                    TRANSFER_WIDTH_8B, BURST_SIZE_1, DMA_AHB_MASTER_1);

    //等待DMA传输完成
    dma_wait_translate_flag(DMA_CHANNEl_0, 0xffffff);
}

3) 以下代码以链表(LLI)模式进行分段搬运:

#include "ci14lp_dma.h"

#define LLI_NUM  (3)
dma_lli_transfer_t lli_buf[LLI_NUM] __attribute__((aligned(4)));

void dma_lli_demo(void)
{
    //配置3段链表,每段独立源/目的地址
    lli_buf[0].src_addr      = (uint32_t)src_buf;
    lli_buf[0].dest_addr     = (uint32_t)dst_buf;
    lli_buf[0].next_lli_addr = (uint32_t)&lli_buf[1];
    lli_buf[0].control_value = dma_get_lli_control_value(...);

    //...依次配置lli_buf[1]、lli_buf[2],最后一段next_lli_addr为0

    dma_lli_mode_config(DMA_CHANNEl_0, lli_buf, DMA_AHB_MASTER_1);
    dma_channel_enable(DMA_CHANNEl_0);
}

5、其它

  • 突发传输(burst)不能跨越1KB地址边界,通常设置为外设FIFO大小的一半。
  • 传输数据量(transfer_size)以传输宽度为单位,如8bit宽度时1024表示1024字节。
  • 同一DMA通道同一时刻只能服务一个外设,多外设并发需求请合理分配DMA_CHANNEl_0/1。
  • 音频IIS通路使用独立的IISDMA(见外设API-IIS),不占用通用DMA通道资源。

6、API 参考

本模块接口声明于 driver\ci14lp_chip_driver\inc\ci14lp_dma.h,实现位于 driver\ci14lp_chip_driver\src\ci14lp_dma.c。