GDMA
示例列表
本章介绍 GDMA 示例的详细信息。RTL87x2G 为 GDMA 外设提供以下示例。
功能概述
GDMA 用于在外设与内存之间或内存与内存之间提供高速数据传输。数据传输可以独立于 CPU 进行,以减少 CPU 的负担。
GDMA 由多个独立的通道组成,可以将数据从一个地方传输到另一个地方。传输源和目的地可以是内存或支持的外设。 一组硬件握手信号将外设与 GDMA 连接,用于控制它们之间的传输(事务)。支持 Single 传输(事务)和 Burst 传输(事务)。 传输数据宽度也是可编程的。GDMA 能够作为流控制器工作,确定 GDMA 传输的长度并终止传输。 GDMA 传输可以作为单块或多块工作。支持链表多块和自动重载多块。传输完成后,GDMA 通道将自动禁用。 传输过程可以暂停和恢复。如果不需要恢复,也支持手动中止传输过程。 GDMA 控制器有一个仲裁器来协调每个 GDMA 请求的优先级。
特性列表
通道数量:10
可编程 GDMA 通道优先级(优先级 0~9)
外设 GDMA 传输的硬件握手。
支持传输中止/暂停功能。
支持 Single 传输(事务)和 Burst 传输(事务)。
每个通道可编程源地址和目的地址。
支持单块和多块传输。
支持两种多块功能:自动重载和链表。
每个通道可编程传输类型:内存到内存、内存到外设、外设到内存、外设到外设。
可编程块大小 1 到 65535 项(每项大小=传输数据宽度)。
支持传输数据宽度:字节(8 位)、半字(16 位)、字(32 位)。
支持传输完成中断和块传输完成中断。
备注
GDMA0_channel9 为 LOG UART,HCI Mode 下 GDMA0_channel1 为 HCI UART TX,GDMA0_channel2 为 HCI UART RX。在使用中注意避免资源冲突。
传输类型
GDMA 支持 4 种传输类型:内存到内存,内存到外设,外设到内存,外设到外设。通过 GDMA_InitTypeDef::GDMA_DIR
进行设置。
在四种传输类型下,通常对源地址和目的端地址使用不同的设定。
如果源端或目的端的地址为内存,则一般会设置源端或目的端地址为自增;如果源端或目的端的地址为某外设的 FIFO,则一般会设置源端或目的端地址固定。
具体设定需要用户根据实际情况进行选择。
源端与目的端地址的变化情况可以通过 GDMA_InitTypeDef::GDMA_SourceInc
和 GDMA_InitTypeDef::GDMA_DestinationInc
进行设定。
硬件握手
GDMA 支持硬件握手,它符合协议,并在 GDMA 与源或目标外设之间进行握手,以控制在它们之间传输 Single 传输(事务)或 Burst 传输(事务)。
如果外设是 GDMA 的源端,则应设置硬件握手,源端握手通过 GDMA_InitTypeDef::GDMA_SourceHandshake
进行设置。
如果外设是 GDMA 的目标端,则应设置硬件握手,目的端握手通过 GDMA_InitTypeDef::GDMA_DestHandshake
进行设置。
GDMA 支持的硬件握手可参考 GDMA Handshake Type。
传输(事务)
传输(事务) 为 GDMA 传输的基本单元,代表每次触发 GDMA 搬运时,GDMA 搬运的数据个数。
传输(事务) 通过 GDMA_InitTypeDef::GDMA_SourceMsize
和 GDMA_InitTypeDef::GDMA_DestinationMsize
进行设置。
GDMA 传输(事务)分为如下两种:
Single 传输(事务): Single 传输的长度始终为 1,并转换为单次传输,对应
GDMA_InitTypeDef::GDMA_SourceMsize
设置为GDMA_Msize_1
。Burst 传输(事务): Burst 传输的长度被编程到 GDMA 中。
Burst 传输(事务)的设置通常与源端或目的端外设 FIFO 大小相关。通常来说,Burst Transaction Size 设置的越大,GDMA 传输效率越快。 对于部分外设,在速率比较高的情况下,不推荐使用 Single 传输(事务),例如 SPI。 由于 Single 传输(事务)的效率相对较低,有可能在 SPI TX + GDMA 的情况下导致 Tx underflow 的情况发生。
GDMA Block Transfer
GDMA 支持 Single-block 与 multi-block 传输。
Single-block: GDMA 数据长度仅由一个 block 组成。当 GDMA 传输数据完成时,会触发 GDMA 总传输完成
GDMA_INT_Transfer
中断。Multi-block: GDMA 数据长度由多个 block 组成。在前一个块结束后,会自动开始另一个新块传输。每传输完成一个 Block 时都会触发 Block 传输完成
GDMA_INT_Block
中断。
单 Block 的数据大小由 GDMA_InitTypeDef::GDMA_BufferSize
进行设定。单个 Block 的最大数据量为 65535。如果 GDMA 传输的数据总量超过 65535,则需要采用 Multi-block 的模式进行传输。
在初始化中,通过设置 GDMA_InitTypeDef::GDMA_Multi_Block_En
为 ENABLE
以开启 Multi-block 传输。
Multi-block 传输模式
Multi-block 传输支持两种模式:Linked Lists 和 Auto-reloading,可通过初始化结构体参数 GDMA_InitTypeDef::GDMA_Multi_Block_Mode
进行设置。
对于源端和目的端传输,均支持上述两种模式,因此在 Multi-block 模式下可以细分为以下七种传输模式:
Multi-block Mode |
Brief |
---|---|
Auto-Reload destination address with continuous source address |
|
Auto-Reload source address with continuous destination address |
|
Auto-Reload source address and destination address |
|
LLI destination address with continuous source address |
|
LLI destination address with auto-Reload source address |
|
LLI source address with continuous destination address |
|
LLI source address with auto-Reload destination address |
|
LLI source address and destination address |
Linked Lists
链表指针(LLP)指向系统内存中下一个链表项(LLI)所在的位置。 LLI 是一组描述下一个块(块描述符)和一个 LLP 寄存器的寄存器集。
在使用链表进行源和目的地的多块传输时,GDMA 由软件启用以开始块传输。 GDMA 获取 LLI 并根据 LLI 重新编程通道寄存器,然后 GDMA 块传输开始。 GDMA 读取源和目的地状态并将其写回到 LLI 的相应位置。 块传输完成后,GDMA 检测源和目的地的 LLP 和自动重载位是否都设置为 0,这意味着整个 GDMA 传输已完成,如果中断未屏蔽,将触发 GDMA 传输完成中断。 否则,这意味着其中一个块已完成,GDMA 将在获取另一个 LLI 后自动开始另一个块。
在 Linked List 传输模式中,每传输完一个 Block,都需要重新读取 LLI 中的 GDMA 设置到 GDMA 寄存器中,因此在初始化时需要在每个 LLI 中设置好每个 Block 的 GDMA 设置。
LLI 结构体可通过初始化结构体参数 GDMA_InitTypeDef::GDMA_Multi_Block_Struct
进行设置。
需要设置的项目有 SAR, DAR, CTL_LOW 和 CTL_HIGH 寄存器。具体配置可参考示例 Memory to Memory - Multi Block 。
Auto-reloading
在多块传输中,源和目的地的自动重载由软件启用 GDMA,启动块传输。GDMA 按照通道寄存器的配置工作。
在块传输完成后,GDMA 自动将通道寄存器重载为通道首次启用时的值。 GDMA 检测源和目的地的 LLP 和自动重载位是否全部设置为 0,这意味着整个 GDMA 传输已经完成,如果中断未被屏蔽,将触发 GDMA 传输完成中断。 否则,这意味着其中一个块已完成,另一个块将自动开始。