[FreeRTOS] UART_Interrupt Receiver not working

Dear Community,

we are trying to send AT commands via UART B. In order to do so, we used the uart_interrupt example provided by Toradex (using DS-5) on FreeRTOS.

Even though we can send the AT commands to our module, when it comes to the Receiver of the UART, we are unable to get into the Rx Interrupt and get the response from it.

In order to figure out the issue, we tried to adapt the polling example as well, but again… no luck! We still couldn’t get the response from the module.

The only changes we made were to use the command AT\r instead of the sample text provided by Toradex in the example.

Do you have any insight? What would you recommend us to do?

Regards.

hi @dimikara

Welcome to the Toradex Community!

Even though we can send the AT commands to our module, when it comes to the Receiver of the UART, we are unable to get into the Rx Interrupt and get the response from it.

So this means you can send commands from iMX7 to your module but not receive anything. Could you check with an oscilloscope, if you are receiving any signals on the Rx Line. Is UART_B working on Linux?

Which Uart_interrupt example are you using exactly? Can you share all your changes you have done to the code?

Best regards, Jaski

hi @jaski.tx

Thank you for the welcome.

Could you check with an oscilloscope, if you are receiving any signals on the Rx Line. Is >UART_B working on Linux?
I know that the signal arrives on the Rx Line since I have an application already working on Linux with A7 but I need to move it to the Cortex-M4.
Which Uart_interrupt example are you using exactly?
The one you provide with freeRTOS called uart_interrupt.

Can you share all your changes you have done to the code?

#include <stdint.h>
#include <stdbool.h>
#include "uart_imx.h"
#include "board.h"

typedef struct _uart_state {
    const uint8_t*    txBuff;          /*!< The buffer of data being sent.*/
    uint8_t*          rxBuff;          /*!< The buffer of received data. */
    volatile uint32_t txSize;          /*!< The remaining number of bytes to be transmitted. */
    volatile uint32_t rxSize;          /*!< The remaining number of bytes to be received. */
    volatile bool     isTxBusy;        /*!< True if there is an active transmit. */
    volatile bool     isRxBusy;        /*!< True if there is an active receive. */
} uart_state_t;

const uint8_t buffStart[] = "AT\r";
const uint8_t bufferData[] = "AT+UBTLE=1\r";

/* Uart runtime state structure */
static uart_state_t uartState;

static void UART_XFER_Config(uart_init_config_t* initConfig);
static bool UART_XFER_Write(uint8_t* txBuffer, uint32_t length);
static uint32_t UART_XFER_GetWriteStatus(void);
static bool UART_XFER_Read(uint8_t* rxBuffer, uint32_t length);
static uint32_t UART_XFER_GetReadStatus(void);

int main(void)
{
    // Setup UART init structure.
    uart_init_config_t initConfig = {
        .baudRate   = 115200u,
        .wordLength = uartWordLength8Bits,
        .stopBitNum = uartStopBitNumOne,
        .parity     = uartParityDisable,
        .direction  = uartDirectionTxRx
    };
    uint8_t rxChar, txChar;

    // Initialize board specified hardware.
    hardware_init();

    // Get current module clock frequency.
    initConfig.clockRate  = get_uart_clock_freq(BOARD_DEBUG_UART_BASEADDR);

    // Initialize the uart module with initialize structure.
    UART_XFER_Config(&initConfig);

    // Inform to start non blocking example.
    UART_XFER_Write((uint8_t*)buffStart, 3);
    // Wait until transmission is finished.
    while (UART_XFER_GetWriteStatus());

    // Call received API
   UART_XFER_Read(&rxChar, 1u);
   // Wait until we receive a character
   while (UART_XFER_GetReadStatus());

   UART_XFER_Write(&rxChar, 1u);


    // Inform user of what to do
    UART_XFER_Write((uint8_t*)bufferData, 11);
    // Wait until transmission is finished.
    while (UART_XFER_GetWriteStatus());

}

static void UART_XFER_Config(uart_init_config_t* initConfig)
{
    /* Assert */

    /* Initialize UART state structure content. */
    uartState.txBuff = 0;
    uartState.rxBuff = 0;
    uartState.txSize = 0;
    uartState.rxSize = 0;
    uartState.isTxBusy = false;
    uartState.isRxBusy = false;

    /* Initialize UART baud rate, bit count, parity, stop bit and direction. */
    UART_Init(BOARD_DEBUG_UART_BASEADDR, initConfig);

    UART_SetTxFifoWatermark(BOARD_DEBUG_UART_BASEADDR, 16);
    UART_SetRxFifoWatermark(BOARD_DEBUG_UART_BASEADDR, 1);

    /* Set UART Interrupt priority */
    NVIC_SetPriority(BOARD_DEBUG_UART_IRQ_NUM, 3);

    /* Call core API to enable the IRQ. */
    NVIC_EnableIRQ(BOARD_DEBUG_UART_IRQ_NUM);

    /* Finally, enable the UART module */
    UART_Enable(BOARD_DEBUG_UART_BASEADDR);
}

static bool UART_XFER_Write(uint8_t* txBuffer, uint32_t length)
{
    if ((uartState.isTxBusy) || (0 == length))
        return false;

    uartState.txBuff = txBuffer;
    uartState.txSize = length;
    uartState.isTxBusy = true;

    UART_SetIntCmd(BOARD_DEBUG_UART_BASEADDR, uartIntTxReady, true);
    return true;
}

static uint32_t UART_XFER_GetWriteStatus(void)
{
    return uartState.txSize;
}

static bool UART_XFER_Read(uint8_t* rxBuffer, uint32_t length)
{
    if ((uartState.isRxBusy) || (0 == length))
        return false;
    uartState.rxBuff = rxBuffer;
    uartState.rxSize = length;
    uartState.isRxBusy = true;

    UART_SetIntCmd(BOARD_DEBUG_UART_BASEADDR, uartIntRxReady, true);
    return true;
}

static uint32_t UART_XFER_GetReadStatus(void)
{
    return uartState.rxSize;
}

void BOARD_DEBUG_UART_HANDLER(void)
{
    /* Exit the ISR if no transfer is happening for this instance. */
    if ((!uartState.isTxBusy) && (!uartState.isRxBusy))
        return;

    if (UART_GetStatusFlag(BOARD_DEBUG_UART_BASEADDR, uartStatusRxReady))
    {
        /* Check to see if there are any more bytes to receive. */
        if (uartState.rxSize)
        {
            while (UART_GetStatusFlag(BOARD_DEBUG_UART_BASEADDR, uartStatusRxReady))
            {
                *(uartState.rxBuff) = (uint8_t)UART_Getchar(BOARD_DEBUG_UART_BASEADDR);
                uartState.rxBuff++;
                uartState.rxSize--;
                if (uartState.rxSize == 0U)
                {
                    UART_SetIntCmd(BOARD_DEBUG_UART_BASEADDR, uartIntRxReady, false);

                    uartState.isRxBusy = false;
                    break;
                }
            }
        }
    }

    if (UART_GetStatusFlag(BOARD_DEBUG_UART_BASEADDR, uartStatusTxReady))
    {
        /* Check to see if there are any more bytes to send. */
        if (uartState.txSize)
        {
            while (UART_GetStatusFlag(BOARD_DEBUG_UART_BASEADDR, uartStatusTxReady))
            {
                /* Transmit data and update tx size/buff */
                UART_Putchar(BOARD_DEBUG_UART_BASEADDR, *(uartState.txBuff));
                uartState.txBuff++;
                uartState.txSize--;
                if (uartState.txSize == 0U)
                {
                    /* Transmit complete */
                    /* Disable the transmitter ready interrupt */
                    UART_SetIntCmd(BOARD_DEBUG_UART_BASEADDR, uartIntTxReady, false);

                    /* Update the information of the module driver state */
                    uartState.isTxBusy = false;
                    break;
                }
            }
        }
    }
}

/*******************************************************************************
 * EOF
 ******************************************************************************/

We are simply trying to send the command and get the “OK” reply. We have made different tests in order to get the reply and put it in a buffer but it’s better to get the basic idea behind it and then build our program around this fix.

Regards

hi @dimikara

Sorry for delay for answering. I will work today on this Issue and let you know the results.
Best regards, Jaski

Dear @dimikara

I was able to find the issue: In both UART examples, an important call to UART_SetModemMode() is missing, which sets up the Rx/Tx signals correctly. The two examples are structured slightly different, therefore the additional line best fits into different locations:

In the UART Interrupt example (uart_imx_interrupt_example_imx7_colibri_m4):
.\imx7_colibri_m4\driver_examples\uart_imx\uart_interrupt\main.c, function UART_XFER_Config()

/* Initialize UART baud rate, bit count, parity, stop bit and direction. */
UART_Init(BOARD_DEBUG_UART_BASEADDR, initConfig);
UART_SetModemMode(BOARD_DEBUG_UART_BASEADDR, uartModemModeDte);

UART_SetTxFifoWatermark(BOARD_DEBUG_UART_BASEADDR, 16);
UART_SetRxFifoWatermark(BOARD_DEBUG_UART_BASEADDR, 1);

In the UART Polling example (uart_imx_polling_example_imx7_colibri_m4):
.\imx7_colibri_m4\driver_examples\uart_imx\uart_polling\main.c, function main()

/* Initialize UART baud rate, bit count, parity, stop bit and direction. */
UART_Init(BOARD_DEBUG_UART_BASEADDR, &initConfig);
UART_SetModemMode(BOARD_DEBUG_UART_BASEADDR, uartModemModeDte);

/* Set UART build-in hardware FIFO Watermark. */
UART_SetTxFifoWatermark(BOARD_DEBUG_UART_BASEADDR, 16);

I will update the git repository accordingly.

Regards, Andy

Dear @andy.tx

from a first look, we can’t see any difference, we will work upon this later on and I will get back to you with our results.

Thank you for your help.
Regards

Dear @dimikara

I successfully tested this change on my desk.
One first test you can do is to physically verify the pin direction of the Rx/Tx signals: With the external device disconnnected, you should be able to pull the Rx signal high and low through a (10kΩ) resistor, while the Tx signal is expected to stay high.
By the way: the git repository is meanwhile updated with the fix.

Regards, Andy