DÍA 195 DE 365

Fase 4: FreeRTOS y Conectividad IoT

📖 Teoría a Estudiar

¿Qué son los Event Flags (Grupos de Eventos)?

Un Event Flag (conocido en la API de FreeRTOS como Event Group) es un registro de 32 bits administrado por el Sistema Operativo. Puedes imaginarlo como un tablero de 32 interruptores (Bits 0 al 31). Cada interruptor representa un evento de tu sistema que puede estar Apagado (0) o Encendido (1).

Lógica AND (Espera Múltiple)

A diferencia de un Semáforo Binario, que solo avisa que "algo" pasó, las Banderas de Eventos permiten Sincronización Múltiple. Una Tarea Maestra puede decirle al RTOS: "Bloquéame (Consume 0% de CPU) y despiértame SOLO SI el Bit 0, el Bit 1 y el Bit 2 están en 1 simultáneamente". Esta es la poderosa lógica de sincronización AND (osFlagsWaitAll).

Lógica OR (Cualquiera es válido)

También puedes usarlos al revés. Una tarea puede pedirle al RTOS: "Bloquéame y despiértame si el Bit 4 O el Bit 5 se encienden". Esta es la lógica de sincronización OR (osFlagsWaitAny). Es ideal para un hilo que reacciona a fallas, ya sea una falla del WiFi (Bit 4) o una falla de voltaje (Bit 5).

SINCRONIZACIÓN DE ARRANQUE MEDIANTE EVENT FLAGS Task 1: PANTALLA Tarda 500ms en bootear Set Bit 0 Task 2: SENSOR I2C Tarda 10ms en bootear Set Bit 1 Task 3: WIFI ESP32 Tarda 3000ms en bootear Set Bit 2 EVENT FLAGS (32 Bits) B0: 1 (LCD_OK) B1: 1 (SENS_OK) B2: 1 (WIFI_OK) LÓGICA AND Task M: METROLOGÍA ESTADO: BLOCKED WaitAll(B0 | B1 | B2) ESTADO: RUNNING ¡Despacha gas seguro! La Tarea Maestra no gasta CPU mientras espera a los 3 periféricos.

⚙️ Ejercicios Prácticos

Ejercicio 1: Coordinaremos el arranque de nuestro Despachador de Gas LP. Definiremos las máscaras de bits para la Pantalla, el Sensor ADC y el WiFi. La Tarea principal de Metrología se declarará en coma inducido (BLOCKED) usando osFlagsWaitAll, y solo se despertará cuando el RTOS detecte que los 3 bits han sido encendidos por las tareas esclavas.


/**
 * @file boot_sync_rtos.c
 * @brief Orquestación de Arranque de Periféricos usando CMSIS-OS v2 Event Flags
 */

#include "stm32f401xe.h"
#include "cmsis_os2.h"

// =======================================================
// DEFINICIÓN DE LOS BITS DE EVENTOS
// =======================================================
// Usamos desplazamientos de bits (Bitwise Shifts) para crear máscaras únicas
#define FLAG_PANTALLA_OK    (1U << 0)  // Bit 0: 0x00000001
#define FLAG_SENSOR_OK      (1U << 1)  // Bit 1: 0x00000002
#define FLAG_WIFI_OK        (1U << 2)  // Bit 2: 0x00000004

// Máscara combinada que representa el Éxito Total
#define FLAGS_SISTEMA_LISTO (FLAG_PANTALLA_OK | FLAG_SENSOR_OK | FLAG_WIFI_OK)

// Objeto global manejador de las banderas
osEventFlagsId_t boot_flags_id;

// =======================================================
// TAREAS INICIALIZADORAS (Esclavas)
// =======================================================
void Thread_Pantalla(void *argument) {
    // 1. Inicializa el hardware SPI (Tarda 500ms)
    ST7789_Init();
    UI_Mostrar_Splash_Screen();
    
    // 2. Avisar al sistema operativo encendiendo nuestro Bit
    osEventFlagsSet(boot_flags_id, FLAG_PANTALLA_OK);
    
    // 3. Entra a su ciclo de vida normal
    for(;;) { osDelay(100); }
}

void Thread_Sensor(void *argument) {
    // 1. Calibra el hardware ADC (Tarda 10ms)
    Sensor_Presion_Calibrar();
    
    // 2. Avisar encendiendo el Bit 1
    osEventFlagsSet(boot_flags_id, FLAG_SENSOR_OK);
    
    for(;;) { osDelay(50); }
}

void Thread_WiFi(void *argument) {
    // 1. Conecta al Router por UART AT Commands (Tarda 3000ms!)
    ESP32_Conectar_Red("Estacion_Gas", "Password123");
    
    // 2. Avisar encendiendo el Bit 2
    osEventFlagsSet(boot_flags_id, FLAG_WIFI_OK);
    
    for(;;) { osDelay(1000); }
}

// =======================================================
// TAREA MAESTRA (Director de Orquesta)
// =======================================================
void Thread_Metrologia(void *argument) {
    
    // 1. EL GRAN BLOQUEO (Sincronización AND)
    // Parámetro 1: El objeto de las Banderas.
    // Parámetro 2: Qué bits estamos esperando.
    // Parámetro 3: Opciones (osFlagsWaitAll = Lógica AND exigiendo todos los bits)
    // Parámetro 4: Timeout (osWaitForever = Sin prisa, el tiempo que tome el WiFi)
    
    osEventFlagsWait(boot_flags_id, FLAGS_SISTEMA_LISTO, osFlagsWaitAll, osWaitForever);
    
    // --- ESTA LÍNEA SOLO SE EJECUTARÁ CUANDO EL SISTEMA ESTÉ AL 100% ---
    
    // Ya es seguro emitir el pitido y encender las válvulas
    Buzzer_Beep();
    Valvula_Habilitar_Seguridad();
    
    // 2. Ciclo de vida normal
    for(;;) {
        // Control de Despacho de Gas LP
        osDelay(10);
    }
}

// =======================================================
// INICIALIZACIÓN PRINCIPAL
// =======================================================
int main(void) {
    SystemClock_Config();
    osKernelInitialize();
    
    // CREAR LAS BANDERAS DE EVENTOS
    boot_flags_id = osEventFlagsNew(NULL);
    
    if (boot_flags_id == NULL) {
        Error_Handler(); // Falla catastrófica de RAM
    }
    
    // Crear Hilos
    osThreadNew(Thread_Pantalla, NULL, NULL);
    osThreadNew(Thread_Sensor,   NULL, NULL);
    osThreadNew(Thread_WiFi,     NULL, NULL);
    osThreadNew(Thread_Metrologia, NULL, &attr_alta_prioridad);
    
    osKernelStart();
    while (1);
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Interbloqueos Previstos y Cadenas de Arranque Deterministas.

En el sector industrial, una máquina jamás debe permitir la operación humana si sus sistemas auxiliares no han verificado su integridad. Si el chip WiFi tarda 5 segundos en negociar el DHCP con el router local, y tú permites que la Metrología abra la válvula de gas en el segundo 2, la máquina podría intentar emitir un "Alerta de Fuga" hacia un socket de internet que aún no existe, provocando un HardFault o Memory Leak.

Al programar el arranque de tu proyecto utilizando **Event Flags**, transformas el caos asíncrono en un bloque de cemento. No necesitas crear un hilo monstruoso y largo que inicialice cosas secuencialmente (primero pantalla, luego wifi, luego sensores). Creaste 3 hilos esbeltos que trabajan en paralelo; mientras la pantalla se dibuja, el sensor se calibra y el WiFi conecta (ahorrando valiosos segundos de Boot Time). La Tarea de Metrología duerme como un vigilante pasivo, consumiendo cero energía, hasta que el RTOS verifica matemáticamente la conjunción binaria (`AND`) de los 3 subsistemas listos. Esto garantiza un Boot determinista, robusto y 100% tolerante a fallas de latencia.

📝 Resumen del Día