Un microcontrolador STM32 tiene un solo núcleo (Single-Core). Físicamente, es imposible que ejecute dos cosas a la vez. FreeRTOS es un "ilusionista" de software. Permite crear la ilusión de paralelismo ejecutando una Tarea durante 1 milisegundo, pausándola, ejecutando otra Tarea por 1 milisegundo, y repitiendo el ciclo a una velocidad que el humano no puede percibir.
El corazón de FreeRTOS es el Scheduler. Utiliza el temporizador de hardware SysTick (que configuramos en los primeros días) para interrumpir a la CPU exactamente 1000 veces por segundo (1 kHz = 1 ms). A este lapso se le llama Tick. Cada vez que ocurre un Tick, el Scheduler evalúa: "¿Hay alguna tarea con mayor prioridad que necesite ejecutarse AHORA?".
Cuando el Scheduler decide cambiar de la Tarea A a la Tarea B, hace magia negra a nivel de Ensamblador: Toma todos los registros de la CPU de la Tarea A y los guarda en un pedazo de RAM llamado Stack. Luego, saca los registros guardados de la Tarea B de la RAM, los mete a la CPU, y le da "Play". La Tarea A nunca supo que fue pausada, y la Tarea B despierta creyendo que nunca dejó de correr.
Ejercicio 1: Abandonaremos el while(1) principal. Para usar FreeRTOS, debemos incluir la librería del kernel, y crear funciones que actuarán como Súper Bucles individuales e independientes (las Tareas). Finalmente, le entregaremos el control absoluto de nuestra máquina a Dios: invocaremos vTaskStartScheduler().
/**
* @file main_rtos.c
* @brief Introducción a FreeRTOS: Separación de Metrología y Red WiFi
*/
#include "stm32f401xe.h"
#include "FreeRTOS.h"
#include "task.h"
// =======================================================
// TAREA 1: METROLOGÍA Y VÁLVULA (Misión Crítica)
// =======================================================
// Una Tarea en FreeRTOS es simplemente una función C con un loop infinito.
// IMPORTANTE: Una tarea jamás debe retornar.
void vTaskMetrologia(void *pvParameters) {
// Inicializaciones locales de la tarea
float litros = 0.0f;
while(1) {
// 1. Lógica crítica Bare-Metal
litros = Leer_Pulsos_Caudalimetro();
if (litros >= 100.0f) {
Valvula_Cerrar_Fisico(); // Cerrar válvula instantáneamente
}
// 2. MAGIA RTOS: Retardo NO Bloqueante
// En lugar de usar HAL_Delay o un for() estúpido, llamamos a vTaskDelay.
// Esto le dice al Kernel: "Ponme en estado BLOCKED por 10 Ticks (10ms)".
// Durante esos 10ms, el Kernel le da el 100% de la CPU a otras tareas.
vTaskDelay(pdMS_TO_TICKS(10));
}
}
// =======================================================
// TAREA 2: RED WIFI Y NUBE (Baja Prioridad / Latencia alta)
// =======================================================
void vTaskWiFi_Cloud(void *pvParameters) {
while(1) {
// 1. Revisar si hay un ticket pendiente
if (Hay_Ticket_Pendiente()) {
// 2. Operación destructiva bloqueante de Red (Puede tardar 3 segundos)
// En un Súper Bucle, esto congelaría el STM32.
// Con FreeRTOS, esta tarea se suspenderá internamente esperando
// al UART, y el Kernel devolverá la CPU a la Tarea de Metrología.
Enviar_Datos_AWS_Cloud();
}
// Dormir esta tarea por 500ms. No nos urge revisar el WiFi todo el tiempo.
vTaskDelay(pdMS_TO_TICKS(500));
}
}
// =======================================================
// EL MAIN (Configurador del Kernel)
// =======================================================
int main(void) {
// 1. Inicialización de Hardware puro
// SystemClock_Config();
// UART_Init();
// GPIO_Init();
// 2. CREACIÓN DE TAREAS EN EL RTOS
// Le informamos al Kernel qué funciones gobernarán el sistema,
// cuánta memoria RAM (Stack) darle a cada una, y qué PRIORIDAD tienen.
// Tarea Metrología: Prioridad 3 (Alta - El hardware físico manda)
xTaskCreate(
vTaskMetrologia, // Puntero a la función de la tarea
"Task_Metro", // Nombre para depuración
256, // Tamaño de Stack en Words (256 * 4 bytes = 1KB de RAM)
NULL, // Parámetros a pasar (ninguno)
3, // Prioridad (Números mayores = más prioridad)
NULL // Handle (No nos interesa guardar su ID)
);
// Tarea WiFi: Prioridad 1 (Baja - No importa si la nube espera)
xTaskCreate(
vTaskWiFi_Cloud,
"Task_WiFi",
512, // WiFi maneja JSONs y Strings, requiere más RAM (2KB)
NULL,
1, // Prioridad baja
NULL
);
// 3. ENCENDER EL MOTOR DEL TIEMPO
// Esta función enciende el Timer SysTick, asume el control del procesador
// y comienza a saltar entre tareas.
vTaskStartScheduler();
// A PARTIR DE AQUÍ EL CÓDIGO MUERE.
// Si llegas a este while, el RTOS falló (Probablemente te quedaste sin RAM).
while(1) {}
return 0;
}
Objetivo del día: Multitarea Real y Certificación SIL-3 con Conectividad IoT.
Ayer vimos cómo el requerimiento comercial de subir los recibos a la nube de AWS amenazó con destruir la confiabilidad de tu Despachador. Si el procesador se queda "pensando" cómo conectarse a Internet, ignorará los pulsos del flujo de gas, provocando sobrellenado de tanques vehiculares (un peligro inminente de explosión).
Al introducir el núcleo de **FreeRTOS** hoy, has cortado el problema de raíz mediante la arquitectura de **Preempción y Prioridades**. Le hemos dicho a la Tarea Metrológica que es la reina (Prioridad 3). Si la Tarea WiFi (Prioridad 1) está a la mitad de ensamblar un larguísimo archivo JSON de texto para enviarlo a internet, y de pronto llega la hora de revisar la válvula, el hardware de FreeRTOS congelará a la Tarea WiFi a la mitad de una letra, cargará la Metrología en la CPU, cerrará la válvula en microsegundos, y luego le devolverá la CPU al WiFi para que termine su JSON. Has logrado tener lo mejor de ambos mundos: Seguridad Industrial Inquebrantable (SIL) e Innovación Comercial (IoT) coexistiendo en el mismo chip de silicio.