I have a design based on the MK22FN512. Originally I used the KSDK development suite with FreeRTOS. This has been running for years with no problems.
Now, extending the design, I migrated over to MCUXpresso with the .mex file and have allowed the development suite to generate all of the start-up and supporting routines.
In this new environment, I get random kStatus_UART_RxHardwareOverrun errors when the LPUART_RTOS_Receive() routine returns.
I have increased the priorities of both the hardware interrupt and the corresponding task, but the problem remains.
Can someone provide me with any pointers? (I am attaching the .mex file and can show pertinent sections of code if that helps.)
Thanks
Solved! Go to Solution.
Thanks to Erich Styger for his suggestions. In looking over his code and reviewing the documentation on FreeRTOS and interrupts, I didn't find anything obvious. However, I did stumble on the answer while reviewing the sequence of events. It all came down to the FreeRTOS priorities and their definition.
Under the Freescale SDK, the default number of priorities was something around 10. When migrating the MCUXpresso, it appears the default is 5. Since most of my code started tasks at priority 6, I set the number in FreeRTOS to 7. That corrected the initial problem(s), but this one remained.
In an effort to bump the priority of this one task, I set it to 7 not knowing that the routine would set it to 0 if the number requested was too high! (Yes, I know that for programmers the first number is 0!) The result of this was that my task ran at priority 0, same as the idle task, and was starved. Thus the overruns.
During my investigation, I 'discovered' that the FreeRTOS timer is assigned to the highest priority. So, I increased the number of priorities and made the task of concern to be one less than the timer priority.
Needless to say, the program has been running for more than 4 days - a new record for the MCUXpresso version!
Thanks for the support.
Thanks to Erich Styger for his suggestions. In looking over his code and reviewing the documentation on FreeRTOS and interrupts, I didn't find anything obvious. However, I did stumble on the answer while reviewing the sequence of events. It all came down to the FreeRTOS priorities and their definition.
Under the Freescale SDK, the default number of priorities was something around 10. When migrating the MCUXpresso, it appears the default is 5. Since most of my code started tasks at priority 6, I set the number in FreeRTOS to 7. That corrected the initial problem(s), but this one remained.
In an effort to bump the priority of this one task, I set it to 7 not knowing that the routine would set it to 0 if the number requested was too high! (Yes, I know that for programmers the first number is 0!) The result of this was that my task ran at priority 0, same as the idle task, and was starved. Thus the overruns.
During my investigation, I 'discovered' that the FreeRTOS timer is assigned to the highest priority. So, I increased the number of priorities and made the task of concern to be one less than the timer priority.
Needless to say, the program has been running for more than 4 days - a new record for the MCUXpresso version!
Thanks for the support.
Hi @davepfaltzgraff,
I had faced similar issues in the past, and I solved it with a custom implementation based on the SDK, which now works without issues for me.
You can find it on Github: https://github.com/ErichStyger/McuOnEclipseLibrary/tree/master
The implementation is in the following three source files:
https://github.com/ErichStyger/McuOnEclipseLibrary/blob/master/lib/config/McuShellUartconfig.h
https://github.com/ErichStyger/McuOnEclipseLibrary/blob/master/lib/src/McuShellUart.h
https://github.com/ErichStyger/McuOnEclipseLibrary/blob/master/lib/src/McuShellUart.c
Search in the files for the following:
McuShellUart_CONFIG_UART_K22FN512_LPUART0_C3_C4
What I had to do is to properly enable the FIFO of the UART and properly check and reset the flags in the IRQ, code posted below:
void McuShellUart_CONFIG_UART_IRQ_HANDLER(void) {
uint8_t data;
uint32_t flags;
#if McuShellUart_CONFIG_USE_FREERTOS
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
#endif
uint8_t count;
flags = McuShellUart_CONFIG_UART_GET_FLAGS(McuShellUart_CONFIG_UART_DEVICE);
#if McuShellUart_CONFIG_HAS_FIFO
if (flags&kUART_RxFifoOverflowFlag) {
count = 0; /* statement to allow debugger to set a breakpoint here */
}
#endif
/* If new data arrived. */
if (flags&McuShellUart_CONFIG_UART_HW_RX_READY_FLAGS) {
#if McuShellUart_CONFIG_HAS_FIFO
count = McuShellUart_CONFIG_UART_DEVICE->RCFIFO;
#else
count = 1;
#endif
while(count!=0) {
data = McuShellUart_CONFIG_UART_READ_BYTE(McuShellUart_CONFIG_UART_DEVICE);
#if McuShellUart_CONFIG_USE_FREERTOS
(void)xQueueSendFromISR(uartRxQueue, &data, &xHigherPriorityTaskWoken);
#else
McuRB_Put(rxRingBuffer, &data);
#endif
count--;
}
}
McuShellUART_CONFIG_CLEAR_STATUS_FLAGS(McuShellUart_CONFIG_UART_DEVICE, flags|McuShellUART_CONFIG_CLEAR_EXTRA_STATUS_FLAGS);
#if McuShellUart_CONFIG_USE_FREERTOS
if (xHigherPriorityTaskWoken != pdFALSE) {
vPortYieldFromISR();
}
#endif
#if McuLib_CONFIG_CPU_IS_ARM_CORTEX_M && ((McuLib_CONFIG_CORTEX_M==4) || (McuLib_CONFIG_CORTEX_M==7))
/* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping exception return operation might vector to incorrect interrupt.
* For Cortex-M7, if core speed much faster than peripheral register write speed, the peripheral interrupt flags may be still set after exiting ISR, this results to
* the same error similar with errata 83869. */
__DSB();
#endif
}
I'm using a FreeRTOS Queue for the characters received, and with the above implementation using FIFO and sufficient queue buffer (depending on the receive task priority and handling), I have been able to receive data with and above 115k without issues or buffer overruns.
Notice the possibility in the above code to set a breakpoint or checkpoint in case of buffer overrun: I kept that in the code just in case, but had no need to use it for several years.
I hope this helps,
Erich
Hi Erich,
I'll look into this approach - after I'm done tearing out my hair trying to figure out what's going on now!
You mention setting the FIFO, but in this case there is no FIFO and the Rx is single buffered. My first thought was that this might be the problem, but I don't see the problem in the older code.
I forgot to mention that the baud rate is only 9600. Since there is not much going on the system until the message is received (marked by \r), there should be plenty of time to service the interrupt.
Thanks, Dave
Hi Dave,
Yes, there should be plenty of time. But it could be that you are blocking interrupts for too long, for some reasons.
I wrote an article series here: https://mcuoneclipse.com/2016/08/14/arm-cortex-m-interrupts-and-freertos-part-1/
The other thought I have: maybe you could use the SystemView trace to see what's going on?
I hope this helps,
Erich