Edit online

编程指南

注:
  • data_width需与外设FIFO位宽对齐。
  • task_len设置需要与data_width对齐。

dma_flow1

1. GPDMA 编程指南

外设到外设传输

  • task_len、block_len:必须与 max(src_width,dst_width)对齐。
  • src_type=io_multi(或io_fast) 与 dst_type=io_multi(或io_fast) :
  • 源端外设与终端外设,其GPDMA通路对应的FIFO水位配置需保持一致
  • block_len =外设GPDMA通路对应的FIFO水位
  • 假设UART2SPI: UART的periph_fifo_level=8Bytes,SPI的periph_fifo_level=4Bytes,SPI_fifo_size=6Bytes,task_len=10Bytes,不满足源端外设periph_fifo_level必须等于终端外设periph_fifo_level的要求,会导致GPDMA工作异常。假设task_len=8Bytes,则会把SPI的FIFO写满,导致溢出。假设task_len=4,则GPDMA会等待UART的请求,但UART因数据量不足无法发出请求,最终导致GPDMA卡死,因为UART需要8个数据才能发出请求,但此时只有6Bytes数据,导致GPDMA卡死。
  • 当src_type=io_multi(或io_fast) 与 dst_type=io_single: block_len 必须等于源端外设其GPDMA通路对应的FIFO水位
  • 当src_type=io_single 与 dst_type=io_multi(或io_fast) : block_len 必须等于终端外设其GPDMA通路对应的FIFO水位
  • 当src_type=io_single 与 dst_type=io_single : 推荐block_len =max(GPDMA的fifo_size,源端fifo_size/2,终端fifo_size/2)
以 SPI 为例,源端为 SPI0,终端为 SPI1。SPI 的 width 支持 8 或者 32。
1. 外设与外设传输编程示例
对象 参数 配置值例 1 配置值例 2 配置值例 3 配置值例 4 配置值例 5 配置值例 6
源端 SPI0

src_SPI0

width 8 8 8 8 8 8
type io_single io_single io_single io_single io_multi (或 io_fast) io_multi (或 io_fast)
终端 SPI1 dst_SPI1
width 32 8 32 8 32 8
type io_single io_single io_multi (或 io_fast) io_multi (或 io_fast) io_multi (或 io_fast) io_multi (或 io_fast)
要求 task_len 与block_len 对齐要求 4Byte 对齐 1Byte 对齐 4Byte 对齐 1Byte 对齐 4Byte 对齐 1Byte 对齐
src_SPI0水位 - - - - block_len block_len
dst_SPI1 水位 - - block_len block_len block_len block_len

Task配置参数

当link_src_sel=0,GPDMA从task_addr与task_h8bits_addr对应地址空间读取Task配置参数。

操作流程如下:首先需要把Task配置参数,写到Memory空间。刷Cache。(由于是CPU写,GPDMA读,存在Cache一致性问题,需要刷一下Cache,让数据实际写到物理存储器中)。然后把Memory空间对应地址写到task_addr与task_h8bits_addr寄存器。然后启动GPDMA

当link_src_sel=1,GPDMA从GPDMA_LINK_ID 、GPDMA_TASK_CFG_1 、GPDMA_BLOCK_LEN 、GPDMA_SRC_ADDR 、GPDMA_DST_ADDR 、GPDMA_TASK_LEN 、GPDMA_TASK_CFG_2与GPDMA_NEXT_TASK_ADDR 寄存器获取Task配置参数。对比link_src_sel=0,主要少了刷Cache的动作。

Task参数配置流程

GPDMA_LINK_ID =0xa1c8_6688

GPDMA_TASK_CFG_1 :dst_data_width、dst_type与dst_id参考设备重要配置信息,dst_burst=3。src_data_width、src_type与src_id参考设备重要配置信息,src_burst=3

GPDMA_BLOCK_LEN :block_len=外设FIFO触发GPDMA水位(或 GPDMA_FIFO_SIZE) 。

GPDMA_SRC_ADDR: 根据需求填写源端地址

GPDMA_DST_ADDR: 根据需求填写终端地址

GPDMA_TASK_LEN : 根据需求填写task_len

GPDMA_TASK_CFG_2 :当为最后一个Task:next_task_h8_addr设置为0xFF,否则为0x00

GPDMA_NEXT_TASK_ADDR :根据Link中下一个Task具体地址填写

GPDMA 编程说明

以下是以 SRAM 搬运数据到 SPI (SPI0) 为例的 GPDMA 配置步骤:

  1. 初始化参数。
    2. GPDMA 编程初始化参数示例
    源端 终端
    SRAM (假设 src _width=32)
    • src_width = 32
    • src_type = memory
    SPI (SPI0, id=8)
    • dst_width = 32
    • dst_type = io_multi
  2. 设置 block_len=16(Bytes)。
  3. 初始化 SPI ,并将 SPI 的FIFO水位设置为与block_len相等。此处设为 16
  4. 使能 GPDMA 模块时钟、释放 GPDMA 复位并使能 GPDMA 中断。
  5. 配置任务链表内容如下(链表存储器必须4Bytes对齐):
    3. GPDMA 任务链表编程示例
    地址 参数描述 备注
    0xa1c8_6688 GPDMA_LINK_ID TASK_LINK_ID 需要与 SET 一致。

    0x2288_2580

    GPDMA_TASK_CFG_1 -
    0x0000_0010 GPDMA_BLOCK_LEN -
    0x9004_7444 GPDMA_SRC_ADDR 源端地址:sram 首地址
    0x913f_0200 GPDMA_DST_ADDR 终端:SPI0 TX_FIFO 地址
    0x0000_00f4 GPDMA_TASK_LEN -
    0x55ff_0000 GPDMA_TASK_CFG_2 使用推荐值 0x55ff_0000。因为只有一个 task,故下一任务高 8bit 地址 =0xff
    0xffff_fffc GPDMA_NEXT_TASK_ADDR 因为只有一个 task,故下一任务低 32bit 地址 =0xffff_fffc。下一任务高 8bit 地址 + 下一任务低 32bit 地址 =0xff_fffffffc,表示 GPDMA Link 结束。
  6. 把任务链表首地址 (0x900406e0),写到 GPDMA 所对应通道的 GPDMA_CH_TASK_ADD_1 寄存器中。
  7. 启动 GPDMA 传输,等待 GPDMA 传输完成中断。