FreeRTOS Concurrency - MisterRager/Codelab-Indicator-Lights GitHub Wiki

FreeRTOS Concurrency: Tasks

/**
 * Using a FreeRTOS task, display a spinning rainbow on the LED ring.
 */
void animate_ring_rotate(struct led_state *ring_ptr);

/**
 * Stop the "spinning rainbow" task.
 */
void stop_animate_ring_rotate();

This couplet of functions uses a FreeRTOS task to create an animation effect in the background. Tasks are the way FreeRTOS managed concurrency (multi-tasking). Each task has its own stack, a parameter provided on launch, and access to the same global and static variable space as any other task.

xTaskCreate(
    task_spin_ring,
    "LED Spinner",
    4096,
    ring_ptr,
    5,
    NULL);

Tasks are launched by calling xTaskCreate from freertos/tasks.h and generally run indefinitely. Here, the function task_spin_ring is called with ring_ptr cast to a void * as its one argument. It has been launched with a stack depth of 4096 and priority of 5. Since the last parameter is NULL, no handle is held onto for managing the task.

static void task_spin_ring(void *args)
{
    ...
    ESP_LOGI(TAG, "Stopped spinning");
    xEventGroupClearBits(group_handle_spin_ring, BIT_STOP_SPIN | BIT_IS_SPINNING);
    vTaskDelete(NULL);
}

When a task function is allowed to exit, be sure to clean up any state that is associated with it: free your mallocs, toggle any bits, and above all, call vTaskDelete(NULL), else the device will crash.

The other concurrency primitive being used is the event group (see freertos/event_groups.h). Event groups are used to send signals to tasks. They are implemented as a bitfields to be queried through provided functions: