Index
In FreeRTOS, tasks often need to wait or execute periodically. vTaskDelay()
and vTaskDelayUntil()
are used to manage task timing, allowing tasks to delay for specific intervals or execute at regular, predictable intervals.
Key Functions for Time Management
vTaskDelay()
:- Causes the task to block for a set period, during which the task is idle.
- The delay is specified in “ticks,” which you can calculate using
pdMS_TO_TICKS()
for easier millisecond conversion. - This function doesn’t guarantee that tasks will run at exact intervals due to potential scheduling variability.
vTaskDelayUntil()
:- Used for periodic tasks that need precise timing. It resumes the task exactly at the scheduled time, compensating for execution time.
- Uses an initial “last wake time” variable to track when the task last ran.
- Ensures tasks run at precise intervals without drift.
Example: Using vTaskDelay()
and vTaskDelayUntil()
for Periodic Tasks
This example creates two tasks:
- One using
vTaskDelay()
to blink an LED at a set interval. - Another using
vTaskDelayUntil()
to blink an LED at precise, regular intervals.
Example Code:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define LED_PIN_1 2 // Assume LED 1 is connected to GPIO 2
#define LED_PIN_2 4 // Assume LED 2 is connected to GPIO 4
void vTaskDelayExample(void *pvParameters) {
// Configure LED_PIN_1 as an output
gpio_pad_select_gpio(LED_PIN_1);
gpio_set_direction(LED_PIN_1, GPIO_MODE_OUTPUT);
while (1) {
// Toggle LED state
gpio_set_level(LED_PIN_1, 1);
printf("vTaskDelay LED ON\n");
vTaskDelay(pdMS_TO_TICKS(500)); // 500 ms delay
gpio_set_level(LED_PIN_1, 0);
printf("vTaskDelay LED OFF\n");
vTaskDelay(pdMS_TO_TICKS(500)); // 500 ms delay
}
}
void vTaskDelayUntilExample(void *pvParameters) {
// Configure LED_PIN_2 as an output
gpio_pad_select_gpio(LED_PIN_2);
gpio_set_direction(LED_PIN_2, GPIO_MODE_OUTPUT);
// Store the last wake time, initialized to current time
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = pdMS_TO_TICKS(1000); // 1-second period
while (1) {
// Toggle LED state
gpio_set_level(LED_PIN_2, 1);
printf("vTaskDelayUntil LED ON\n");
vTaskDelay(pdMS_TO_TICKS(500)); // 500 ms on-time
gpio_set_level(LED_PIN_2, 0);
printf("vTaskDelayUntil LED OFF\n");
// Use vTaskDelayUntil to resume at the next 1-second interval
vTaskDelayUntil(&xLastWakeTime, xFrequency);
}
}
void app_main(void) {
// Create the task using vTaskDelay()
xTaskCreate(vTaskDelayExample, "vTaskDelay Task", 2048, NULL, 1, NULL);
// Create the task using vTaskDelayUntil()
xTaskCreate(vTaskDelayUntilExample, "vTaskDelayUntil Task", 2048, NULL, 1, NULL);
}
Explanation of Code
- Task Using
vTaskDelay()
:- The
vTaskDelayExample
function toggles an LED every 500 milliseconds, simulating a blink effect. - The
vTaskDelay(pdMS_TO_TICKS(500))
call delays the task for 500 milliseconds. However, because FreeRTOS is a multi-tasking OS, other tasks may execute during this time.
- The
- Task Using
vTaskDelayUntil()
:- The
vTaskDelayUntilExample
function toggles a second LED on for 500 milliseconds, then usesvTaskDelayUntil()
to ensure it resumes exactly 1 second after the last execution. - The
vTaskDelayUntil(&xLastWakeTime, xFrequency)
function updatesxLastWakeTime
to ensure that each loop iteration starts precisely 1 second apart, creating a predictable period even if task execution varies.
- The
- Main Function (
app_main
):- Creates both tasks. The two tasks run independently and toggle their respective LEDs at their defined intervals.
Output Explanation
You should see output similar to the following:
vTaskDelay LED ON
vTaskDelayUntil LED ON
vTaskDelay LED OFF
vTaskDelayUntil LED OFF
...