DÍA 184 DE 365

Fase 4: FreeRTOS y Conectividad IoT

📖 Teoría a Estudiar

El Estándar CMSIS-OS v2

CMSIS significa Cortex Microcontroller Software Interface Standard. Es una iniciativa de la empresa ARM para unificar la forma en que programamos sus procesadores. CMSIS-OS v2 es una capa de abstracción para Sistemas Operativos (RTOS). En lugar de escribir xTaskCreate (que es exclusivo de FreeRTOS), la industria exige usar osThreadNew. Por debajo, esta función llama a FreeRTOS, pero si mañana te cambias de RTOS, tu código de alto nivel se mantiene intacto.

Desacoplando la Pantalla y la Metrología

En el Súper Bucle, la pantalla LCD es tu peor enemigo. Dibujar un número a color por SPI puede tardar 10 o 15 milisegundos. En el mundo de la metrología de fluidos, 15ms es una eternidad. Si la válvula debía cerrarse en el milisegundo 5, pero el procesador estaba ocupado pintando píxeles verdes, derramarás gas y regalarás dinero.

Al dividir la máquina en Hilos (Threads), le asignamos la prioridad osPriorityHigh a la Tarea de Metrología, y la prioridad osPriorityNormal a la Pantalla. Cuando la pantalla esté a la mitad de dibujar un número, el reloj del sistema (Tick) interrumpirá a la CPU, el Scheduler revisará y dirá: "¡La Metrología es urgente!". Congelará la pantalla, leerá el gas, cerrará la válvula, y luego devolverá el control a la pantalla. Todo en microsegundos.

PREEMPCIÓN BASADA EN PRIORIDADES (CMSIS-OS v2) TIEMPO (ms) → 10 ms 20 ms 30 ms Thread_Pantalla osPriorityNormal Dibuja Fondo SUSPENDIDA Dibuja Precio SPI osDelay Thread_Metrologia osPriorityHigh PID Cierra Válvula! PID Context Switch (Preempción) El Kernel congela la pantalla porque la Metrología despertó (Mayor Prioridad)

⚙️ Ejercicios Prácticos

Ejercicio 1: Abandonamos el código nativo de FreeRTOS e importamos cmsis_os2.h. Declararemos las estructuras de atributos (osThreadAttr_t) que le dicen al sistema operativo cuánta memoria SRAM necesita cada hilo. Luego, construiremos los dos hilos principales: el bucle bloqueante de la pantalla (UI) y el bucle estricto de la Válvula.


/**
 * @file main_os2.c
 * @brief Orquestación de Tareas con CMSIS-OS v2 en el Despachador de Gas
 */

#include "stm32f401xe.h"
#include "cmsis_os2.h"    // Abstracción ARM oficial para RTOS
#include "metrologia.h"
#include "st7789_driver.h"

// =======================================================
// HILO 1: INTERFAZ GRÁFICA (Baja Prioridad)
// =======================================================
void Thread_Pantalla(void *argument) {
    
    // Todo lo que ocurra antes del while(1) se ejecuta solo 1 vez al arrancar
    ST7789_TFT_Init();
    
    // Este es el "Súper Bucle" exclusivo de la pantalla
    for (;;) {
        // Leer datos atómicos protegidos por el Getter
        float litros = Metro_GetLitrosTotales();
        
        // Esta operación es lentísima (15 a 20ms) dibujando por SPI.
        // En Bare-Metal, bloquearía todo. Aquí, no importa.
        UI_Dibujar_Numeros_Gigantes(litros);
        
        // Rendimos la CPU durante 33 milisegundos (~30 fps)
        // La tarea pasa al estado BLOCKED.
        osDelay(33); 
    }
}

// =======================================================
// HILO 2: METROLOGÍA DE PRECISIÓN (Alta Prioridad)
// =======================================================
void Thread_Metrologia(void *argument) {
    
    for (;;) {
        // Ejecutamos el algoritmo PID y leemos los pulsos
        float lts = Leer_Caudalimetro();
        
        // Si alcanzamos el límite exacto, la válvula se cierra AHORA.
        // Debido a que su prioridad es ALTA, si este hilo despierta, 
        // destrozará cualquier dibujo de pantalla a la mitad para ejecutarse.
        if (lts >= 20.0f) {
            Valvula_SetApertura(0.0f); 
        }
        
        // Dormimos exactamente 10 milisegundos.
        // osDelayUntil garantiza un ritmo absoluto (ejecución periódica estricta),
        // ideal para algoritmos matemáticos como el PID.
        osDelay(10);
    }
}

// =======================================================
// CONFIGURACIÓN E INICIO DEL RTOS
// =======================================================
int main(void) {
    
    // 1. Inicializar Hardware Crítico
    SystemClock_Config();
    
    // 2. Inicializar el Kernel CMSIS-OS
    osKernelInitialize();
    
    // 3. ATRIBUTOS DEL HILO DE PANTALLA
    const osThreadAttr_t pantalla_attr = {
        .name = "UI_Task",
        .stack_size = 1024 * 4,           // Pantallas a color necesitan mucha RAM (4KB)
        .priority = (osPriority_t) osPriorityNormal, 
    };
    
    // 4. ATRIBUTOS DEL HILO DE METROLOGÍA
    const osThreadAttr_t metrologia_attr = {
        .name = "Metro_Task",
        .stack_size = 1024 * 1,           // Matemáticas simples, poca RAM (1KB)
        .priority = (osPriority_t) osPriorityHigh, // Prioridad de vida o muerte
    };
    
    // 5. CREACIÓN DE LOS HILOS
    osThreadNew(Thread_Pantalla, NULL, &pantalla_attr);
    osThreadNew(Thread_Metrologia, NULL, &metrologia_attr);
    
    // 6. ARRANCAR EL MOTOR DEL TIEMPO
    osKernelStart();
    
    // En un RTOS sano, la ejecución jamás llega a este punto.
    while (1);
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Aislamiento de Procesos Lentos mediante Multi-Threading.

Cuando programaste tu pantalla a color ST7789 (Día 171), viste que transferir $115,200$ bytes por SPI tomaba un tiempo físico inevitable. En el antiguo paradigma Bare-Metal, el Despachador entero se "congelaba" mientras se pintaba el rojo y el azul en la pantalla. Si en esos milisegundos el usuario soltaba el gatillo de la pistola de gas, la máquina no se enteraba, provocando un grave riesgo de seguridad.

Al implementar `osThreadNew` hoy, le has otorgado a tu sistema **Separación de Intereses (Separation of Concerns) en tiempo de ejecución**. Le diste a la Metrología el poder dictatorial (`osPriorityHigh`). Ahora, la pantalla gráfica puede tardar 20 o 50 milisegundos en dibujarse sin problemas; si en medio de un trazo el sensor requiere atención, el Kernel de CMSIS-OS pausa microscópicamente el dibujo, cierra la válvula con precisión milimétrica, y reanuda el pintado de la pantalla sin que el usuario note el corte. Has logrado la magia de la verdadera multitarea concurrente.

📝 Resumen del Día