Timer callbacks run code when a timer finishes. They help do tasks regularly without blocking other work.
Timer callback execution context in FreeRTOS
void TimerCallback(TimerHandle_t xTimer) {
// Your code here
}
// Create timer
TimerHandle_t xTimer = xTimerCreate(
"TimerName", // Timer name
pdMS_TO_TICKS(1000), // Timer period in ticks
pdTRUE, // Auto-reload (true for repeating)
(void *)0, // Timer ID
TimerCallback // Callback function
);
// Start timer
xTimerStart(xTimer, 0);The callback function runs inside the timer service task context, not your main task.
Keep the callback code short and avoid blocking calls to not delay other timers.
void MyTimerCallback(TimerHandle_t xTimer) {
// Toggle LED
ToggleLED();
}
TimerHandle_t xTimer = xTimerCreate("LEDTimer", pdMS_TO_TICKS(1000), pdTRUE, NULL, MyTimerCallback);
xTimerStart(xTimer, 0);void OneShotCallback(TimerHandle_t xTimer) {
// Send a message once after delay
SendMessage();
}
TimerHandle_t xTimer = xTimerCreate("OneShot", pdMS_TO_TICKS(5000), pdFALSE, NULL, OneShotCallback);
xTimerStart(xTimer, 0);This program creates a repeating timer that calls the callback every second. The callback prints how many times it was called.
The timer runs in the timer service task context, so it does not block the main program.
#include "FreeRTOS.h" #include "timers.h" #include <stdio.h> void TimerCallback(TimerHandle_t xTimer) { static int count = 0; count++; printf("Timer callback called %d times\n", count); } int main(void) { TimerHandle_t xTimer = xTimerCreate("MyTimer", pdMS_TO_TICKS(1000), pdTRUE, NULL, TimerCallback); if (xTimer == NULL) { printf("Timer creation failed\n"); return 1; } if (xTimerStart(xTimer, 0) != pdPASS) { printf("Timer start failed\n"); return 1; } // Start the scheduler vTaskStartScheduler(); // Should never reach here return 0; }
Timer callbacks run in the timer service task, so avoid long or blocking operations inside them.
Do not call FreeRTOS API functions that are not safe from timer callback context.
Use synchronization methods if sharing data between timer callbacks and other tasks.
Timer callbacks run when a timer expires, inside the timer service task context.
Keep callback code short and non-blocking to avoid delaying other timers.
Use timers to perform periodic or delayed actions without stopping main tasks.
Practice
Solution
Step 1: Understand timer callback execution
Timer callbacks in FreeRTOS run when the timer expires, but not in the main task or ISR context.Step 2: Identify the correct context
The timer callback runs inside the timer service task context, which is a dedicated task for handling timers.Final Answer:
Inside the timer service task context -> Option CQuick Check:
Timer callback context = timer service task [OK]
- Thinking timer callbacks run in ISR context
- Assuming callbacks run in main application task
- Confusing hardware timer peripheral with callback context
Solution
Step 1: Recall FreeRTOS timer callback signature
The callback function must accept a TimerHandle_t parameter representing the timer.Step 2: Match the correct function signature
Only the signature withvoid TimerCallback(TimerHandle_t xTimer)matches FreeRTOS requirements.Final Answer:
void TimerCallback(TimerHandle_t xTimer) -> Option AQuick Check:
Callback signature = void func(TimerHandle_t) [OK]
- Using no parameters in callback
- Using void* or int instead of TimerHandle_t
- Returning int instead of void
void vTimerCallback(TimerHandle_t xTimer) {
printf("Timer expired\n");
}
int main() {
TimerHandle_t xTimer = xTimerCreate("Timer", pdMS_TO_TICKS(1000), pdFALSE, NULL, vTimerCallback);
xTimerStart(xTimer, 0);
vTaskDelay(pdMS_TO_TICKS(1500));
return 0;
}Solution
Step 1: Analyze timer creation and start
The timer is created with 1 second period, one-shot, and started, but vTaskStartScheduler() is missing.Step 2: Check scheduler requirement
FreeRTOS timers require the scheduler (and timer service task) to be running via vTaskStartScheduler(); without it, the callback never executes, producing no output.Final Answer:
No output -> Option BQuick Check:
Missing vTaskStartScheduler() = no callback execution [OK]
- Assuming scheduler starts automatically
- Thinking timer expires without scheduler running
- Believing vTaskDelay alone allows callback execution
void vTimerCallback(TimerHandle_t xTimer) {
vTaskDelay(pdMS_TO_TICKS(100));
printf("Timer callback done\n");
}Solution
Step 1: Understand timer callback context
Timer callbacks run inside the timer service task, which handles all timers sequentially.Step 2: Analyze use of vTaskDelay in callback
Calling vTaskDelay blocks the timer service task, delaying other timers and causing timing issues.Final Answer:
Using vTaskDelay inside timer callback blocks timer service task -> Option AQuick Check:
Blocking calls in timer callback delay all timers [OK]
- Thinking callbacks can safely block or delay
- Assuming missing return causes error
- Believing printf is disallowed in callbacks
void vTimerCallback(TimerHandle_t xTimer) {
// Option 1
// vTaskDelay(pdMS_TO_TICKS(100));
// toggleLED();
// Option 2
toggleLED();
}
int main() {
TimerHandle_t xTimer = xTimerCreate("LEDTimer", pdMS_TO_TICKS(500), pdTRUE, NULL, vTimerCallback);
xTimerStart(xTimer, 0);
vTaskStartScheduler();
return 0;
}Solution
Step 1: Review timer callback best practices
Timer callbacks should be short and non-blocking to avoid delaying other timers.Step 2: Evaluate options for toggling LED
Option 1 uses vTaskDelay inside callback, which blocks timer service task. Option 2 calls toggleLED directly without delay, which is correct.Final Answer:
Use Option 2 with direct toggleLED call in callback -> Option DQuick Check:
Non-blocking callback = direct toggleLED call [OK]
- Adding delays inside timer callbacks
- Trying to toggle LED outside timer context
- Blocking main task instead of using timer
Ready to prove it?
Pass the test and this pattern moves unknown
