DMA 控制器(DMAC)

概述

通用直接内存访问(General Direct Memory Access,GDMA)控制器,也称 DMAC,用于在内存与外设之间传输数据。搬运过程中无需 CPU 介入, 降低了 CPU 的工作负载。DMAC 架构示意图如下:

../../_images/dmac_arch.svg

DMAC 支持以下特性:

RTL8721Dx:
  • 支持多达 8 个独立通道,通道的源端口和目的端口均可自由分配给 Memory 或者支持 DMAC 功能的外设

  • 支持通道优先级配置

  • 支持多种传输方向

    • 外设到内存

    • 外设到外设

    • 内存到外设

    • 内存到内存

  • 每个通道均内置独立的 FIFO,其中各通道 FIFO 大小不同,可满足不同应用场景

  • 可以灵活设定流控(Flow Control),由用户决定是由源外设、目的外设还是 DMAC 控制传输请求和节奏

  • 支持单次和突发(burst)传输模式

  • 支持单个数据块和多个数据块传输

  • 支持安全传输模式

  • 支持低功耗

  • 支持数据传输过程中暂停、恢复和关闭传输通道

DMAC 配置

DMA 一般配置流程如下:

  1. 初始化时钟:打开 DMA 控制器(DMAC)时钟

  2. 配置相关 DMA 通道

  1. 申请一个空闲的 DMA 通道

  2. 根据应用需求,配置通道控制参数

  1. 传输方向和流控:如内存到外设、外设到内存等,以及由源或目的外设、或 DMAC 控制传输请求和节奏

  2. 源端口和目的端口地址

  3. 传输宽度(1/2/4 Bytes)

  4. 突发长度 msize(1/4/8/16)

  5. 传输块大小(Block Size)

  6. 优先级设置

  1. 使能通道中断(如需传输完成/异常通知)

  2. 启动数据传输:打开通道使能位,启动 DMA 通道,外设/DMAC 发起 DMA 请求,启动数据搬运过程

  3. 结束与后处理

    1. DMA 传输完成后,产生中断

    2. 在中断服务函数中处理完成信号、释放资源等

DMA 参数示意图如下所示:

../../_images/dmac_block_size_diagram.svg

通道申请和释放

DMA 通过以下两个 API 实现通道的申请和释放:

  • GDMA_ChnlAlloc() :按顺序从通道 0 开始分配

  • GDMA_ChnlFree() :按照指定的通道编号释放通道

通道申请过程中,可能出现两个 CPU 同时申请一个通道,这会导致程序运行异常。为解决该问题,在通道申请过程中,会使用硬件信号量来 保护。

传输方向和流控制器

目前共有四种传输方向和两种流控制器设置,共八种可用配置。

  • 当外设作为流控制器时,DMA 将根据外设发出的单次/突发请求进行数据传输。

  • 当 DMAC 作为流控制器时,所有来自外设的请求都将按照配置的请求进行处理。

CTLx.TT_FC[2:0](x为通道编号)

方向

流控制器

000

内存 到 内存

DMAC

001

内存 到 外设

DMAC

010

外设 到 内存

DMAC

011

外设 到 外设

DMAC

100

外设 到 内存

外设

101

外设 到 外设

源外设

110

内存 到 外设

外设

111

外设 到 外设

目的外设

流控制器配置原则:

  • 如果 block_ts 已知,使用 DMAC 作为流控制器。例如播放音乐、图片等,以及搬运内存数据。

  • 如果 block_ts 未知,使用外设作为流控制器。例如 UART 接收不定长数据,可以让 UART 做流控制器,每当有数据来临再请求传输。

警告

  • 仅当 DMAC 用作流控制器时,才能设置 block_ts 参数。

  • 使用外设作为流控制器,需要确保 IP 在硬件设计上支持触发 DMA 请求。详情可参考 握手 章节。

数据块大小

RTL8721Dx:

上图阐述了 DMAC 传输数据大小的设置。block_ts 表示将在单个数据块中传输的数据量,需要设置为 总数据量/SRC_TR_WIDTH,最大值是 {{IC_PARAM_GDMA_BLOCK_SIZE}}

事务模式和宽度

DMAC 传输时,单次传输事务(Transaction)的大小可配置:

  • msize > 1:突发传输

  • msize = 1:单次传输

CTLx.SRC_MSIZE[2:0]/DEST_MSIZE[2:0]

传输 msize

000

1

001

4

010

8

011

16

100 及以上

不支持

DMAC 支持以下传输宽度:

CTLx.SRC_TR_WIDTH[2:0]/DST_TR_WIDTH[2:0]

传输宽度/Byte

000

1

001

2

010

4

011 及以上

不支持

  • 当 DMAC 作为流控制器,单个数据块传输到最后,剩余的数据量不足以完成一次 Msize * Width 传输,但满足一次 1 * Width 传输,DMAC 将发起单次传输请求,完成传输。

  • 当外设作为流控制器,外设决定发出单次传输还是突发传输请求。

备注

  • 读写外设时: SRC_TR_WIDTH/DST_TR_WIDTH 根据外设的数据宽度决定。

  • 读写内存时:

    • 如果缓存被禁用,内存地址无需对齐,但需确保总数据量能被 SRC_TR_WIDTH 整除,以保证 block_ts 为整数。

    • 如果缓存被启用,内存地址必须满足缓冲区边界对齐,且需按缓存行对齐。

  • 当源或者目的是内存时(如 P2M、M2M 模式):硬件将强制 Memory 端的传输位宽为 4 Bytes,配置的 DST_TR_WIDTHSRC_TR_WIDTH 参数将被忽略。

  • 为防止 FIFO 溢出或下溢,要求 SRC_MSIZE * SRC_TR_WIDTH 必须等于 DST_MSIZE * DST_TR_WIDTH

传输类型

DMAC 支持以下传输类型:

  • Single Block: 仅包含一个数据块

  • Multi-Block:包含多个数据块

    • 自动重加载(Auto-reloading)模式

    • 链表(Link List)模式

    • 连续(Continuous)模式

各个模式使用场景及特点如下:

DMAC 各模式特点

模式

子模式

使用场景

特点

Single Block

地址空间连续且仅传输一次

  • 传输完成后 DMA 立即停止

Multi-Block

auto-reload

地址空间连续且源端或者目的端需要重复加载某一个数据块

  • 若开启块中断,每个块传输完成都会暂停,直到中断处理结束

Link List

地址空间非连续

  • 若开启块中断,每个块传输完成后触发中断,但将立即传输下一个块

  • 该模式下,即便进入中断也不会阻碍 DMA 数据传输

continuous

单个地址空间连续的数据块

  • 始终保持地址递增模式,若源和目的端均为 continuous 模式,则传输与 single block 相同

  • 通常用于仅一端为连续地址、另一端使用 auto-reload 或 Link List 模式的场景

Auto-reloading 模式

在 auto-reloading 模式下,源和目标可分别选择使用的方法。

Auto-reloading 传输类型

设置

说明

Src auto reload

PGDMA_InitTypeDef->GDMA_ReloadSrc = 1

PGDMA_InitTypeDef->GDMA_ReloadDst = 0

对多块传输(multi-block transfers),每块结束时SAR寄存器会从初始值自动重载,目的地址连续,如

Multi-Block 传输-源地址自动重载&目的地址连续 所示。

Dst auto reload

PGDMA_InitTypeDef->GDMA_ReloadSrc = 0

PGDMA_InitTypeDef->GDMA_ReloadDst = 1

对多块传输,每块结束时DAR寄存器会从初始值自动重载,源地址连续。

Src & Dst auto reload

PGDMA_InitTypeDef->GDMA_ReloadSrc = 1

PGDMA_InitTypeDef->GDMA_ReloadDst = 1

对多块传输,每块结束时SAR和DAR寄存器都会从初始值自动重载,如 Multi-Block 传输-源和目的地址均自动重载 所示。

../../_images/mbd_source_auto_dest_cont.png

Multi-Block 传输-源地址自动重载&目的地址连续

../../_images/mbd_source_dest_auto.png

Multi-Block 传输-源和目的地址均自动重载

地址递增类型

源地址递增

包含两种模式:

  • 递增(Increment):表示在每次源端传输时,源地址是否递增。递增操作用于对齐到下一个 CTLx.SRC_TR_WIDTH 边界。

  • 不变(No change):如果设备从具有固定地址的源外设 FIFO 读取数据,则应将该字段设置为"不变"。

目的地址递增

包含两种模式:

  • 递增(Increment):表示在每次目的端传输时,目的地址是否递增。递增操作用于对齐到下一个 CTLx.DST_TR_WIDTH 边界。

  • 不变(No change):如果设备将数据写入到具有固定地址的目的外设 FIFO,则应将该字段设置为"不变"。

配置原则:

  • 如果源端或者目的端为 Memory,地址模式一般设置为 Increment

  • 如果源端或者目的端为外设,地址模式一般设置为 No Change

FIFO

每个 DMAC 通道都有自己独立的 FIFO,且不同通道的 FIFO 大小不同。

RTL8721Dx:
FIFO Size

通道号

CH0

CH1

CH2~CH7

FIFO 大小/Bytes

128

128

32

中断类型

DMAC 支持多种中断类型,这些中断可独立使用或组合使用。

中断类型

说明

块中断

单个数据块传输完成触发

传输中断

所有数据块传输完毕时产生

错误中断

传输过程中发生错误

备注

  • 多块 auto-reload 模式下,块中断触发后将暂停传输,待中断处理函数执行完毕后再继续。

  • Link List 模式的传输完成条件为:最后一个数据块的下一数据块指针为空。

  • Link List 模式下,块中断不会暂停传输,下一个数据块将立即开始传输。

挂起和终止

DMAC 支持通道的挂起恢复和强制终止。

  • 挂起通道:直接配置 CFGx.CH_SUSP,但不保证当前数据传输已完成。需结合 CFGx.INACTIVE 状态检测,方可安全暂停且不丢失数据。

  • 恢复传输:清除 CFGx.CH_SUSP 即可继续进行数据传输。

  • 终止传输:需持续轮询 CFGx.INACTIVE 直至该位设为 1,方可终止传输。

备注

CFGx.INACTIVE 用于指示通道在 AXI 总线上是否处于空闲状态(1 = 非活跃,0 = 活跃)。可与 CFGx.CH_SUSP 配合使用,在目的端为外设时安全关闭通道。通道进入非活跃状态的场景:

  • DMAC 完成所有待写数据的内存写入操作后,CFGx.INACTIVE 自动置 1。

  • 外设数据宽度(如 4 字节)超出 DMAC FIFO 剩余空间(如 2 字节),无法发起写操作,CFGx.INACTIVE 立即置 1。

聚集和分散

RTL8721Dx:

不支持。

优先级

DMAC 支持两种通道优先级:

  • 软件:各通道优先级可通过 CFGx.CH_PRIOR 配置,有效值范围为 0 ~ (DMAC_NUM_CHANNELS-1)。其中, 0 为最高优先级, DMAC_NUM_CHANNELS-1 为最低优先级。

  • 硬件:若两个通道请求的软件优先级相同,或未配置软件优先级,通道编号较小的通道优先级更高(例如:通道 2 优先级高于通道 4)。

握手

DMAC 仅支持硬件握手,不支持软件握手。仅在与外设进行数据传输时,才需配置握手接口。所有硬件握手接口在 IC 设计阶段已固定,用户无法自行更改。 当前 IC 支持的硬件握手接口及其对应 IP 如下表所示:

RTL8721Dx:
DMAC 握手接口

功能

握手编号

说明

UART0 TX

0

UART0 RX

1

UART1 TX

2

UART1 RX

3

UART2 TX

4

UART2 RX

5

SPI0 TX

6

SPI0 RX

7

SPI1 TX

8

SPI1 RX

9

SPIC TX

10

SPIC RX

11

SPORT0 TX

12

两个FIFO,占用编号12和13

SPORT0 RX

14

两个FIFO,占用编号14和15

SPORT1 TX

16

两个FIFO,占用编号16和17

SPORT1 RX

18

两个FIFO,占用编号18和19

LEDC_TX

20

I2C0 TX

21

I2C0 RX

22

I2C1 TX

23

I2C1 RX

24

实时状态获取

DMAC 支持实时获取当前传输的源地址、目的地址和已传输数据量。

需调用对应 API 读取。

备注

若要获取已传输数据量,block_ts 必须至少大于 768,且不可在中断函数中读取;否则,获取的值始终为 0。

安全机制

默认情况下,DMAC 的安全传输功能处于关闭状态。当用户需要使用该功能时,需首先开启 Trustzone 功能

DMAC 支持针对每个通道独立配置安全传输功能。启用该功能后,DMAC 将通过 AXI 主机接口发起 Secure 访问请求。此时,DMAC 可以在安全和非安全的外设(或内存)之间传递数据。

  • 安全通道仅能在安全世界中配置,且安全通道可访问安全外设(内存)和非安全外设(内存);

  • 非安全通道仅能访问非安全外设(内存)。

要启用某通道的安全传输特性,可在 Secure 代码中配置 DMAC 参数时,设置如下结构体成员:

PGDMA_InitTypeDef->SecureTransfer = 1;

DMA 和缓存

当使用 DMA 在内存之间或者内存和外设之间传输数据,如果此时 Cache 也正常启用,需要注意 Cache 和内存数据不一致的问题。

DMA TX

当 DMA 的源端是 Memory,需要发送数据时,一般流程如下:

  1. 申请发送缓冲区,需要确保起始地址和大小都与 Cache Line 对齐。

  2. CPU 将数据写入 Memory 缓冲区。

  3. 调用 DCache_Clean() 函数清理数据缓存

  4. 配置 DMA 发送参数

  5. DMA 启动传送

DMA RX

  1. CPU 分配接收缓冲区

  2. 执行 DCache_Clean() 确保接收缓冲区处于 clean 状态(如果接收缓冲区处于 clean 状态,可跳过此步骤)

    小心

    此步骤执行的原因是:

    • 对于 Cortex-A32,如果 Cache 中的接收缓冲区处于 dirty 状态,执行第 5 步 DCache_Invalidate() 将同时执行 cleaninvalidate 操作,可能会导致意外写入行为。

    • 如果 Cache 中的接收缓冲区处于 dirty 状态,当 CPU 的 D-Cache 满了,CPU 可能会将接收缓冲区中的脏数据写回内存,覆盖 DMA 已经写入的内容。

  3. 配置 DMA Rx 参数

  4. 配置并使能 DMA Rx 中断处理函数

  5. 执行 DCache_Invalidate() 作废 Cache 中对应的数据,确保 Cache 没有残留旧的接收缓冲区数据。

小心

此步骤必须执行,原因如下:

  • 对于具有自动数据预取功能的 CPU(如 Cortex-A32 和 DSP),当 CPU 读取接收缓冲区相邻地址的内容时,CPU 会在后台执行行填充操作,自动将接收缓冲区的旧值重新加载到 Cache 中。

  • 防止 CPU 在 DMA 处理期间将旧值读入 Cache。

  1. CPU 读取接收缓冲区(DMA Rx 返回的值)

备注

将缓冲区地址与 Cache Line 行对齐将减少 Cache 与内存数据不一致的问题。

DMAC 示例

单块

  1. 分配一个空闲通道

    ch_num = GDMA_ChnlAlloc(gdma.index, (IRQ_FUN) Dma_memcpy_int, (u32)(&gdma), 3);
    

    这个函数同时包含以下操作:

    • 注册 IRQ 处理程序(如果使用中断模式)

    • 启用 NVIC 中断

    • 注册要使用的 DMAC 通道

  2. 配置中断类型

    PGDMA_InitTypeDef->GDMA_IsrType = (TransferType | ErrType);
    
  3. 配置中断处理函数

    在中断处理函数中清除挂起的中断。

    GDMA_ClearINT(0, PGDMA_InitTypeDef->GDMA_ChNum);
    
  4. 传输配置

    PGDMA_InitTypeDef->GDMA_SrcMsize   = MsizeEight;
    PGDMA_InitTypeDef->GDMA_SrcDataWidth = TrWidthFourBytes;
    PGDMA_InitTypeDef->GDMA_DstMsize = MsizeEight;
    PGDMA_InitTypeDef->GDMA_DstDataWidth = TrWidthFourBytes;
    PGDMA_InitTypeDef->GDMA_BlockSize = DMA_CPY_LEN >> 2;
    PGDMA_InitTypeDef->GDMA_DstInc = IncType; // if dst type is peripheral:no change
    PGDMA_InitTypeDef->GDMA_SrcInc = IncType; // if src type is peripheral:no change
    
  5. 配置硬件握手接口(如果目的端或源端为外设)

    PGDMA_InitTypeDef->GDMA_SrcHandshakeInterface= GDMA_HANDSHAKE_INTERFACE_AUDIO_RX;
    

    PGDMA_InitTypeDef->GDMA_DstHandshakeInterface = GDMA_HANDSHAKE_INTERFACE_AUDIO_TX;
    
  6. 配置传输地址

    PGDMA_InitTypeDef->GDMA_SrcAddr = (u32)BDSrcTest;
    PGDMA_InitTypeDef->GDMA_DstAddr = (u32)BDDstTest;
    
  7. 使用 GDMA_Init() 函数设置 DMAC 索引、通道、数据宽度、msize、传输方向、地址递增模式、硬件握手接口、重载控制、中断类型、块大小、多块配置,以及源地址和目的地址

    GDMA_Init(gdma.index, gdma.ch_num, PGDMA_InitTypeDef);
    
  8. 清理缓存

    DCache_CleanInvalidate();
    
  9. 启用 DMAC 通道

GDMA_Cmd(gdma.index, gdma.ch_num, ENABLE);

多块

这是 SRC 自动重载模式的示例。与单块相比,多块的 步骤 2 ~ 步骤 4 不同。

  1. 分配一个空闲通道

    ch_num = GDMA_ChnlAlloc(gdma.index, (IRQ_FUN) Dma_memcpy_int, (u32)(&gdma), 3);
    

    这个函数同时包含以下操作:

    • 注册 IRQ 处理程序(如果使用中断模式)

    • 启用 NVIC 中断

    • 注册要使用的 DMAC 通道

  2. 配置中断类型

    PGDMA_InitTypeDef->GDMA_IsrType = (BlockType | TransferType | ErrType);
    
  3. 配置中断处理函数

    1. 清除中断

      GDMA_ClearINT(0, PGDMA_InitTypeDef->GDMA_ChNum);
      
    2. 在最后一个数据块开始之前清除自动重载模式

      GDMA_ChCleanAutoReload(0, PGDMA_InitTypeDef->GDMA_ChNum, CLEAN_RELOAD_SRC);
      
  4. 传输配置

    PGDMA_InitTypeDef->GDMA_SrcMsize   = MsizeEight;
    PGDMA_InitTypeDef->GDMA_SrcDataWidth = TrWidthFourBytes;
    PGDMA_InitTypeDef->GDMA_DstMsize = MsizeEight;
    PGDMA_InitTypeDef->GDMA_DstDataWidth = TrWidthFourBytes;
    PGDMA_InitTypeDef->GDMA_BlockSize = DMA_CPY_LEN >> 2;
    PGDMA_InitTypeDef->GDMA_DstInc = IncType; // If DST type is peripheral: no change
    PGDMA_InitTypeDef->GDMA_SrcInc = IncType; // If SRC type is peripheral: no change
    PGDMA_InitTypeDef->GDMA_ReloadSrc = 1;
    PGDMA_InitTypeDef->GDMA_ReloadDst = 0;
    
  5. 配置硬件握手接口(如果目的端或源端为外设)

    PGDMA_InitTypeDef->GDMA_SrcHandshakeInterface= GDMA_HANDSHAKE_INTERFACE_AUDIO_RX;
    

    PGDMA_InitTypeDef->GDMA_DstHandshakeInterface = GDMA_HANDSHAKE_INTERFACE_AUDIO_TX;
    
  6. 配置传输地址

    PGDMA_InitTypeDef->GDMA_SrcAddr = (u32)BDSrcTest;
    PGDMA_InitTypeDef->GDMA_DstAddr = (u32)BDDstTest;
    
  7. 使用 GDMA_Init() 函数设置 DMAC 索引、通道、数据宽度、msize、传输方向、地址递增模式、硬件握手接口、重载控制、中断类型、块大小、多块配置,以及源地址和目的地址

    GDMA_Init(gdma.index, gdma.ch_num, PGDMA_InitTypeDef);
    
  8. 清理缓存

    DCache_CleanInvalidate();
    
  9. 启用 DMAC 通道

    GDMA_Cmd(gdma.index, gdma.ch_num, ENABLE);
    

Raw API

GDMA Exported Types

struct GDMA_CH_LLI

GDMA CH LLI Structure Definition.

Public Members

GDMA_CH_LLI_ELE LliEle

Specifies the GDMA Linked List Item Element structure field of Linked List Item in block chaining. This structure variable stores the necessary parameters of a block descriptor.

u32 BlockSize

Specifies the GDMA block size of one block in block chaining. This parameter indicates the block size of the current block transfer.

struct GDMA_CH_LLI *pNextLli

Specifies the GDMA Linked List Item pointer. This parameter stores the address pointing to the next Linked List Item in block chaining.

struct GDMA_CH_LLI_ELE

GDMA LLI ELE Structure Definition.

Public Members

u32 Sarx

Specifies the GDMA channel x Source Address Register (SARx) value field of a block descriptor in block chaining. This parameter stores the source address of the current block transfer.

u32 Darx

Specifies the GDMA channel x Destination Address Register(DARx) value field of a block descriptor in block chaining. This parameter stores the destination address of the current block transfer.

u32 Llpx

Specifies the GDMA channel x Linked List Pointer Register(LLPx) value field of a block descriptor in block chaining. This parameter is a address, which points to the next block descriptor.

u32 CtlxLow

Specifies the GDMA channel x Control Register(CTRx) Low 32 bit value field of a block descriptor in block chaining. This parameter stores the DMA control parameters of the current block transfer.

u32 CtlxUp

Specifies the GDMA channel x Control Register(CTRx) High 32 bit value field of a block descriptor in block chaining. This parameter stores the DMA control parameters of the current block transfer.

u32 Temp

Specifies the reserved GDMA channel x register value field of a block descriptor in block chaining.

struct GDMA_InitTypeDef

GDMA Init Structure Definition.

Public Members

u8 GDMA_Index

Specifies the GDMA index. This parameter can be the value 0.

u8 GDMA_ChNum

Specifies the GDMA channel number. This parameter can be the value 0 ~ 7.

u8 GDMA_ChPrior

Specifies the GDMA channel priority. This parameter can be the value 0 ~ 7, while 0 for highest priority. If more than one channel are set with the same priority value, the channel with small channel number index has higher priority.

u32 GDMA_DIR

Specifies the GDMA transmission direction. This parameter can be a value of GDMA Data Transfer Direction

u32 GDMA_DstDataWidth

Specifies the GDMA destination transfer width. This parameter can be a value of GDMA Data Size

u32 GDMA_SrcDataWidth

Specifies the GDMA transfer width. This parameter can be a value of GDMA Data Size

u32 GDMA_DstInc

Specifies the GDMA destination address increment mode. This parameter can be a value of GDMA Increment Mode

u32 GDMA_SrcInc

Specifies the GDMA source address increment mode. This parameter can be a value of GDMA Increment Mode

u32 GDMA_DstMsize

Specifies the GDMA destination burst transaction length. This parameter can be a value of GDMA Msize

u32 GDMA_SrcMsize

Specifies the GDMA source burst transaction length. This parameter can be a value of GDMA Msize

u32 GDMA_SrcAddr

Specifies the GDMA source address. This parameter can be a value of the memory or peripheral space address, depending on the GDMA data transfer direction.If this address is configured, GDMA will move data from here to the destination address space

u32 GDMA_DstAddr

Specifies the GDMA destination address. This parameter can be a value of the memory or peripheral space address, depending on the GDMA data transfer direction.If this address is configured, GDMA will move data here from source address space

u32 GDMA_BlockSize

Specifies the GDMA block transfer size. This parameter indicates the total number of single transactions for every block transfer.

u32 GDMA_IsrType

Specifies the GDMA interrupt types. This parameter can be a value of GDMA Interrupt Type

u32 GDMA_ReloadSrc

Specifies the GDMA automatic source reload . This parameter can be the 0 or 1.(0 : disable / 1 : enable). if this value is set to 1, source address register can be automatically reloaded from its initial value at the end of every block for multi-block transfers. this parameter is only valid in multi block transmission mode

u32 GDMA_ReloadDst

Specifies the GDMA automatic destination reload . This parameter can be the 0 or 1.(0 : disable / 1 : enable). if this parameter is set 1, destination address register can be automatically reloaded from its initial value at the end of every block for multi-block transfers. this parameter is only valid in multi block transmission mode

u32 GDMA_LlpDstEn

Specifies the GDMA whether block chaining is enabled or disabled on the destination side only. this parameter is only valid in multi-block transmission mode

u32 GDMA_LlpSrcEn

Specifies the GDMA whether block chaining is enabled or disabled on the source side only. this parameter is only valid in multi-block transmission mode

u32 GDMA_SrcHandshakeInterface

Specifies the GDMA hardware handshaking interface for the source peripheral of a GDMA channel. This parameter can be a value of GDMA0 HS HandShake Interface

u32 GDMA_DstHandshakeInterface

Specifies the GDMA hardware handshaking interface for the destination peripheral of a GDMA channel. This parameter can be a value of GDMA0 HS HandShake Interface

u32 MuliBlockCunt

Specifies the GDMA Multi-block counter. This parameter is used in multi-block transmission.

u32 MaxMuliBlock

Specifies the GDMA Max block number in Multi-block transmission. This parameter is used in multi-block transmission.

u32 SecureTransfer

Specifies the GDMA secure transmission. This parameter is used in secure world of trustzone.

typedef struct GDMA_CH_LLI_ELE *PGDMA_CH_LLI_ELE
typedef struct GDMA_InitTypeDef *PGDMA_InitTypeDef

GDMA Exported Constants

GDMA0 HS HandShake Interface

/* Handshake interface for UART0 TX. */
#define GDMA_HANDSHAKE_INTERFACE_UART0_TX (0)

/* Handshake interface for UART0 RX. */
#define GDMA_HANDSHAKE_INTERFACE_UART0_RX (1)

/* Handshake interface for UART1 TX. */
#define GDMA_HANDSHAKE_INTERFACE_UART1_TX (2)

/* Handshake interface for UART1 RX. */
#define GDMA_HANDSHAKE_INTERFACE_UART1_RX (3)

/* Handshake interface for UART2 TX. */
#define GDMA_HANDSHAKE_INTERFACE_UART2_TX (4)

/* Handshake interface for UART2 RX. */
#define GDMA_HANDSHAKE_INTERFACE_UART2_RX (5)
RTL8721Dx:
/* Handshake interface for SPI0 TX. */
#define GDMA_HANDSHAKE_INTERFACE_SPI0_TX (6)

/* Handshake interface for SPI0 RX. */
#define GDMA_HANDSHAKE_INTERFACE_SPI0_RX (7)

/* Handshake interface for SPI1 TX. */
#define GDMA_HANDSHAKE_INTERFACE_SPI1_TX (8)

/* Handshake interface for SPI1 RX. */
#define GDMA_HANDSHAKE_INTERFACE_SPI1_RX (9)

/* Handshake interface for SPIC TX. */
#define GDMA_HANDSHAKE_INTERFACE_SPIC_TX (10)

/* Handshake interface for SPIC RX. */
#define GDMA_HANDSHAKE_INTERFACE_SPIC_RX (11)

/* Handshake interface for SPORT0 FIFO0 TX. */
#define GDMA_HANDSHAKE_INTERFACE_SPORT0F0_TX (12)

/* Handshake interface for SPORT0 FIFO1 TX. */
#define GDMA_HANDSHAKE_INTERFACE_SPORT0F1_TX (13)

/* Handshake interface for SPORT0 FIFO0 RX. */
#define GDMA_HANDSHAKE_INTERFACE_SPORT0F0_RX (14)

/* Handshake interface for SPORT0 FIFO1 RX. */
#define GDMA_HANDSHAKE_INTERFACE_SPORT0F1_RX (15)

/* Handshake interface for SPORT1 FIFO0 TX. */
#define GDMA_HANDSHAKE_INTERFACE_SPORT1F0_TX (16)

/* Handshake interface for SPORT1 FIFO1 TX. */
#define GDMA_HANDSHAKE_INTERFACE_SPORT1F1_TX (17)

/* Handshake interface for SPORT1 FIFO0 RX. */
#define GDMA_HANDSHAKE_INTERFACE_SPORT1F0_RX (18)

/* Handshake interface for SPORT1 FIFO1 RX. */
#define GDMA_HANDSHAKE_INTERFACE_SPORT1F1_RX (19)

/* Handshake interface for LEDC TX. */
#define GDMA_HANDSHAKE_INTERFACE_LEDC_TX (20)

/* Handshake interface for I2C0 TX. */
#define GDMA_HANDSHAKE_INTERFACE_I2C0_TX (21)

/* Handshake interface for I2C0 RX. */
#define GDMA_HANDSHAKE_INTERFACE_I2C0_RX (22)

/* Handshake interface for I2C1 TX. */
#define GDMA_HANDSHAKE_INTERFACE_I2C1_TX (23)

/* Handshake interface for I2C1 RX. */
#define GDMA_HANDSHAKE_INTERFACE_I2C1_RX (24)

/* Handshake interface for Zigbee TX. */
#define GDMA_HANDSHAKE_INTERFACE_Zigbee_TX (NULL)

/* Handshake interface for Zigbee RX. */
#define GDMA_HANDSHAKE_INTERFACE_Zigbee_RX (NULL)

/* Handshake interface for ADC RX. */
#define GDMA_HANDSHAKE_INTERFACE_ADC_RX (NULL)

/* Handshake interface for Audio TX. */
#define GDMA_HANDSHAKE_INTERFACE_AUDIO_TX (NULL)

/* Handshake interface for Audio RX. */
#define GDMA_HANDSHAKE_INTERFACE_AUDIO_RX (NULL)

GDMA Data Size

/* Transfer width of one byte. */
#define TrWidthOneByte ((u32)0x00000000)

/* Transfer width of two bytes. */
#define TrWidthTwoBytes ((u32)0x00000001)

/* Transfer width of four bytes. */
#define TrWidthFourBytes ((u32)0x00000002)

/* Check if GDMA data size value is valid. */
#define IS_GDMA_DATA_SIZE (((SIZE) == TrWidthOneByte) || \
    ((SIZE) == TrWidthTwoBytes) || \
    ((SIZE) == TrWidthFourBytes))

GDMA Data Transfer Direction

/* Memory to memory transfer. */
#define TTFCMemToMem ((u32)0x00000000)

/* Memory to peripheral transfer. */
#define TTFCMemToPeri ((u32)0x00000001)

/* Peripheral to memory transfer. */
#define TTFCPeriToMem ((u32)0x00000002)

/* Peripheral to peripheral transfer. */
#define TTFCPeriToPeri ((u32)0x00000003)

/* Peripheral to memory, peripheral as flow controller. */
#define TTFCPeriToMem_PerCtrl ((u32)0x00000004)

/* Peripheral to peripheral, source peripheral as flow controller. */
#define TTFCPeriToPeri_SrcPerCtrl ((u32)0x00000005)

/* Memory to peripheral, peripheral as flow controller. */
#define TTFCMemToPeri_PerCtrl ((u32)0x00000006)

/* Peripheral to peripheral, destination peripheral as flow controller. */
#define TTFCPeriToPeri_DstPerCtrl ((u32)0x00000007)

/* Check if GDMA transfer direction value is valid. */
#define IS_GDMA_DIR (((DIR) == TTFCMemToMem) || \
    ((DIR) == TTFCMemToPeri) || \
    ((DIR) == TTFCPeriToMem) ||\
    ((DIR) == TTFCPeriToPeri) ||\
    ((DIR) == TTFCPeriToMem_PerCtrl) || \
    ((DIR) == TTFCPeriToPeri_SrcPerCtrl) || \
    ((DIR) == TTFCPeriToPeri_DstPerCtrl) || \
    ((DIR) == TTFCMemToPeri_PerCtrl))

GDMA Increment Mode

/* Address increment mode. */
#define IncType ((u32)0x00000000)

/* Address decrement mode. */
#define DecType ((u32)0x00000001)

/* Address no-change mode. */
#define NoChange ((u32)0x00000002)

/* Check if GDMA increment mode value is valid. */
#define IS_GDMA_IncMode (((STATE) == IncType) || \
    ((STATE) == DecType) || \
    ((STATE) == NoChange))

GDMA Index Channel Definition

/* Maximum GDMA index value. */
#define MAX_GDMA_INDX (0)

/* Maximum GDMA channel number. */
#define MAX_GDMA_CHNL (7)

/* Check if GDMA channel number is valid. */
#define IS_GDMA_ChannelNum ((NUM) <= MAX_GDMA_CHNL)

/* Check if GDMA index value is valid. */
#define IS_GDMA_Index ((NUM) <= MAX_GDMA_INDX)

GDMA Interrupt Type

/* DMA transfer complete interrupt type. */
#define TransferType ((u32)0x00000001)

/* DMA block transfer complete interrupt type. */
#define BlockType ((u32)0x00000002)

/* DMA transfer error interrupt type. */
#define ErrType ((u32)0x000000010)

/* Check if GDMA interrupt type configuration is valid. */
#define IS_GDMA_CONFIG_IT ((((IT) & 0xFFFFFFE0) == 0x00) && ((IT) != 0x00))

GDMA Msize

/* Burst transaction length of 1 item. */
#define MsizeOne ((u32)0x00000000)

/* Burst transaction length of 4 items. */
#define MsizeFour ((u32)0x00000001)

/* Burst transaction length of 8 items. */
#define MsizeEight ((u32)0x00000002)

/* Burst transaction length of 16 items. */
#define MsizeSixteen ((u32)0x00000003)

/* Burst transaction length of 32 items. */
#define Msize32 ((u32)0x00000004)

/* Burst transaction length of 64 items. */
#define Msize64 ((u32)0x00000005)

/* Burst transaction length of 128 items. */
#define Msize128 ((u32)0x00000006)

/* Burst transaction length of 256 items. */
#define Msize256 ((u32)0x00000007)

/* Check if GDMA Msize value is valid. */
#define IS_GDMA_MSIZE (((SIZE) == MsizeOne) || \
    ((SIZE) == MsizeFour) || \
    ((SIZE) == MsizeEight)|| \
    ((SIZE) == MsizeSixteen) || \
    ((SIZE) == Msize32) || \
    ((SIZE) == Msize64) || \
    ((SIZE) == Msize128) || \
    ((SIZE) == Msize256))

GDMA Reload Definition

/* Clean source auto-reload. */
#define CLEAN_RELOAD_SRC ((u32)0x00000001)

/* Clean destination auto-reload. */
#define CLEAN_RELOAD_DST ((u32)0x00000002)

/* Clean both source and destination auto-reload. */
#define CLEAN_RELOAD_SRC_DST ((u32)0x00000003)

GDMA Interrupt Status

RTL8721Dx:

No content

GDMA Channel Status

RTL8721Dx:

No content

GDMA Exported Functions

u8 GDMA_Abort(u8 GDMA_Index, u8 GDMA_ChNum)

Abort a channel.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

返回:

TRUE if the channel is successfully aborted, FALSE otherwise.

void GDMA_ChCleanAutoReload(u8 GDMA_Index, u8 GDMA_ChNum, u32 CleanType)

GDMA AutoReload set.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • CleanType --

    This parameter can be any combination of the following values:

    • CLEAN_RELOAD_SRC

    • CLEAN_RELOAD_DST

u8 GDMA_ChnlAlloc(u32 GDMA_Index, IRQ_FUN IrqFun, u32 IrqData, u32 IrqPriority)

Allocate a free channel.

参数:
  • GDMA_Index -- Always 0.

  • IrqFun -- GDMA IRQ callback function.

  • IrqData -- GDMA IRQ callback data.

  • IrqPriority -- GDMA IrqPriority.

返回:

Allocated GDMA channel number, or 0xFF if no free channel is available.

u8 GDMA_ChnlFIFOIsEmpty(u8 GDMA_Index, u8 GDMA_ChNum)

Get whether the fifo is empty.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

返回:

TRUE if the channel FIFO is empty, FALSE otherwise.

u8 GDMA_ChnlFree(u8 GDMA_Index, u8 GDMA_ChNum)

Free a channel, this channel will not be used.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

返回:

TRUE if the channel is successfully freed, FALSE otherwise.

u32 GDMA_ClearINT(u8 GDMA_Index, u8 GDMA_ChNum)

Clear all the Pending Interrupt status.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

返回:

Active interrupt types whose interrupt status is cleared, refer to GDMA Interrupt Type.

备注

Clear all the active interrupts status for the current GDMA channel.

u32 GDMA_ClearINTPendingBit(u8 GDMA_Index, u8 GDMA_ChNum, u32 GDMA_IT)

Clear the specidied Pending Interrupt status.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • GDMA_IT --

    specifies the GDMA interrupt sources whose interrupt status will be cleared. This parameter can be one or combinations of the following values:

    • TransferType

    • BlockType

    • ErrType

返回:

Active interrupt types whose interrupt status is cleared, refer to GDMA Interrupt Type.

备注

This function completes clearing the specified type interrupt status. Which type interrupt status will be cleared, refer to the parameter "GDMA_IT".

void GDMA_Cmd(u8 GDMA_Index, u8 GDMA_ChNum, u32 NewState)

GDMA channel Disable/Enable.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • NewState -- Disable/Enable.

u32 GDMA_GetBlkSize(u8 GDMA_Index, u8 GDMA_ChNum)

Get the total number of data bytes written to the target memory or peripheral device during DMA transmission.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

返回:

Block size configured for the current GDMA channel.

u32 GDMA_GetDstAddr(u8 GDMA_Index, u8 GDMA_ChNum)

Get the destination writing address during DMA transmission.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

返回:

Destination address.

u8 GDMA_GetIrqNum(u8 GDMA_Index, u8 GDMA_ChNum)

Get irq number for a channel.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

返回:

IRQ number for the specified GDMA channel.

u32 GDMA_GetSrcAddr(u8 GDMA_Index, u8 GDMA_ChNum)

Get the source reading address during DMA transmission.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

返回:

Source address.

void GDMA_INTConfig(u8 GDMA_Index, u8 GDMA_ChNum, u32 GDMA_IT, u32 NewState)

Enables or disables the specified GDMA interrupts.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • GDMA_IT --

    specifies the GDMA interrupt sources to be enabled or disabled. This parameter can be one or combinations of the following values:

    • TransferType

    • BlockType

    • ErrType

  • NewState -- DISABLE/ENABLE.

void GDMA_Init(u8 GDMA_Index, u8 GDMA_ChNum, PGDMA_InitTypeDef GDMA_InitStruct)

Initialize the GDMA registers according to the specified parameters in GDMA_InitStruct.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • GDMA_InitStruct -- pointer to a GDMA_InitTypeDef structure that contains the configuration information for the GDMA peripheral.

void GDMA_Resume(u8 GDMA_Index, u8 GDMA_ChNum)

Resume a channel.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

void GDMA_SetBlkSize(u8 GDMA_Index, u8 GDMA_ChNum, u32 BlkSize)

Set GDMA block size.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

void GDMA_SetChnlPriority(u8 GDMA_Index, u8 GDMA_ChNum, u32 ChnlPriority)

Set channel priority.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • ChnlPriority -- channel priority to set.

void GDMA_SetDstAddr(u8 GDMA_Index, u8 GDMA_ChNum, u32 DstAddr)

Set destination address.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • DstAddr -- destination address

void GDMA_SetLLP(u8 GDMA_Index, u8 GDMA_ChNum, u32 MultiBlockCount, struct GDMA_CH_LLI *pGdmaChLli, u32 round)

Set LLP mode when use GDMA Linked List Pointer Register.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • MultiBlockCount -- block counts.

  • pGdmaChLli -- LLP node list, point to a Linked List Item.

  • round --

    • 0 Linear list, last node id last one

    • 1 Last node is not the end.

void GDMA_SetSrcAddr(u8 GDMA_Index, u8 GDMA_ChNum, u32 SrcAddr)

Set source address.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

  • SrcAddr -- source address

void GDMA_StructInit(PGDMA_InitTypeDef GDMA_InitStruct)

Fill each GDMA_InitStruct member with its default value.

参数:
  • GDMA_InitStruct -- pointer to a GDMA_InitTypeDef structure which will be initialized.

void GDMA_Suspend(u8 GDMA_Index, u8 GDMA_ChNum)

Suspend a channel.

参数:
  • GDMA_Index -- Always 0.

  • GDMA_ChNum -- 0 ~ 7.

RTL8721Dx:

No content

Mbed API

MBED_GDMA Exported Types

Structure Type

typedef struct gdma_s gdma_t

typedef struct gdma_s to gdma_t

MBED_GDMA Exported Functions

void dma_memcpy(gdma_t *dma_obj, void *dst, void *src, uint32_t len)

Accomplish memory copy by DMA.

参数:
  • dma_obj -- GDMA object defined in application software.

  • dst -- Destination memory address.

  • src -- Source memory address.

  • len -- Copy data length.

void dma_memcpy_deinit(gdma_t *dma_obj)

Deinitialize the GDMA.

参数:
  • dma_obj -- GDMA object defined in application software.

void dma_memcpy_init(gdma_t *dma_obj, dma_irq_handler handler, uint32_t id)

Initialize the GDMA.

参数:
  • dma_obj -- GDMA object defined in application software.

  • handler -- User-defined GDMA IRQ callback function.

  • id -- User-defined GDMA IRQ callback parameter.