Fixed Length Transmit and Receive - GDMA

This sample demonstrates data communication with a PC terminal using UART and GDMA.

The SoC transmits data to the PC terminal using GDMA, which transfers data from memory to the peripheral of UART TX FIFO.

The SoC receives data from the PC terminal using GDMA, which transfers data from the peripheral of UART TX FIFO to memory.

The SoC sends the buffer data back to the PC terminal once the GDMA transfer is complete.

In this sample, the PC terminal program must send data greater than or equal to UART_RX_GDMA_BUFFER_SIZE bytes to trigger the GDMA interrupt.

Users can change the pin configuration, GDMA configuration, and other information in the example through different macro configurations. For specific macro configurations, refer to Configuration.

Requirements

For requirements, please refer to the Requirements.

In addition, it is necessary to install serial port assistant tools such as PuTTY or UartAssist on the PC terminal.

Configurations

  1. The following macros can be configured to modify GDMA channel settings.

    // 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. The following macros can be configured to modify the transmission data size of the GDMA TX/RX channels.

    #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. The following macros can be configured to modify the pin definitions.

    #define UART_TX_PIN                         P3_0
    #define UART_RX_PIN                         P3_1
    

Wiring

Connect P3_0(UART TX Pin) to the RX pin of the FT232 and P3_1(UART RX Pin) to the TX pin of the FT232.

Building and Downloading

For building and downloading, please refer to the Building and Downloading.

Experimental Verification

Preparation Phase

  1. Start a PC terminal like PuTTY or UartAssist and connect to the used COM port with the following UART settings:

  • Baud rate: 115200

  • 8 data bits

  • 1 stop bit

  • No parity

  • No hardware flow control

Testing Phase

  1. After resetting the EVB, observe the log information as shown in the Debug Analyzer.

    Start uart tx rx by gdma test!
    
  2. This sample starts with transmitting ### Uart trx gdma sample\r\n. Observe that the string appears on the PC terminal.

  3. The SoC sends 29 hexadecimal numbers to the PC terminal (in this sample, the TX Block size UART_TX_GDMA_BUFFER_SIZE is set to 29): 10 11 12 … 2C. Observe that these 29 hexadecimal numbers appear on the PC terminal.

  4. Type more than 29 characters on the PC terminal (in this sample, the RX Block size UART_RX_GDMA_BUFFER_SIZE is set to 29). Observe that the same characters appear on the PC terminal.

Code Overview

This section introduces the code and process description for initialization and corresponding function implementation in the sample.

Source Code Directory

The directory for project file and source code are as follows:

  • Project directory: sdk\samples\peripheral\uart\trx_gdma\proj

  • Source code directory: sdk\samples\peripheral\uart\trx_gdma\src

Initialization

The initialization flow for peripherals can refer to Initialization Flow in General Introduction.

  1. Call Pad_Config() and Pinmux_Config() to configure the PAD and PINMUX of the corresponding pins. If UART_CONFIG_HW_FLOW_CTRL is set to 1, the CTS and RTS pins still need to be configured.

    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. Call RCC_PeriphClockCmd() to enable the UART clock.

  3. Initialize the UART peripheral:

    1. Define the UART_InitTypeDef type UART_InitStruct, and call UART_StructInit() to pre-fill UART_InitStruct with default values.

    2. Modify the UART_InitStruct parameters as needed. The UART initialization parameter configuration is shown in the table below.

    3. Call UART_Init() to initialize the UART peripheral.

UART Initialization Parameters

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. Initialize the GDMA peripheral:

    1. Define a GDMA_InitTypeDef type GDMA_InitStruct, and call GDMA_StructInit() to pre-fill GDMA_InitStruct with default values.

    2. Modify the GDMA_InitStruct parameters as needed. The initialization parameters for the GDMA TX and RX channels are configured as shown in the table below. Call GDMA_Init() to initialize the GDMA peripheral.

    3. Configure the GDMA total transfer complete interrupt GDMA_INT_Transfer and NVIC. For NVIC configurations, refer to Interrupt Configuration.

    4. Call GDMA_Cmd() to enable the corresponding GDMA channel transfer.

GDMA Initialization Parameters

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

-

Functional Implementation

  1. Call uart_senddata_continuous to transmit ### Uart trx gdma sample ###\r\n to PC terminal. Within the function uart_senddata_continuous, wait for the UART TX FIFO to be empty, and then fill the data into the FIFO in batches.

    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. After enabling the GDMA TX channel transmission, the GDMA TX channel transfers data from GDMA_SendData_Buffer to (&(UART_DEMO->UART_RBR_THR)). Once the GDMA TX data transmission is complete, it triggers the GDMA TX channel GDMA_INT_Transfer interrupt. Print the corresponding information within the interrupt handling function.

    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. After enabling the GDMA RX channel transmission, when characters are entered on the PC terminal, the GDMA RX channel transfers data from (&(UART_DEMO->UART_RBR_THR)) to GDMA_ReceiveData_Buffer. When more than 29 bytes (1 Block) are entered, it triggers the GDMA RX channel GDMA_INT_Transfer interrupt:

    1. Clear the GDMA GDMA_INT_Transfer interrupt flag.

    2. Call uart_senddata_continuous to send the data received by GDMA GDMA_ReceiveData_Buffer back to the PC terminal.

    3. Print the GDMA transfer completion information.

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);
}