En esta entrada nos vamos a familiarizar con FreeRTOS y su código fuente. Aprenderemos cómo se implementa en el ESP32 con el IDE de Arduino. Para empezar, vamos a la página oficial de FreeRTOS y descargamos el código desde Downloads. Mientras que se descarga el archivo, podemos ver las secciones de kernel, libraries y resources para entender como implementar el SO en otro dispositivo. Cuando tengamos el archivo podemos ver su contenido y observamos las distintas carpetas que contienen los ejemplos, las librerías y el código base.

Pero en este tutorial nos centraremos en la versión modificada para ESP32 y por lo tanto podemos consultar los cambios hechos al código fuente original de FreeRTOS para adaptarlo a la ESP32.
Instalando la ESP32 en el IDE de Arduino
Para que nuestra ESP32 funcione en el IDE de Arduino y podamos programarla es necesario agregarla al administrador de tarjetas. Para ello vamos a añadir en el repositorio el enlace del distribuidor de la tarjeta. Abrimos el IDE de Arduino y nos vamos a la sección de Archivo>Preferencias y añadimos este enlace: https://dl.espressif.com/dl/package_esp32_index.json a las URL adicionales.

Ahora nos vamos al administrador de tarjetas desde Herramientas>Placa>Gestor de Tarjetas y buscamos la ESP32, encontramos la tarjeta y la instalamos en nuestro IDE. Con esto podremos cargar nuestros programas a la tarjeta y trabajar con la versión modificada de FreeRTOS.

Desarrollo del programa
Como primer ejercicio vamos a desarrollar un programa “Blink” usando las funciones propias de FreeRTOS. La codificación puede parecer un poco excesiva para algo simple como parpadear un LED pero nos va a familiarizar con los elementos básicos del sistema y nos permitirá desarrollar ejercicios más complejos después.
Lo primero que debemos hacer es definir ciertas constantes para indicarle al programa que procesador vamos a usar, si el 0 o el 1 y el LED que vamos a parpadear, que será el LED integrado. Para ello, dependiendo de las librerías del programa, definimos app_cpu como el procesador 0 o 1 y definimos la constante led_pin como el LED a parpadear
//use only core 1 for demo purpouses
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif
//Pins
static const int led_pin = LED_BUILTIN;
Después definimos la función que haremos llamar para parpadear el LED, que en otras palabras será nuestra Tarea 1 o “Task 1”. Una función que no regrese parámetros con funciones vTaskDelay() y digitalWrite() será suficiente. Observen que en este caso usamos vTaskDelay y no solamente delay(). Esto se debe a que es una función de FreeRTOS que sirve de retardo para cada Tarea.
//Our task: blink an LED
void toggleLED(void *parameter){
while(1){
digitalWrite(led_pin,HIGH);
vTaskDelay(500 / portTICK_PERIOD_MS);
digitalWrite(led_pin,LOW);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
Por ultimo, vamos a crear la función de configuración en donde asignamos el tipo de pin al LED y configuramos los parámetros de nuestra tarea formalmente. Le asignamos a la tarea una función, un nombre, la cantidad de memoria que puede usar, un apuntador, la prioridad de la tarea, otro apuntador que nos permite manejar la tarea y el núcleo o procesador que vamos a usar. En función loop() no necesitamos agregar nada.
void setup() {
//Configure pins
pinMode(led_pin, OUTPUT);
//task to run forever
xTaskCreatePinnedToCore(
toggleLED, //Funcion a llamar
"Toggle LED", //Nombre de la tarea
1024, //Bytes de memoria que puede usar la tarea
NULL, //Apuntador de memoria (no se usa)
1, //Prioridad de la tarea (de 0 a 24, siendo 24 la mayor prioridad)
NULL, //Apuntador de tarea
app_cpu); //Nucleo o procesador que vamos a usar
}
void loop() {
// put your main code here, to run repeatedly:
}
Si todo salió correctamente deberías ver tu LED integrado parpadeando a 1Hz. Si quieres copiar y pegar el códuigo completo puedes revisar el final de esta entrada.
Conclusiones:
Hemos creado nuestro primer código de FreeRTOS y nos hemos familiarizado con las funciones que permiten crear las tareas y los parámetros con las que se configuran. Nuestro siguiente ejercicio sería crear una nueva tarea que se ejecute de forma paralela y que tenga un delay distinto los 500ms, esto creará un efecto de parpadeo distinto y controlará al LED de forma simultánea.
Código:
//use only core 1 for demo purpouses
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif
//Pins
static const int led_pin = LED_BUILTIN;
//Our task: blink an LED
void toggleLED(void *parameter){
while(1){
digitalWrite(led_pin,HIGH);
vTaskDelay(500 / portTICK_PERIOD_MS);
digitalWrite(led_pin,LOW);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
void setup() {
//Configure pins
pinMode(led_pin, OUTPUT);
//task to run forever
xTaskCreatePinnedToCore(
toggleLED, //Funcion a llamar
"Toggle LED", //Nombre de la tarea
1024, //Bytes de memoria que puede usar la tarea
NULL, //Apuntador de memoria (no se usa)
1, //Prioridad de la tarea (de 0 a 24, siendo 24 la mayor prioridad)
NULL, //Apuntador de tarea
app_cpu); //Nucleo o procesador que vamos a usar
}
void loop() {
// put your main code here, to run repeatedly:
}
Referencias:
Introduction to RTOS Part 2 – Getting Started with FreeRTOS | Digi-Key Electronics