Fixed Length Transmit and Receive - DMA

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

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

The SoC receives data from the PC terminal using DMA, 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 DMA transfer is complete.

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

Requirements

The sample supports the following development kits:

Development Kits

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

For more requirements, please refer to Quick Start.

Wiring

Connect P3_0 to the RX pin of the FT232 and P3_1 to the TX pin of the FT232.

Building and Downloading

This sample can be found in the SDK folder:

Project file: samples\peripheral\uart\trx_gdma\proj\rtl87x2g\mdk

Project file: samples\peripheral\uart\trx_gdma\proj\rtl87x2g\gcc

To build and run the sample, follow the steps listed below:

  1. Open sample project file.

  2. To build the target, follow the steps listed on the Generating App Image in Quick Start.

  3. After a successful compilation, the app bin app_MP_xxx.bin will be generated in the directory mdk\bin or gcc\bin.

  4. To download app bin into EVB board, follow the steps listed on the MP Tool Download in Quick Start.

  5. Press reset button on EVB board and it will start running.

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 to 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 chapter will be introduced according to the following several parts:

  1. Source Code Directory.

  2. Peripheral initialization will be introduced in chapter Initialization .

  3. Functional implementation after initialization will be introduced in chapter Functional Implementation .

Source Code Directory

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

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

Source files are currently categorized into several groups as below.

└── Project: output_toggle
    └── secure_only_app
        └── Device                   includes startup code
            ├── startup_rtl.c
            └── system_rtl.c
        ├── CMSIS                    includes CMSIS header files
        ├── CMSE Library             Non-secure callable lib
        ├── lib                      includes all binary symbol files that user application is built on
            └── rtl87x2g_io.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl_gdma.c
            ├── rtl_nvic.c
            ├── rtl_pinmux.c
            ├── rtl_rcc.c
            └── rtl_uart.c
        └── APP                      includes the ble_peripheral user application implementation
            ├── io_uart.c
            └── main_ns.c

Initialization

The initialization process includes board_uart_init and driver_uart_init .


board_uart_init contains the PAD and PINMUX settings:

  1. Config PAD: Set the pin to PINMUX mode, PowerOn, internal Pull-Up.

  2. Config PINMUX: Assign pins for UART3_TX and UART3_RX functions respectively.


driver_uart_init contains the initialization of the UART peripheral.

  1. Enable PCC Clock.

  2. Set the baud rate to 115200, no parity, 1-bit stop bit, 8-bit data length.

  3. Enable UART DMA transmission.

  4. Set UART_TxWaterLevel to 1, recommended setting is GDMA_MSize.

  5. Set UART_RxWaterLevel to 1, recommended setting is GDMA_MSize.

  6. Enable UART TX DMA, RX DMA.

RCC_PeriphClockCmd(APBPeriph_UART3, APBPeriph_UART3_CLOCK, ENABLE);
...
UART_InitStruct.UART_Div            = BaudRate_Table[BAUD_RATE_115200].div;
UART_InitStruct.UART_Ovsr           = BaudRate_Table[BAUD_RATE_115200].ovsr;
UART_InitStruct.UART_OvsrAdj        = BaudRate_Table[BAUD_RATE_115200].ovsr_adj;
...
UART_InitStruct.UART_DmaEn          = UART_DMA_ENABLE;
UART_InitStruct.UART_TxWaterLevel   = 1; /* Better to equal: GDMA_MSize */
UART_InitStruct.UART_RxWaterLevel   = 1; /* Better to equal: GDMA_MSize */
UART_InitStruct.UART_TxDmaEn        = ENABLE;
UART_InitStruct.UART_RxDmaEn        = ENABLE;
...

Execute UART_SendDataByGDMA to initialize the GDMA to send data.

  1. Use GDMA channel 3.

  2. The GDMA transfer direction is memory to peripheral.

  3. The source address is set to GDMA_SendData_Buffer and the destination address is set to (&(UART_DEMO->UART_RBR_THR)).

  4. Enable the GDMA channel 3 total transfer completion interrupt GDMA_INT_Transfer.

  5. Enable GDMA channel 3 transfer.

GDMA_InitStruct.GDMA_ChannelNum       = UART_TX_GDMA_CHANNEL_NUM;
GDMA_InitStruct.GDMA_DIR              = GDMA_DIR_MemoryToPeripheral;
...
GDMA_InitStruct.GDMA_SourceAddr       = (uint32_t)GDMA_SendData_Buffer;
GDMA_InitStruct.GDMA_DestinationAddr  = (uint32_t)(&(UART_DEMO->UART_RBR_THR));
...
GDMA_INTConfig(UART_TX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer, ENABLE);
...
GDMA_Cmd(UART_TX_GDMA_CHANNEL_NUM, ENABLE);

Execute UART_ReceiveDataByGDMA to initialize the GDMA to receive data.

  1. Use GDMA channel 4.

  2. The GDMA transfer direction is peripheral to memory.

  3. The source address is set to (&(UART_DEMO->RB_THR)) and the destination address is set to GDMA_ReceiveData_Buffer.

  4. Enable the GDMA channel 4 total transfer completion interrupt GDMA_INT_Transfer.

  5. Enable GDMA channel 4 transfer.

GDMA_InitStruct.GDMA_ChannelNum       = UART_RX_GDMA_CHANNEL_NUM;
GDMA_InitStruct.GDMA_DIR              = GDMA_DIR_PeripheralToMemory;
...
GDMA_InitStruct.GDMA_SourceAddr       = (uint32_t)(&(UART_DEMO->UART_RBR_THR));
GDMA_InitStruct.GDMA_DestinationAddr  = (uint32_t)GDMA_ReceiveData_Buffer;
...
GDMA_INTConfig(UART_RX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer, ENABLE);
...
GDMA_Cmd(UART_RX_GDMA_CHANNEL_NUM, ENABLE);

Functional Implementation

  1. Execute uart_senddata_continuous to transmit ### Uart trx gdma sample ###\r\n to PC terminal.

  2. Executing GDMA_Cmd() initiates the GDMA transfer from memory to UART TX FIFO. Once the GDMA transfer is complete, it triggers the GDMA_INT_Transfer interrupt and enters the interrupt handler function UART_TX_GDMA_Handler.

    1. Clear the GDMA channel 3 GDMA_INT_Transfer interrupt flag bit.

    2. Print the GDMA Handler transmit data completed information.

GDMA_ClearINTPendingBit(UART_TX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer);

DBG_DIRECT("UART_TX_GDMA_Handler, Data transmission completion!");
  1. Typing characters on the PC terminal initiates the GDMA transfer from the UART RX FIFO to memory. When the input exceeds 29 characters (1 Block), it triggers the GDMA_INT_Transfer interrupt and enters the interrupt handler function UART_RX_GDMA_Handler.

    1. Clear the GDMA channel 1 GDMA_INT_Transfer interrupt flag bit.

    2. Execute uart_senddata_continuous to send the data back to the PC terminal.

    3. Print the GDMA transport received data completion information.

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