Hi Daniel,
After days of bug hunting, I made some progress. The problem is not with RX but with TX.
Consider the following excerpt of code (TX section of UART IRQ handler in fsl_uart.c) :
void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle)
{
...
if ((base->S1 & UART_S1_TDRE_MASK) && (base->C2 & UART_C2_TIE_MASK))
{
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
count = FSL_FEATURE_UART_FIFO_SIZEn(base) - base->TCFIFO;
#else
count = 1;
#endif
while ((count) && (handle->txDataSize))
{
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
tempCount = MIN(handle->txDataSize, count);
#else
tempCount = 1;
#endif
UART_WriteNonBlocking(base, handle->txData, tempCount);
handle->txData += tempCount;
handle->txDataSize -= tempCount;
count -= tempCount;
if (!handle->txDataSize)
{
handle->txState = kUART_TxIdle;
base->C2 = (base->C2 & ~UART_C2_TIE_MASK);
if (handle->callback)
{
handle->callback(base, handle, kStatus_UART_TxIdle, handle->userData);
}
}
}
}
}
I have discovered that sometimes, conditions at line 6 are fulfilled while the ones at line 15 are not.
This means that the TX IRQ has been triggered but is not cleared.
Once this has happened, the IRQ handler is fired indefinitely stalling the system (higher priority IRQs are still working).
My work around is to always clear the TX IRQ (lines 14 and 48) :
void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle)
{
....
if ((base->S1 & UART_S1_TDRE_MASK) && (base->C2 & UART_C2_TIE_MASK))
{
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
count = FSL_FEATURE_UART_FIFO_SIZEn(base) - base->TCFIFO;
#else
count = 1;
#endif
if ((count) && (handle->txDataSize))
{
while ((count) && (handle->txDataSize))
{
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
tempCount = MIN(handle->txDataSize, count);
#else
tempCount = 1;
#endif
UART_WriteNonBlocking(base, handle->txData, tempCount);
handle->txData += tempCount;
handle->txDataSize -= tempCount;
count -= tempCount;
if (!handle->txDataSize)
{
handle->txState = kUART_TxIdle;
base->C2 = (base->C2 & ~UART_C2_TIE_MASK);
if (handle->callback)
{
handle->callback(base, handle, kStatus_UART_TxIdle, handle->userData);
}
}
}
}
else
{
base->C2 = (base->C2 & ~UART_C2_TIE_MASK);
}
}
}
There is the same problem for LPUART in fsl_lpuart.c.
Another fix in fsl_lpuart, line 1087 :
base->STAT |= LPUART_STAT_IDLE_MASK;
The above code clears all STAT bits, making IRQ handler remaining code relying on STAT content not functional.
My fix is the following :
base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_IDLE_MASK);
There is not the same problem with UART in fsl_uart.c
Regards,
Nicolas