Disabling interrupts manually, not by taskENTER_CRITICAL()

Hi!

I am writing a program for STM32 using FreeRTOS. I have a shared resource between a task and an interrupt. When I access this shared resource, can I disable this interrupt manually by changing the STM32 registers?

In “Mastering the FreeRTOS™ Real Time Kernel” section 7.2 it is said:
“Calling taskENTER_CRITICAL() and taskEXIT_CRITICAL() is the only legitimate way for a task to alter the interrupt enable state of the processor on which FreeRTOS is running. Altering the interrupt enable state by any other means will invalidate the macro’s nesting count.”

What does that mean exactly? As I understand, taskENTER_CRITICAL() disables all interrupts that use FreeRTOS API. But I need to disable only one interrupt. Do I have to use this function?

Hi Allfather (welcome btw),

I absolutely agree that in order to establish “mutual exclusion” between two threads of execution of which at least one is an interrupt, only inhibiting those interrupts that might be involved in data corruption is the best solution and should definitely be preferred over using the critical section (CS). The main purpose of the CS is to provide uniterruptable code blocks for the FreeRTOS kernel to prevent data corruption of the internal data structures. It’s like a nuclear war head in the combat against synchronization problems as claiming the CS effectively stalls the OS and every task and ISR managed by the OS.

Many many code examples overuse the CS to enforce “simple” mutual exclusion where it is not needed. I believe the reason for that is that FreeRTOS is very portable, and coding for it should be as generic as possible. Not all targets support fine granularity interrupt disabling, so the CS is sort of like the smallest common denominator.

I do strongly recommend using less invasive interrupt disabling where the platform allows that. On the Cortex M, you can even do that on either of two levels: The NVIC level and the device level (eg UART).

1 Like

using taskENTER_CRITICAL/EXIT_CRITICAL should be the only way you turn on and off the GLOBAL interrupt structure. While you could manually set and clear that processor control register, it is not advised as FreeRTOS assumes that it is the only thing changing it.

If you need to disable only a single interrupt, you are free to control that by manipulating the NVIC to do it, as FreeRTOS doesn’t use that, and in fact, you generally need to individually enable each of these interrupts as you configure them,

1 Like