Critical Sections and Interrupt Disabling in FreeRTOS
📖 Scenario: You are working on a small embedded system using FreeRTOS. You need to protect a shared variable from being changed by an interrupt while your task is updating it. This is important to avoid errors caused by simultaneous access.
🎯 Goal: Build a simple FreeRTOS program that safely updates a shared variable by disabling interrupts during the update, demonstrating the use of critical sections.
📋 What You'll Learn
Create a shared variable called sharedCounter initialized to 0
Create a variable called interruptMask to hold the interrupt state
Use taskENTER_CRITICAL() and taskEXIT_CRITICAL() to protect the update of sharedCounter
Print the value of sharedCounter after the update
💡 Why This Matters
🌍 Real World
Embedded systems often have tasks and interrupts accessing the same data. Protecting shared data with critical sections prevents errors and crashes.
💼 Career
Understanding how to disable interrupts and use critical sections is essential for embedded software engineers working with real-time operating systems like FreeRTOS.
Progress0 / 4 steps
1
Create the shared variable
Create a global variable called sharedCounter and set it to 0.
FreeRTOS
Hint
Use volatile to tell the compiler this variable can change unexpectedly.
2
Create the interrupt mask variable
Create a variable called interruptMask of type UBaseType_t to hold the interrupt state before disabling interrupts.
FreeRTOS
Hint
This variable will store the interrupt state returned by taskENTER_CRITICAL_FROM_ISR().
3
Protect the update with critical section
Use taskENTER_CRITICAL() and taskEXIT_CRITICAL() to disable interrupts while increasing sharedCounter by 1. Use taskENTER_CRITICAL() and taskEXIT_CRITICAL() to protect the update.
FreeRTOS
Hint
Wrap the update inside the critical section calls to prevent interrupts during the change.
4
Print the updated value
Print the value of sharedCounter using printf to show the result after the critical section update.
FreeRTOS
Hint
Use printf with the format specifier %d to print the integer value.
Practice
(1/5)
1. What is the main purpose of using taskENTER_CRITICAL() and taskEXIT_CRITICAL() in FreeRTOS?
easy
A. To prevent interrupts during a critical section of code
B. To start and stop a task scheduler
C. To allocate memory dynamically
D. To create a new task
Solution
Step 1: Understand critical sections in FreeRTOS
Critical sections are used to protect code that must not be interrupted to avoid data corruption or race conditions.
Step 2: Role of taskENTER_CRITICAL() and taskEXIT_CRITICAL()
These functions disable and enable interrupts respectively, marking the start and end of a critical section.
Final Answer:
To prevent interrupts during a critical section of code -> Option A
Quick Check:
Critical sections stop interrupts = A [OK]
Hint: Critical sections disable interrupts to protect code [OK]
Common Mistakes:
Confusing critical sections with task creation
Thinking they manage memory
Assuming they start the scheduler
2. Which of the following is the correct syntax to mark the start of a critical section in FreeRTOS?
easy
A. taskEXIT_CRITICAL();
B. vTaskStartCritical();
C. taskENTER_CRITICAL();
D. xTaskDisableInterrupts();
Solution
Step 1: Identify the function to enter critical section
The correct FreeRTOS API to disable interrupts and enter a critical section is taskENTER_CRITICAL().
Step 2: Check other options for correctness
taskEXIT_CRITICAL() exits the critical section, others are not valid FreeRTOS functions.
Final Answer:
taskENTER_CRITICAL(); -> Option C
Quick Check:
Enter critical section = taskENTER_CRITICAL() [OK]
Hint: Enter critical section with taskENTER_CRITICAL() [OK]
Common Mistakes:
Using taskEXIT_CRITICAL() to start critical section
D. Interrupts remain disabled causing system issues
Solution
Step 1: Check for matching critical section calls
The code calls taskENTER_CRITICAL() but does not call taskEXIT_CRITICAL() to re-enable interrupts.
Step 2: Understand consequences of missing exit
Interrupts remain disabled indefinitely, which can cause system to freeze or miss important events.
Final Answer:
Interrupts remain disabled causing system issues -> Option D
Quick Check:
Missing taskEXIT_CRITICAL() disables interrupts forever = A [OK]
Hint: Always pair taskENTER_CRITICAL() with taskEXIT_CRITICAL() [OK]
Common Mistakes:
Ignoring missing exit call
Assuming increment fails
Thinking code has syntax errors
5. You have a shared resource accessed by multiple tasks and interrupts. Which approach best protects the resource while keeping system responsiveness high?
hard
A. Use long critical sections with taskENTER_CRITICAL() and taskEXIT_CRITICAL() around all resource access
B. Use short critical sections only around the minimal code that accesses the resource
C. Disable all interrupts globally for the entire program runtime
D. Avoid using critical sections and rely on task delays
Solution
Step 1: Understand impact of critical section length
Long critical sections block interrupts for too long, reducing system responsiveness.
Step 2: Best practice for protecting shared resources
Short critical sections minimize interrupt blocking while protecting shared data safely.
Final Answer:
Use short critical sections only around the minimal code that accesses the resource -> Option B
Quick Check:
Short critical sections = better responsiveness [OK]
Hint: Keep critical sections short for best performance [OK]
Common Mistakes:
Using long critical sections unnecessarily
Disabling interrupts globally
Ignoring synchronization needs
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.