Challenge - 5 Problems
FreeRTOS Shutdown Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate2:00remaining
What is the output of this FreeRTOS shutdown sequence?
Consider this FreeRTOS task code snippet that initiates a graceful shutdown. What will be printed to the console?
FreeRTOS
#include "FreeRTOS.h" #include "task.h" #include <stdio.h> void vShutdownTask(void *pvParameters) { printf("Shutdown started\n"); vTaskDelay(pdMS_TO_TICKS(100)); printf("Closing resources\n"); vTaskDelay(pdMS_TO_TICKS(100)); printf("Shutdown complete\n"); vTaskDelete(NULL); } int main() { xTaskCreate(vShutdownTask, "ShutdownTask", 1000, NULL, 1, NULL); vTaskStartScheduler(); return 0; }
Attempts:
2 left
💡 Hint
Think about the order of printf statements and the delays between them.
✗ Incorrect
The task prints 'Shutdown started', waits 100 ms, prints 'Closing resources', waits another 100 ms, then prints 'Shutdown complete'. The order is exactly as in option C.
🧠 Conceptual
intermediate1:30remaining
Which FreeRTOS function is best to notify tasks to start graceful shutdown?
In a FreeRTOS system, you want to signal multiple tasks to begin their shutdown routines. Which function is most appropriate for this notification?
Attempts:
2 left
💡 Hint
Consider a lightweight way to notify tasks without deleting them immediately.
✗ Incorrect
xTaskNotifyGive() sends a direct notification to a task, which is efficient for signaling events like shutdown. vTaskDelete() deletes a task immediately, not for signaling. vTaskDelay() just delays a task. xQueueSend() is for queues, not direct task notification.
🔧 Debug
advanced2:30remaining
Why does this FreeRTOS shutdown code cause a deadlock?
Analyze the following code snippet. Why does the system hang during shutdown?
FreeRTOS
SemaphoreHandle_t xResourceSemaphore;
void vShutdownTask(void *pvParameters) {
xSemaphoreTake(xResourceSemaphore, portMAX_DELAY);
// Clean up resource
vTaskDelay(pdMS_TO_TICKS(200));
xSemaphoreGive(xResourceSemaphore);
vTaskDelete(NULL);
}
void vMainTask(void *pvParameters) {
xSemaphoreTake(xResourceSemaphore, portMAX_DELAY);
// Perform work
vTaskDelay(pdMS_TO_TICKS(500));
xSemaphoreGive(xResourceSemaphore);
vTaskDelete(NULL);
}
int main() {
xResourceSemaphore = xSemaphoreCreateMutex();
xTaskCreate(vMainTask, "MainTask", 1000, NULL, 2, NULL);
xTaskCreate(vShutdownTask, "ShutdownTask", 1000, NULL, 3, NULL);
vTaskStartScheduler();
return 0;
}Attempts:
2 left
💡 Hint
Look at the semaphore creation in the main function.
✗ Incorrect
xSemaphoreCreateMutex() returns a SemaphoreHandle_t that must be assigned to xResourceSemaphore (e.g., xResourceSemaphore = xSemaphoreCreateMutex();), but it isn't. Thus, xResourceSemaphore remains uninitialized (likely NULL), and xSemaphoreTake() on an invalid handle causes both tasks to block indefinitely with portMAX_DELAY.
📝 Syntax
advanced2:00remaining
Which option correctly implements a graceful shutdown flag in FreeRTOS?
You want to use a global flag to signal tasks to shutdown gracefully. Which code snippet correctly declares and uses this flag?
FreeRTOS
volatile bool shutdownFlag = false; void vTaskFunction(void *pvParameters) { while (!shutdownFlag) { // Task work vTaskDelay(pdMS_TO_TICKS(100)); } // Cleanup code vTaskDelete(NULL); }
Attempts:
2 left
💡 Hint
Check variable initialization and type correctness.
✗ Incorrect
Option D correctly declares the flag as volatile bool initialized to false and uses a proper while loop condition. Option D lacks volatile, which can cause optimization issues in multi-tasking. Option D uses int instead of bool, which is less clear. Option D declares volatile bool but does not initialize it, leading to undefined behavior.
🚀 Application
expert3:00remaining
How many tasks remain active after this shutdown sequence?
Given the following FreeRTOS code, how many tasks remain running after the shutdown sequence completes?
FreeRTOS
#include "FreeRTOS.h" #include "task.h" #include <stdio.h> volatile bool shutdownFlag = false; void vWorkerTask(void *pvParameters) { while (!shutdownFlag) { vTaskDelay(pdMS_TO_TICKS(50)); } printf("Worker task cleanup done\n"); vTaskDelete(NULL); } void vMonitorTask(void *pvParameters) { vTaskDelay(pdMS_TO_TICKS(200)); shutdownFlag = true; printf("Shutdown flag set\n"); vTaskDelete(NULL); } int main() { xTaskCreate(vWorkerTask, "Worker1", 1000, NULL, 2, NULL); xTaskCreate(vWorkerTask, "Worker2", 1000, NULL, 2, NULL); xTaskCreate(vMonitorTask, "Monitor", 1000, NULL, 3, NULL); vTaskStartScheduler(); return 0; }
Attempts:
2 left
💡 Hint
Consider when each task deletes itself after shutdownFlag is set.
✗ Incorrect
MonitorTask sets shutdownFlag after 200 ms and deletes itself. Both Worker tasks detect shutdownFlag true, print cleanup message, and delete themselves. After all deletions, no tasks remain running.