This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129ENCPDT: How to receive UART bytes quickly when waking from deep sleep?

Part Number: TM4C129ENCPDT

Tool/software:

I am currently using freeRTOS on the TM4C129ENCPDT microcontroller. To save power, I am using deep sleep in the idle hook as follows:

void vApplicationIdleHook( void ) {
    SysCtlDeepSleep();
}

My UART configuration is: BAUD 57600, the UART clock is PIOSC at 16 Mhz.

SysCtlPeripheralEnable(UART0_BASE);
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
UARTConfigSetExpClk(UART0_BASE, 16000000, 57600,
    (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE |
     UART_CONFIG_WLEN_8));
UARTEnable(UART0_BASE);

IntEnable(INT_UART0);
UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

In the UART interrupt handler, I am copying bytes received into a freeRTOS queue (another task will process the queue):

void UARTIntHandler(void)
{
    // Get the interrupt status.
    uint32_t status = UARTIntStatus(UART0_BASE, true);

    // Clear the asserted interrupts.
    UARTIntClear(UART0_BASE, status);

    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    while(UARTCharsAvail(UART0_BASE)) {
        char c = UARTCharGetNonBlocking(UART0_BASE);
        // Read the next character from the UART and write it into the UART buffer
        xQueueSendFromISR(UARTBytesQueue, &c, &xHigherPriorityTaskWoken);
    }
    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}

My issue is: When I send a message longer than 16 bytes to the MCU, only the first 16 bytes are received properly. I suspect this is due to the internal UART FIFO buffer being 16 bytes, and my code takes too long to wake from deep sleep mode, thus the UART FIFO buffer fills up and subsequent bytes are lost. The problem does not occur if I use SysCtlSleep() instead of SysCtlDeepSleep().

Is there a way to increase the UART FIFO buffer size? If not, how could I work around this issue to ensure that bytes received from UART are not lost when the MCU is waking up? I would like to enter deep-sleep when the processor is idle, yet it seems like I cannot wake from deep sleep fast enough before the UART FIFO fills up.

  • My issue is: When I send a message longer than 16 bytes to the MCU, only the first 16 bytes are received properly. I suspect this is due to the internal UART FIFO buffer being 16 bytes, and my code takes too long to wake from deep sleep mode, thus the UART FIFO buffer fills up and subsequent bytes are lost. The problem does not occur if I use SysCtlSleep() instead of SysCtlDeepSleep().

    Is there a way to increase the UART FIFO buffer size? If not, how could I work around this issue to ensure that bytes received from UART are not lost when the MCU is waking up? I would like to enter deep-sleep when the processor is idle, yet it seems like I cannot wake from deep sleep fast enough before the UART FIFO fills up.

    If there is a overflow then OE bit will set in the UARTRSR register. Please confirm if this is the case. If OE flag is indeed set, then what you currently do by only entering SysCtlSleep is the best option. The hardware FIFO is only 16 entry deep. There is no other way to change. One option you can try is to change the RXIFIFOSEL to the smallest threshold at which an interrupt is generated. By configuring RXIFLSEL to 0, you will generate interrupts when 2 bytes arrive. This will give the FIFO more time to buffer subsequent data while the processor is waking up. If this still causes overflow then you need to not enter deepsleep as the wakeup time takes longer than the speed the data is coming into the FIFO. 

  • Thanks. I did confirm that the UART buffer was indeed overrun.

    Unfortunately, setting UARTIFLS to the smallest threshold seems not to resolve the issue. I will work around this issue by not entering deep-sleep when I expect to receive UART messages.

    By the way, the offset for UARTIFLS is documented as 0x0034 in the datasheet, but in the SDK I am using, the offset is 0x38 in inc/hw_types.h. I am using TivaWare_C_Series-2.2.0.295 and referring to page 1316 of www.ti.com/.../spms441b.pdf.

  • Hi Eric,

    By the way, the offset for UARTIFLS is documented as 0x0034 in the datasheet, but in the SDK I am using, the offset is 0x38 in inc/hw_types.h

    Please use the proven API to configure the RX or TX FIFO threshold level.