eRTOS
Manejo de Tareas en FreeRTOS con ESP32
En este documento, exploraremos cómo crear, pausar, reanudar y eliminar tareas en FreeRTOS utilizando un ESP32. También veremos cómo asignar tareas a diferentes núcleos del procesador y corregiremos errores comunes para evitar reinicios inesperados.
1. Creación de Tareas
Para iniciar, creamos una tarea simple que cuenta hasta 5 antes de eliminarse:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
TaskHandle_t taskHandle1 = NULL;
void task1(void *args) {
int count = 0;
while (1) {
count++;
printf("Task 1 count: %d\n", count);
if (count > 5) {
vTaskDelete(NULL);
}
}
}
void app_main(void)
{
xTaskCreate(task1, "task1", 4096, NULL, 10, &taskHandle1);
}
Este código crea una tarea que se ejecuta en un bucle hasta que count supera 5, momento en el cual se elimina.
2. Creación de una Segunda Tarea
Para agregar una segunda tarea, modificamos el código para incluir task2:
TaskHandle_t taskHandle2 = NULL;
void task2(void *args) {
int count = 0;
while (1) {
count++;
printf("Task 2 count: %d\n", count);
}
}
void app_main(void)
{
xTaskCreate(task1, "task1", 4096, NULL, 10, &taskHandle1);
xTaskCreate(task2, "task2", 4096, NULL, 10, &taskHandle2);
}
Ahora, tenemos dos tareas ejecutándose en paralelo con la misma prioridad.
3. Asignación de Tareas a Diferentes Núcleos
Podemos ejecutar task2 en el segundo núcleo del ESP32 utilizando xTaskCreatePinnedToCore:
void app_main(void)
{
xTaskCreate(task1, "task1", 4096, NULL, 10, &taskHandle1);
xTaskCreatePinnedToCore(task2, "task2", 4096, NULL, 10, &taskHandle2, 1);
}
De esta manera, task1 se ejecuta en el núcleo 0 y task2 en el núcleo 1.
4. Control de Ejecución de Tareas
Ahora, task1 controlará la ejecución de task2. La lógica es la siguiente:
- Cuando task1 llega a 3, suspende task2.
- Cuando task1 llega a 10, reanuda task2.
- Cuando task1 llega a 12, elimina task2.
- Cuando task1 llega a 15, se elimina a sí misma.
Código actualizado:
void task1(void *args) {
int count = 0;
while (1) {
count++;
printf("Task 1 count: %d\n", count);
if (count == 3) {
vTaskSuspend(taskHandle2);
printf("Task 2 suspended\n");
}
if (count == 10) {
vTaskResume(taskHandle2);
printf("Task 2 resumed\n");
}
if (count == 12) {
vTaskDelete(taskHandle2);
printf("Task 2 deleted\n");
}
if (count == 15) {
printf("Task 1 deleted\n");
vTaskDelete(NULL);
}
}
}
Este código permite que task1 gestione task2 de manera controlada.
5. Compilación y Ejecución
Para compilar y subir el código al ESP32, ejecutamos en la terminal:
idf.py build
idf.py -p COM3 flash
idf.py -p COM3 monitor
Observaremos la ejecución en el monitor serie, donde task1 contará y suspenderá, reanudará y eliminará task2 en los momentos adecuados.
6. Consideraciones Finales
- Evita el uso de >= en los condicionales para evitar ejecuciones repetidas y errores de kernel.
- Las impresiones pueden no aparecer en orden exacto, ya que FreeRTOS ejecuta tareas lo más rápido posible.
- Asignar tareas a núcleos específicos puede mejorar el rendimiento, pero requiere planificación.
Este ejercicio nos ayuda a comprender cómo FreeRTOS maneja tareas y cómo podemos controlarlas eficientemente.