High Frequency Interrupt and Queues/Semaphores

imaduck wrote on Saturday, July 08, 2017:

Hi everyone,

I have a question regarding FreeRTOS with high Frequency Interrupts and Queues/Semaphores.
The setup:
Cortex M4 (NXP LPC4337)
UART Interrupt with high data rates
One Semaphore as new data notify
Given by the UART ISR with:

configASSERT(uart3NewDataSemaphore);
xSemaphoreGiveFromISR(uart3NewDataSemaphore, &higherPriorityTaskWokenUart3);
portEND_SWITCHING_ISR(higherPriorityTaskWokenUart3);

The counterpart tries to take this semaphore wit:

 xSemaphoreTake(uart3NewDataSemaphore, portMAX_DELAY);

With no or small data rate (e.g. with manual serial input through putty) everything works fine. But if we connect a peripheral with a lot of data we get in trouble and often the programm hangs up in the function vListInsert in FreeRTOS/list.c.

The following IRQs are activated:
CAN1 with priority 6
ADC0 with priority 6
UART3 with priority 6
configPRIO_BITS is set to __NVIC_PRIO_BITS which equals 3

Maybe someone here as an idea about the problem?

Cheers,
Marvin

Edit: Updated IRQ Priorities

richarddamon wrote on Saturday, July 08, 2017:

That sort of hang up is most often caused by the priorities being higher (lower in value for Arms) than configMAX_SYSCALL_INTERRUPT_PRIORITY which will cause corruption of FreeRTOS control variables. High interrupt rates will make it more likely that this will cause an issue.

A second point is that when you have a high interrupt rate, you generally want to do the preliminary processing inside the ISR, and have it buffer up a packet of data and then pass that down to a task to process as a packet (if you can’t setup a DMA transfer to handle the high speed collection). Task switching does cost time, so doing it too fast can exhaust you CPU processing. (It sort of depends on how fast is ‘fast’ and how fast is the processor.

A smaller point is that if you do need to transfer to a task, if you can use the direct-to-task notification you will save some processing.

One last comment on your architecture, is that you are using a semaphore on data ready and the task does the actual data read, you are requiring that the task actually gets the read done within a character time or your might lose data (depending on the fifo abilities of the Serial Port). This is one reason it is also good to get the data in the ISR.