Critical Section issues
Posted by Christian
on January 24, 2013
I'd like to describe a bad scenario we encountered during our project using the uxCriticalNesting variable. In our design, we use Cortex-M3 and the free RTOS version is v7.1.0.
In the enter critical section function called in a task, the first instruction executed is a DISABLE interrupts. In our case, a higher priority interrupt occured just right after the disable interrupt instruction. In the interrupt handler, an enter and exit critical section was called. In the exit critical section from the handler, the interrupts were enabled again because the nesting counter was set to 1.
When the handler interrupt completed, it returns in the critical section in the task with nesting counter to 0 and interrupt enabled... So, the next instruction is the nesting counter increment to 1 and sometimes a switch context can occur in this critical section. In another task, if an other critical section is called, disable interrupt instruction is called and the nesting counter set to 2, and when exit critical section function is called, the nesting decrements to 1 and the interrupts remains disabled.
The task will not be interrupted by other task and the system is still frozen for ever!
An other situation, if higher interrupt priority occurs in a critical section, we called xSemaphoreGiveFromISR(). In that function, we noticed that it enables the interrupts. So, we can provoke context switch in the task's critical section area and maybe corrupt the protected resource.
In brief, the FreeRTOS configMAX_SYSCALL_INTERRUPT_PRIORITY is actually set to 191. We can see in that case higher priority can break our system.
Is there any document available to be aware about some rules about critical section? It's hard to reproduce the problem, but it can happen!
RE: Critical Section issues
Posted by Dave
on January 24, 2013
“In the enter critical section function called in a task, the first instruction executed is a DISABLE interrupts. In our case, a higher priority interrupt occured just right after the disable interrupt instruction. In the interrupt handler, an enter and exit critical section was called. In the exit critical section from the handler, the interrupts were enabled again because the nesting counter was set to 1. ”
I have not read past this paragraph but have already noted two things that are wrong with your application and guess the rest of your post relates to that.
1) You must not use taskENTER_CRITICAL from an ISR. In fact, you must not call any API functions that don't end in FromISR in an ISR. You can use
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
(code cut from queue.c)
2) If you have an interrupt calling API function when the task is in a critical section then the rule that interrupts that use the FromISR API functions must have a priority at or below configMAX_SYSCALL_INTERRUPT_PRIORITY.
Some links that might help you
Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd..
See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.