Fixed Length Transmit and Receive - GDMA

该示例使用 UARTGDMA 与 PC 终端进行固定长度的数据通信。

SoC 使用 GDMA 将数据发送到 PC 终端程序(如 PuTTY 或 UartAssist),GDMA 将数据从 Memory 传输到 UART TX FIFO 外设。

SoC 使用 GDMA 接收 PC 终端输入的数据,GDMA 将数据从 UART RX FIFO 外设传输到 Memory。

一旦 GDMA 传输完成,SoC 将缓冲数据发送回 PC 终端。

在该示例中,PC 终端程序必须发送大于等于 UART_RX_GDMA_BUFFER_SIZE 个字节的数据,才会触发 GDMA 中断。

用户可以通过不同的宏配置改变示例中的引脚配置,GDMA 配置等信息,具体宏配置详见 配置选项

环境需求

该示例的环境需求,可参考 环境需求

此外,需要在 PC 终端安装 PuTTY 或 UartAssist 等串口助手工具。

配置选项

  1. 可配置如下宏修改 GDMA 通道设置。

    // Set the following macros to modify the UART TX GDMA Channel configurations.
    #define UART_TX_GDMA_CHANNEL_NUM            GDMA_CH_NUM3
    #define UART_TX_GDMA_CHANNEL                GDMA_Channel3
    #define UART_TX_GDMA_CHANNEL_IRQN           GDMA_Channel3_IRQn
    #define UART_TX_GDMA_Handler                GDMA_Channel3_Handler
    
    // Set the following macros to modify the UART RX GDMA Channel configurations.
    #define UART_RX_GDMA_CHANNEL_NUM            GDMA_CH_NUM4
    #define UART_RX_GDMA_CHANNEL                GDMA_Channel4
    #define UART_RX_GDMA_CHANNEL_IRQN           GDMA_Channel4_IRQn
    #define UART_RX_GDMA_Handler                GDMA_Channel4_Handler
    
  2. 可配置如下宏修改 GDMA TX/RX 通道的传输数据量。

    #define UART_TX_GDMA_BUFFER_SIZE            29              /*< Set this macro to modify the UART TX GDMA transfer size. */
    #define UART_RX_GDMA_BUFFER_SIZE            29              /*< Set this macro to modify the UART RX GDMA transfer size. */
    
  3. 可配置如下宏修改引脚定义。

    #define UART_TX_PIN                         P3_0
    #define UART_RX_PIN                         P3_1
    

硬件连线

连接 P3_0(UART TX Pin)和 FT232 的 RX,P3_1(UART RX Pin) 和 FT232 的 TX。

编译和下载

该示例的编译和下载流程,可参考 编译和下载

测试验证

准备阶段

  1. 启动 PuTTY 或 UartAssist 等 PC 终端,连接到使用的 COM 端口,并进行以下 UART 设置:

  • 波特率: 115200

  • 8 数据位

  • 1 停止位

  • 无校验

  • 无硬件流控

测试阶段

  1. 当 EVB 启动后,在 Debug Analyzer 工具内观察如下 log。

    Start uart tx rx by gdma test!
    
  2. 该示例开始发送 ### Uart trx gdma sample\r\n ,观察 PC 终端上出现的字符串。

  3. SoC 向 PC 终端发送 29 个十六进制数(该示例 TX Block size UART_TX_GDMA_BUFFER_SIZE 设置为 29):10 11 12 … 2C, 观察 PC 终端上显示这 29 个十六进制数。

  4. 在 PC 终端上输入超过 29 个字符(该示例 RX Block size UART_RX_GDMA_BUFFER_SIZE 设置为 29)。观察 PC 终端上是否显示相同的字符。

代码介绍

该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明。

源码路径

工程文件和源码路径如下:

  • 工程路径: sdk\samples\peripheral\uart\trx_gdma\proj

  • 源码路径: sdk\samples\peripheral\uart\trx_gdma\src

初始化

外设的初始化流程可参考 General Introduction 中的 初始化流程 部分。

  1. 调用 Pad_Config()Pinmux_Config(),配置对应引脚的 PAD 和 PINMUX。

    void board_uart_init(void)
    {
        Pad_Config(UART_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
        Pad_Config(UART_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
    
        Pinmux_Config(UART_TX_PIN, UART3_TX);
        Pinmux_Config(UART_RX_PIN, UART3_RX);
    }
    
  2. 调用 RCC_PeriphClockCmd() ,开启 UART 时钟。

  3. 对 UART 外设进行初始化:

    1. 定义 UART_InitTypeDef 类型 UART_InitStruct ,调用 UART_StructInit()UART_InitStruct 预填默认值。

    2. 根据需求修改 UART_InitStruct 参数,UART 的初始化参数配置如下表。

    3. 调用 UART_Init(),初始化 UART 外设。

UART 初始化参数

UART Hardware Parameters

Setting in the UART_InitStruct

UART

UART Baudrate Parameter - div

UART_InitTypeDef::UART_Div

BaudRate_Table[BAUD_RATE_115200].div

UART Baudrate Parameter - ovsr

UART_InitTypeDef::UART_Ovsr

BaudRate_Table[BAUD_RATE_115200].ovsr

UART Baudrate Parameter - ovsr_adj

UART_InitTypeDef::UART_OvsrAdj

BaudRate_Table[BAUD_RATE_115200].ovsr_adj

GDMA Enable

UART_InitTypeDef::UART_DmaEn

ENABLE

TX GDMA Enable

UART_InitTypeDef::UART_TxDmaEn

ENABLE

RX GDMA Enable

UART_InitTypeDef::UART_RxDmaEn

ENABLE

TX Waterlevel

UART_InitTypeDef::UART_TxWaterLevel

1

RX Waterlevel

UART_InitTypeDef::UART_RxWaterLevel

1

  1. 对 GDMA 外设进行初始化:

    1. 定义 GDMA_InitTypeDef 类型 GDMA_InitStruct ,调用 GDMA_StructInit()GDMA_InitStruct 预填默认值。

    2. 根据需求修改 GDMA_InitStruct 参数。GDMA TX 和 RX 通道的初始化参数配置如下表。调用 GDMA_Init(),初始化 GDMA 外设。

    3. 配置 GDMA 总传输完成中断 GDMA_INT_Transfer 和 NVIC,NVIC 相关配置可参考 中断配置

    4. 调用 GDMA_Cmd() 使能对应 GDMA 通道传输。

GDMA 初始化参数

GDMA Hardware Parameters

Setting in the GDMA_InitStruct

GDMA TX Channel

GDMA RX Channel

Channel Num

GDMA_InitTypeDef::GDMA_ChannelNum

3

4

Transfer Direction

GDMA_InitTypeDef::GDMA_DIR

GDMA_DIR_MemoryToPeripheral

GDMA_DIR_PeripheralToMemory

Buffer Size

GDMA_InitTypeDef::GDMA_BufferSize

UART_TX_GDMA_BUFFER_SIZE

UART_RX_GDMA_BUFFER_SIZE

Source Address Increment or Decrement

GDMA_InitTypeDef::GDMA_SourceInc

DMA_SourceInc_Inc

DMA_SourceInc_Fix

Destination Address Increment or Decrement

GDMA_InitTypeDef::GDMA_DestinationInc

DMA_DestinationInc_Fix

DMA_DestinationInc_Inc

Source Data Size

GDMA_InitTypeDef::GDMA_SourceDataSize

GDMA_DataSize_Byte

GDMA_DataSize_Byte

Destination Data Size

GDMA_InitTypeDef::GDMA_DestinationDataSize

GDMA_DataSize_Byte

GDMA_DataSize_Byte

Source Burst Transaction Length

GDMA_InitTypeDef::GDMA_SourceMsize

GDMA_Msize_1

GDMA_Msize_1

Destination Burst Transaction Length

GDMA_InitTypeDef::GDMA_DestinationMsize

GDMA_Msize_1

GDMA_Msize_1

Source Address

GDMA_InitTypeDef::GDMA_SourceAddr

GDMA_SendData_Buffer

(&(UART_DEMO->UART_RBR_THR))

Destination Address

GDMA_InitTypeDef::GDMA_DestinationAddr

(&(UART_DEMO->UART_RBR_THR))

GDMA_ReceiveData_Buffer

Source Handshake

GDMA_InitTypeDef::GDMA_SourceHandshake

-

GDMA_Handshake_UART3_RX

Destination Handshake

GDMA_InitTypeDef::GDMA_DestHandshake

GDMA_Handshake_UART3_TX

-

功能实现

  1. 执行 uart_senddata_continuous ,发送 ### Uart trx gdma sample ###\r\n 到 PC 终端。在函数 uart_senddata_continuous 内,等待 UART TX FIFO 为空时,分批将数据填入 FIFO 中。

    void uart_senddata_continuous(UART_TypeDef *UARTx, const uint8_t *pSend_Buf, uint16_t vCount)
    {
        uint8_t count;
        while (vCount / UART_TX_FIFO_SIZE > 0)
        {
            while (UART_GetFlagStatus(UARTx, UART_FLAG_TX_FIFO_EMPTY) == 0);
            for (count = UART_TX_FIFO_SIZE; count > 0; count--)
            {
                UARTx->UART_RBR_THR = *pSend_Buf++;
            }
            vCount -= UART_TX_FIFO_SIZE;
        }
    
        while (UART_GetFlagStatus(UARTx, UART_FLAG_TX_FIFO_EMPTY) == 0);
        while (vCount--)
        {
            UARTx->UART_RBR_THR = *pSend_Buf++;
        }
    }
    
  2. 使能 GDMA TX 通道传输后,GDMA TX 通道将数据从 GDMA_SendData_Buffer 搬到 (&(UART_DEMO->UART_RBR_THR)) 。当 GDMA TX 数据传输完成后,触发 GDMA TX 通道 GDMA_INT_Transfer 中断。在中断处理函数内打印相应信息。

    void UART_TX_GDMA_Handler(void)
    {
        GDMA_ClearINTPendingBit(UART_TX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer);
        DBG_DIRECT("UART_TX_GDMA_Handler, Data transmission completion!");
    }
    
  3. 使能 GDMA RX 通道传输后,当在 PC 终端输入字符时,GDMA RX 通道将数据从 (&(UART_DEMO->UART_RBR_THR)) 搬到 GDMA_ReceiveData_Buffer 。当输入字符超过 29 个字节(1 Block)时,触发 GDMA RX 通道 GDMA_INT_Transfer 中断:

    1. 清除 GDMA GDMA_INT_Transfer 中断标志位。

    2. 执行 uart_senddata_continuous ,将 GDMA 收到的数据 GDMA_ReceiveData_Buffer 发回 PC 终端。

    3. 打印 GDMA 传输完成信息。

void UART_RX_GDMA_Handler(void)
{
    GDMA_ClearINTPendingBit(UART_RX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer);
    DBG_DIRECT("UART_RX_GDMA_Handler, Data transmission completion!");
    uart_senddata_continuous(UART_DEMO, GDMA_ReceiveData_Buffer, UART_RX_GDMA_BUFFER_SIZE);
}