Does vPortEnterCritical assume that the interrupts are enabled before the first call?

The reason for this question is most of the port implementations when the critical nesting count reaches 0, either re-enable all interrupts or unmask all priorities instead of restoring to what it was before the first call to vPortEnterCritical. This makes me think all the ports are assuming that interrupts are enabled (Or all priorities unmasked depending on the port) before the call to vPortEnterCritical.

vPortEnterCritical assumes that it is the only thing controlling the enabling of interrupts.

1 Like

Are you facing any problem?

Thanks Gaurav. Not as such.
Unfortunately, in our system, I think this assumption may not hold true all the time that when vPortEnterCritical is called interrupts were enabled to begin with. There are other APIs like vPortDisableInterrupts which can be used to disable interrupts prior to calling vPortEnterCritical. That means state of the interrupts before first call to vPortEnterCritical will have to be stored like critical nesting count in the TCB. This state can then be used to restore the interrupt state once the critical section exits. We need to store the interrupt state in the TCB because we have enabled pre-emptive scheduling and that enables kernel to yield from within the critical section.

Can you elaborate on that? Are you talking about before starting the scheduler or afterwards?

Which FreeRTOS port are you using?

*===Can you elaborate on that? Are you talking about before starting the scheduler or afterwards? *
After the scheduler is started. I am still trying to figure out whether we should enforce this assumption that interrupts are always enabled outside of the critical section after the scheduler is started.

===Which FreeRTOS port are you using?
Cortex-A53/R5. We modified it to disable/enable interrupts at the CPU level instead of masking/unmasking in the GIC>

So you want to have code sequences like the following:

disable_interrupts();

     taskENTER_CRITICAL();

     taskEXIT_CRITICAL();

enable_interrupts();

If yes, why can’t you always use taskENTER_CRITICAL/taskEXIT_CRITICAL?

I assume you are modifying the definition of portENABLE_INTERRUPTS/portDISABLE_INTERRUPTS - FreeRTOS-Kernel/portable/GCC/ARM_CR5/portmacro.h at main · FreeRTOS/FreeRTOS-Kernel · GitHub?

==If yes, why can’t you always use taskENTER_CRITICAL/taskEXIT_CRITICAL?
Yes, that is what we should do.

===I assume you are modifying the definition of portENABLE_INTERRUPTS/portDISABLE_INTERRUPTS -
Yes.

Then I think your problem should be solved. Let us know if you have any other issue.

1 Like