Hello,
I have a KL82 which I attached a modem to it. It communicates via UART.
If the bus is busy (message every second) everything works fine. But if there is rarely any activity (about once a minute) the interrupt for UART RX does not fire when the modem sends data.
This is resolved by reinitializing the UART.
Do you know why this occurs or how I can debug more deeply? Thanks a lot in advance.
Here is my ISR code for reference
void MODEM_LPUART_IRQHandler(void)
{
#ifdef TRACE_SYSVIEW_LPUART_CALLBACK
SEGGER_SYSVIEW_RecordEnterISR();
#endif
interfaceModem_hasWoken = pdFALSE;
/** if new data is in buffer */
if ((kLPUART_RxDataRegFullFlag)&LPUART_GetStatusFlags(MODEM_LPUART))
{
TPM_StopTimer(TPM0); /** stop timer for timeout detection */
interfaceModem_data = LPUART_ReadByte(MODEM_LPUART); /** read data from buffer */
if (uxQueueMessagesWaitingFromISR(InterfaceModem::rxQueue)<INTERFACE_MODEM_RX_QUEUE_SIZE-3)
{ /** Submit to queue */
xQueueSendFromISR(InterfaceModem::rxQueue,&interfaceModem_data,&interfaceModem_hasWoken);
if (interfaceModem_data=='\n')
{ /** if this char is a line ending, activate the timer. Every Message of SIM808 ends with */
TPM_SetTimerPeriod(TPM0,TIMER_MESSAGETIMEOUT_RELOAD_VALUE);
TPM_StartTimer(TPM0,kTPM_SystemClock);
TPM0->CNT=0;
}
}
else
{ /** If data could not be submitted, set overflow occured, clear queues and stop timeout timer */
InterfaceModem::rxOverflowOccured=1;
TPM_StopTimer(TPM0);
xQueueReceiveFromISR(InterfaceModem::rxMessageTimeoutSignalQueue,&interfaceModem_data,&interfaceModem_hasWoken);
while (xQueueReceiveFromISR(InterfaceModem::rxQueue,&interfaceModem_data,&interfaceModem_hasWoken)==pdTRUE);
InterfaceModem::rxOverflowOccured=1;
}
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
#ifdef TRACE_SYSVIEW_LPUART_CALLBACK
SEGGER_SYSVIEW_RecordExitISR();
#endif
portYIELD_FROM_ISR(interfaceModem_hasWoken);
}
Hi mldevw,
Could it because the lpuart is deactived by your OS, for example the clock source is changed? If lpuart is configured properly, waiting time does not affect lpuart's work.
Regards,
Jing
Hello,
I am only doing one clock switch right at the start of the application. When the modem is running, no clock switch is taking place.
I am using FreeRTOS, I don't know if this could be the issue.
Strangely this occurs only when communication is rare. Once I keep the channel busy, I do not experience the problem anymore.
Edit: I am using the LPUART_Driver from the MCUXpresso SDK, not the FreeRTOS Driver.
I make sure that only one process is accessing the UART at a time.
Hi,
You can compare LPUART register settings and its clock source setting to see what is changed when it not work.
Regards,
Jing
Hello,
so I could reproduce the error and have the following finding:
EDIT2:
I made a mistake reading out, actually the STAT-Register changed
It changed from 00 80 00 00 to 00 D8 00 00 (error)
This means:
OR from 0 to 1
IDLE from 0 to 1
TC from 0 to 1
In the other error case (00 D0 00 00):
OR = 0
IDLE = 1
TC = 1
I have seen there is an overrun and I will concentrate on getting rid of that for now.
I'll get back to you if that solves the problem
LPUART->MODIR has changed from 00 D8 00 00 to 00 80 00 00(Value was printed out with printf("%" PRIu32,LPUART->MODIR); and then converted to hex)
EDIT: Now I have also seen a case where MODIR is 00 D0 00 00 both before the error and when it occured
For my Init I use the defaults, but change the baudrate and enable tx and rx.
LPUART_GetDefaultConfig(&config);config.baudRate_Bps = currentBaudrate;config.enableTx = true;config.enableRx = true;
Reading the datasheet (see below) it's not clear to me what this means.Also I did not find any use of MODIR in the lpuart driver from the SDK but for initialisation.
Can you please help me on finding outa) what the flags in the MODIR mean, which are changedb) why MODIR changes
Thanks a lot in advance.
Sub-Family Reference Manual Rev. 3, 08/2016, p. 1493
Hello,
the overrun issue occurs although I am sure my ISR reads the byte in time.
The ringbuffer is not an option for me, as I need to use the RxBufFull Interrupt for timing and detecting the end of frame.
I have also tried to reset the flags register (STAT) before every sending, but this didn't help either.
any ideas?
Hi,
RDRF is set when the number of datawords in the receive buffer is greater than the number indicated by LPUART_WATER[RXWATER]. You can set a smaller RXWATER value to have enough time to read out data before overflow. You can enable ORIE bit to enable overflow interrupt to observe when overflow happen.
Regards,
Hi,
thanks for your feedback, I'll be watching the ORIE now.
I didn't quite understand why you pointed out RDRF, as this is never set in my case. Could you please elaborate?
Thanks in advance.
Kind regards.
Hello,
with an oscilloscope I figured the hardware is not sending the message in the first place. It turns out this is not a fault at the receiving end (as I suspected) but actually the message is not sent out.
Workaround currently in use: Reinitialize UART (only INIT not DEINIT) before sending any message. This is working fine.
Hello,
it turned out to provoke the same kind of error.
I am currently not sure what to do anymore, as I am taking care to fetch the data in a manner no OR occurs.
Hello, thanks for your reply.
I have already checked the interrupts, but the config is the same before the error and when the error occurs. It can take some time to reproduce the error, but I will feedback on the setting of the UART registers once it does.