编程指南
- data_width需与外设FIFO位宽对齐。
- task_len设置需要与data_width对齐。

外设到外设传输
- 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)
| 对象 | 参数 | 配置值例 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 配置步骤:
- 初始化参数。
表 2. GPDMA 编程初始化参数示例 源端 终端 SRAM (假设 src _width=32) src_width = 32src_type = memory
SPI (SPI0, id=8) dst_width = 32dst_type = io_multi
- 设置 block_len=16(Bytes)。
- 初始化 SPI ,并将 SPI 的FIFO水位设置为与block_len相等。此处设为 16
- 使能 GPDMA 模块时钟、释放 GPDMA 复位并使能 GPDMA 中断。
- 配置任务链表内容如下(链表存储器必须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 结束。 - 把任务链表首地址 (0x900406e0),写到 GPDMA 所对应通道的 GPDMA_CH_TASK_ADD_1 寄存器中。
- 启动 GPDMA 传输,等待 GPDMA 传输完成中断。
