Challenge - 5 Problems
FreeRTOS Critical Section Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate2:00remaining
Output of nested critical sections in FreeRTOS
Consider the following FreeRTOS code snippet. What will be the output printed to the console?
FreeRTOS
#include "FreeRTOS.h" #include "task.h" #include <stdio.h> void exampleFunction() { taskENTER_CRITICAL(); printf("Inside first critical section\n"); taskENTER_CRITICAL(); printf("Inside nested critical section\n"); taskEXIT_CRITICAL(); printf("Exited nested critical section\n"); taskEXIT_CRITICAL(); printf("Exited first critical section\n"); } int main() { exampleFunction(); return 0; }
Attempts:
2 left
💡 Hint
Remember that nested critical sections in FreeRTOS use a counter to track entry and exit.
✗ Incorrect
FreeRTOS allows nested critical sections by incrementing a nesting count on each taskENTER_CRITICAL call and decrementing it on taskEXIT_CRITICAL. The output follows the order of the print statements inside and after each critical section.
❓ Predict Output
intermediate2:00remaining
Effect of interrupt disabling on task switching
What will happen if interrupts are disabled globally in FreeRTOS for a long time inside a task?
FreeRTOS
void vTaskFunction(void *pvParameters) {
portDISABLE_INTERRUPTS();
// Simulate long processing
for (volatile int i = 0; i < 1000000; i++) {}
portENABLE_INTERRUPTS();
vTaskDelete(NULL);
}Attempts:
2 left
💡 Hint
Think about what disabling interrupts globally means for the scheduler.
✗ Incorrect
Disabling interrupts globally prevents the FreeRTOS scheduler from running, so no context switches occur. This can cause the system to freeze if interrupts are disabled for too long.
🔧 Debug
advanced2:00remaining
Identify the error in critical section usage
What error will the following FreeRTOS code cause when run on a Cortex-M microcontroller?
FreeRTOS
void faultyFunction() {
taskENTER_CRITICAL();
// Critical code
taskEXIT_CRITICAL();
taskEXIT_CRITICAL(); // Extra exit
}Attempts:
2 left
💡 Hint
Check how FreeRTOS tracks critical section nesting internally.
✗ Incorrect
Calling taskEXIT_CRITICAL more times than taskENTER_CRITICAL causes the nesting count to go below zero, leading to undefined behavior and possible system instability.
🧠 Conceptual
advanced2:00remaining
Why use portENTER_CRITICAL instead of taskENTER_CRITICAL?
In FreeRTOS, what is the main difference between portENTER_CRITICAL() and taskENTER_CRITICAL(), and when should portENTER_CRITICAL be used?
Attempts:
2 left
💡 Hint
Consider the abstraction layers in FreeRTOS and hardware-specific code.
✗ Incorrect
portENTER_CRITICAL is a macro that disables interrupts at the hardware port level and is used in low-level or ISR code. taskENTER_CRITICAL is a higher-level macro that calls portENTER_CRITICAL and manages nesting for tasks.
❓ Predict Output
expert3:00remaining
Output of interrupt priority masking in critical section
Given the following FreeRTOS code on a Cortex-M with configMAX_SYSCALL_INTERRUPT_PRIORITY set to 5, what is the value of variable x after the critical section?
FreeRTOS
#include "FreeRTOS.h" #include "task.h" #include "cmsis_os.h" volatile int x = 0; void vTask(void *pvParameters) { taskENTER_CRITICAL(); x = 10; taskEXIT_CRITICAL(); } int main() { NVIC_SetPriorityGrouping(3); // Priority grouping NVIC_SetPriority(SysTick_IRQn, 6); // Lower priority than max syscall NVIC_SetPriority(USART1_IRQn, 4); // Higher priority than max syscall x = 0; vTask(NULL); return x; }
Attempts:
2 left
💡 Hint
Recall that taskENTER_CRITICAL disables interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY.
✗ Incorrect
taskENTER_CRITICAL disables interrupts with priority equal or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY (5). Since SysTick_IRQn is priority 6 (lower priority), it is masked. USART1_IRQn with priority 4 (higher priority) is not masked but does not affect x here. So x is set to 10 safely.