I am using S32K144 UART peripheral. RXD interrupt and TXD interrupt vector are the same one, so in interrupt handler, we have to check whether due to Rx or Tx that the ISR function is called.
My question 1 is : If ISR is entered due to Tx, at the same time, a Rx byte is shift to data register finished. whether the received byte will be affected?
My ISR function just like below:
void UARTSrv_isr(void)
{
uint8_t lub_temp;
/* For reception interrupt. */
if(LPUART1->CTRL & 0X200000)
{
if(LPUART1->STAT & 0X200000)
{
lub_temp = (uint8_t)LPUART1->DATA;
testTotalReceived += 1;
UARTSrv_Rx_isr(lub_temp);
}
}
/* For transmission interrupt. */
if(LPUART1->CTRL & 0X800000)
{
if(LPUART1->STAT & 0X800000)
{
if(lpuart1_State.txSize > 0)
{
LPUART1->DATA = *lpuart1_State.txBuff;
++lpuart1_State.txBuff;
--lpuart1_State.txSize;
}
else
{
/* Disable transmission complete interrupt */
LPUART_SetIntMode(LPUART1, LPUART_INT_TX_DATA_REG_EMPTY, false);
/* Update the information of the module driver state */
lpuart1_State.isTxBusy = false;
lpuart1_State.transmitStatus = STATUS_SUCCESS;
}
}
}
/* For overruninterrupt. */
if (LPUART1->STAT & 0X80000)
{
lpuart1_State.receiveStatus = STATUS_UART_RX_OVERRUN;
/* Clear the flag, OR the rxDataRegFull will not be set any more */
LPUART1->STAT |= 0X80000;
}
}
User defined function "UARTSrv_Rx_isr" definition as below:
PRIVATE_FCT void UARTSrv_Rx_isr(uint8_t ch)
{
pUART_rx_data_t pRx = &rs_rxData;
if(FALSE == pRx->bufFull)
{
pRx->buf[pRx->inIndex] = ch;
pRx->bufEmpty = FALSE;
pRx->recBytes += 1u;
pRx->inIndex += 1u;
if(UART_RX_DATA_BUF_LEN <= pRx->inIndex)
{
pRx->inIndex = 0u;
}
if(pRx->inIndex == pRx->outIndex)
{
pRx->bufFull = TRUE;
}
}
}
But when I check my received data, I found that received bytes lost frequently.
My question 2 is: whether my ISR has problem? or my issue is due to other possible reasons?
Thank you~~
Additionally: I check the UART receive overrun interrupt, it was entered frequently. How to avoid enter the overrun interrupt or how to process it?
Hi Xiaoyu,
For checking which one interrupt occur RX or TX, I checked the data buffers like below. Then I jumped into the proper interrupt routine.
void LPUART1_RxTx_IRQHandler(void)
{
if((LPUART1->STAT & LPUART_STAT_RDRF_MASK)>>LPUART_STAT_RDRF_SHIFT) // Checked Receive data buffer
RxISR();
if((LPUART1->STAT & LPUART_STAT_TDRE_MASK)>>LPUART_STAT_TDRE_SHIFT) // Checked Transmit data buffer
TxISR();
}
When overrun occurs and OR flag is set, no additional data is stored in the data buffer.
It happens when Rx buffer is not empty (not read) and further data are received. That’s why the data are lost.
There are some possibilities which can help you:
- Decrease the BaudRate value
- Set the higher priority of LPUART interrupt
- Choose the fastest clock source for the LPUART
- You can consider the use of FIFO register see 51.3.1.12 LPUART FIFO Register (FIFO) in the reference manual.
I hope it helps you.
Best regards,
Diana
Hi,
Have you tried FIFO for UART. If yes please let me know how you configured.
Thanks..!
Harish
@harish_g2 Did you manage to make the communication using FIFO?
Dear Diana,
I have a question.
When I deal with receive by UART in debug mode using break point, STATUS_UART_RX_OVERRUN occurred.
It was ok.
however, I want to know how to clear Error when STATUS_UART_RX_OVERRUN was occurred.
Do I deal with as below?
/* For overruninterrupt. */
if (LPUART1->STAT & 0X80000)
{
lpuart1_State.receiveStatus = STATUS_UART_RX_OVERRUN;
/* Clear the flag, OR the rxDataRegFull will not be set any more */
LPUART1->STAT |= 0X80000;
}
Thanks.
Hello,
Yes, at first, check if the Receiver Overrun Flag is set and if yes, clear the flag.
Best Regards,
Diana
Hello Diana Batrlova,
I have tried to set the priority of used LPUART to highest level of all interrupts I am using. It works!
Next step, I will try to improve my SW use FIFO.
Thank you for your solution~~
hello Diana Batrlova,
I have tried to set the priority of LPUART I used to