Using vTaskDelayUntil() for Precise Timing in FreeRTOS
📖 Scenario: You are programming a FreeRTOS task that needs to toggle an LED at a precise 500 ms interval. Using vTaskDelayUntil() helps keep the timing exact, even if the task takes some time to run.
🎯 Goal: Create a FreeRTOS task that toggles an LED every 500 milliseconds using vTaskDelayUntil() for precise timing.
📋 What You'll Learn
Create a variable to hold the last wake time using TickType_t
Set a delay interval of 500 milliseconds using pdMS_TO_TICKS(500)
Use vTaskDelayUntil() inside the task loop to wait precisely
Toggle the LED inside the loop
Print a message each time the LED toggles
💡 Why This Matters
🌍 Real World
Precise timing is important in embedded systems for tasks like blinking LEDs, reading sensors, or controlling motors at exact intervals.
💼 Career
Understanding <code>vTaskDelayUntil()</code> is essential for embedded developers working with FreeRTOS to create reliable and predictable real-time applications.
Progress0 / 4 steps
1
Create the task function and last wake time variable
Write a FreeRTOS task function called vLEDTask that declares a variable TickType_t xLastWakeTime and initializes it with xTaskGetTickCount().
FreeRTOS
Hint
Use xTaskGetTickCount() to get the current tick count for timing.
2
Define the delay interval variable
Inside the vLEDTask function, create a variable const TickType_t xDelay500ms and set it to pdMS_TO_TICKS(500) to represent 500 milliseconds delay.
FreeRTOS
Hint
Use pdMS_TO_TICKS(500) to convert 500 milliseconds to ticks.
3
Add the infinite loop with vTaskDelayUntil() and toggle LED
Inside the vLEDTask function, add a for (;;) infinite loop. Inside the loop, call vTaskDelayUntil(&xLastWakeTime, xDelay500ms) to wait precisely. Then toggle the LED by calling ToggleLED().
FreeRTOS
Hint
Use vTaskDelayUntil() with the address of xLastWakeTime and the delay variable.
4
Print a message each time the LED toggles
Inside the infinite loop in vLEDTask, after toggling the LED, add a printf("LED toggled\n") statement to print a message each time the LED changes state.
FreeRTOS
Hint
Use printf("LED toggled\n") to show the LED toggle event.
Practice
(1/5)
1. What is the main purpose of vTaskDelayUntil() in FreeRTOS?
easy
A. To delay a task until a fixed periodic time, keeping timing precise
B. To delay a task for a random amount of time
C. To suspend a task indefinitely
D. To immediately resume a suspended task
Solution
Step 1: Understand the function's purpose
vTaskDelayUntil() is designed to delay a task until a specific time, maintaining a fixed periodic interval.
Step 2: Compare options with function behavior
Only To delay a task until a fixed periodic time, keeping timing precise describes this precise periodic delay. Other options describe unrelated behaviors.
Final Answer:
To delay a task until a fixed periodic time, keeping timing precise -> Option A
Quick Check:
Precise periodic delay = A [OK]
Hint: vTaskDelayUntil keeps timing steady, not random delays [OK]
Common Mistakes:
Confusing vTaskDelayUntil with vTaskDelay
Thinking it suspends tasks indefinitely
Assuming it resumes tasks immediately
2. Which of the following is the correct way to declare the variable used with vTaskDelayUntil() to track the last wake time?
easy
A. TickType_t xLastWakeTime = 0;
B. int xLastWakeTime = 0;
C. TickType_t xLastWakeTime;
D. void *xLastWakeTime = NULL;
Solution
Step 1: Identify the correct type for last wake time
The FreeRTOS API specifies TickType_t as the type for tick counts and time tracking.
Step 2: Initialization rules for vTaskDelayUntil
The variable must be declared but not necessarily initialized to zero; it is initialized by calling xLastWakeTime = xTaskGetTickCount(); before the loop.
Final Answer:
TickType_t xLastWakeTime; -> Option C
Quick Check:
Use TickType_t without initial zero for last wake time [OK]
Hint: Declare with TickType_t, initialize with xTaskGetTickCount() [OK]
Common Mistakes:
Using int instead of TickType_t
Initializing to zero instead of using xTaskGetTickCount()
Using void pointer type
3. Given the code snippet below, what will be the approximate delay between each "Task running" print?
A. Approximately 1000 milliseconds, steady without drift
B. Exactly 1000 milliseconds between prints
C. Variable delay, sometimes less than 1000 milliseconds
D. No delay, prints continuously
Solution
Step 1: Understand vTaskDelayUntil behavior
It delays the task until the next fixed interval based on the last wake time, keeping timing steady.
Step 2: Analyze the delay duration
The delay is set to 1000 ms converted to ticks, so the task runs approximately every 1000 ms without accumulating drift.
Final Answer:
Approximately 1000 milliseconds, steady without drift -> Option A
Quick Check:
vTaskDelayUntil = steady periodic delay [OK]
Hint: vTaskDelayUntil keeps intervals steady, not exact but no drift [OK]
Common Mistakes:
Assuming exact millisecond precision
Confusing with vTaskDelay which causes drift
Thinking delay varies randomly
4. Identify the error in the following FreeRTOS task code using vTaskDelayUntil():
void vTaskFunction(void *pvParameters) {
TickType_t xLastWakeTime = 0;
for (;;) {
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(500));
// Task code here
}
}
medium
A. vTaskDelayUntil() should not be used inside a loop
B. TickType_t cannot be initialized to zero
C. pdMS_TO_TICKS() cannot be used as a delay parameter
D. xLastWakeTime should be initialized with xTaskGetTickCount() before the loop
Solution
Step 1: Check initialization of xLastWakeTime
It must be initialized to the current tick count using xTaskGetTickCount() before the loop to set the reference time.
Step 2: Verify usage of vTaskDelayUntil
The function is correctly used inside the loop, and pdMS_TO_TICKS is valid for converting milliseconds to ticks.
Final Answer:
xLastWakeTime should be initialized with xTaskGetTickCount() before the loop -> Option D
Quick Check:
Initialize xLastWakeTime with xTaskGetTickCount() [OK]
Hint: Always init last wake time with xTaskGetTickCount() before loop [OK]
Common Mistakes:
Not initializing xLastWakeTime before loop
Misusing vTaskDelayUntil outside loops
Incorrect delay parameter types
5. You want a FreeRTOS task to run exactly every 200 ms without drift, but your task sometimes takes 50 ms to execute. How should you use vTaskDelayUntil() to achieve this?
hard
A. Use vTaskDelayUntil() with 50 ms delay to match task execution time
B. Initialize xLastWakeTime with xTaskGetTickCount() before the loop, then call vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(200)) inside the loop after task code
C. Initialize xLastWakeTime to zero and call vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(250)) before task code
D. Call vTaskDelay(pdMS_TO_TICKS(200)) after task code to delay fixed 200 ms
Solution
Step 1: Understand timing requirements
The task must run every 200 ms total, including 50 ms execution time, so delay should be 200 ms fixed interval.
Step 2: Correct usage of vTaskDelayUntil
Initialize xLastWakeTime with xTaskGetTickCount() before the loop, then call vTaskDelayUntil() with 200 ms delay after task code to maintain steady timing without drift.
Final Answer:
Initialize xLastWakeTime with xTaskGetTickCount() before the loop, then call vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(200)) inside the loop after task code -> Option B
Quick Check:
Init last wake time + vTaskDelayUntil with full period = D [OK]
Hint: Init last wake time, delay full period after task code [OK]
Common Mistakes:
Using vTaskDelay instead of vTaskDelayUntil causing drift
Not accounting for task execution time in delay
Initializing xLastWakeTime incorrectly
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.