Receive Interrupt

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

The PC terminal programs (for example PUTTY or UartAssist) transmit data.

The SoC receives the data and triggers an interrupt. In the UART interrupt handler, the UART_INT_RD_AVA case stores the received data into a buffer and the UART_FLAG_RX_IDLE case sets received_flag to indicate that the reception is complete.

The SoC sends the buffer data back to the PC terminal once the received_flag is set.

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\rx_interrupt\proj\rtl87x2g\mdk

Project file: samples\peripheral\uart\rx_interrupt\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, observe the log information as shown in the Debug Analyzer.

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

  3. Type strings on the PC terminal and observe that the same string appears on the PC terminal. Simultaneously, observe the received data and interrupt information appearing in the Debug Analyzer.

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\rx_interrupt\proj

  • Source code directory: sdk\samples\peripheral\uart\rx_interrupt\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_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 pins as PINMUX mode, PowerOn, internal Pull-Up.

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


driver_uart_init contains the initialization of the UART peripheral.

  1. Enable PCC Clock.

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

  3. Set RX threshold level to 14 bytes.

  4. Enable UART receive data interrupt UART_INT_RD_AVA and UART receive idle interrupt UART_INT_RX_IDLE.

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_Parity         = UART_PARITY_NO_PARTY;
UART_InitStruct.UART_StopBits       = UART_STOP_BITS_1;
UART_InitStruct.UART_WordLen        = UART_WORD_LENGTH_8BIT;
UART_InitStruct.UART_RxThdLevel     = 14;
UART_InitStruct.UART_IdleTime       = UART_RX_IDLE_2BYTE;
...
UART_INTConfig(UART_DEMO, UART_INT_RD_AVA, ENABLE);
UART_INTConfig(UART_DEMO, UART_INT_RX_IDLE, ENABLE);
...

Functional Implementation

  1. Execute uart_senddata_continuous to transmit ### Uart interrupt sample ###\r\n to the PC terminal.

  2. After the PC terminal transmits the string, RX data is detected and UART_INT_RD_AVA or UART_INT_RX_IDLE interrupt is triggered.

  3. In the UART interrupt handler, UART is receiving data, triggering the UART_INT_RD_AVA interrupt and workflow should be executed as follows:

    1. Disable UART_INT_RD_AVA interrupt first.

    2. Execute UART_GetIID() to determine the interrupt identifier.

      1. When ID is UART_INT_ID_RX_LEVEL_REACH (RX FIFO level reached RX FIFO threshold which is set as UART_RxThdLevel), read data from FIFO and save data in buffer UART_Recv_Buf.

      2. When ID is UART_INT_ID_RX_DATA_TIMEOUT (There’s at least 1 UART data in the RX FIFO but no character has been input to the RX FIFO for the last time of 4 characters), read data from FIFO and save data in buffer UART_Recv_Buf.

    3. Enable UART_INT_RD_AVA interrupt.

  4. In the UART interrupt handler, UART has finished receiving data trigger UART_FLAG_RX_IDLE interrupt (If no data is put into RX FIFO within the RX idle timeout period after reading all data in the RX FIFO) and the workflow should be executed as follows:

    1. Disable UART_INT_RX_IDLE interrupt.

    2. Clear the RX FIFO.

    3. Enable UART_INT_RX_IDLE interrupt again.

    4. Set receive_flag to indicate that the reception is complete.

uint32_t int_status = UART_GetIID(UART_DEMO);
UART_INTConfig(UART_DEMO, UART_INT_RD_AVA, DISABLE);

if (UART_GetFlagStatus(UART_DEMO, UART_FLAG_RX_IDLE) == SET)
{
    UART_INTConfig(UART_DEMO, UART_INT_RX_IDLE, DISABLE);
    UART_ClearRxFIFO(UART_DEMO);
    UART_INTConfig(UART_DEMO, UART_INT_RX_IDLE, ENABLE);
    receive_flag = true;
}

switch (int_status & 0x0E)
{
case UART_INT_ID_RX_DATA_TIMEOUT:
    {
        lenth = UART_GetRxFIFODataLen(UART_DEMO);
        UART_ReceiveData(UART_DEMO, UART_Recv_Buf, lenth);
        ...
        break;
    }
...

case UART_INT_ID_RX_LEVEL_REACH:
    {
        lenth = UART_GetRxFIFODataLen(UART_DEMO);
        UART_ReceiveData(UART_DEMO, UART_Recv_Buf, lenth);
        ...
        break;
    }
...
}

UART_INTConfig(UART_DEMO, UART_INT_RD_AVA, ENABLE);
  1. The SoC sends the buffer data back to the PC terminal once the received_flag is set.

while (1)
{
    if (receive_flag == true)
    {
        receive_flag = false;
        uart_senddata_continuous(UART_DEMO, UART_Send_Buf, UART_Recv_Buf_Lenth);

        for (uint16_t i = 0; i < UART_Recv_Buf_Lenth; i++)
        {
            UART_Recv_Buf[i] = 0;
        }
        UART_Recv_Buf_Lenth = 0;
    }
}