DÍA 200 DE 365

Fase 4: FreeRTOS y Conectividad IoT

📖 Teoría a Estudiar

Ingeniería del Caos (Stress Testing)

Probar un sistema en "condiciones normales" es fácil; todo funciona cuando el clima es perfecto. El verdadero trabajo del Arquitecto Embebido es probar el sistema bajo condiciones patológicas. Para ello, creamos temporalmente un Chaos Monkey (Mono del Caos), una tarea diseñada exclusivamente para comportarse como hardware averiado y redes saturadas.

Vectores de Ataque Interno

Nuestra tarea inyectará deliberadamente tres tipos de ruido en la topología de nuestro RTOS:

  1. Tormenta de Interrupciones (Interrupt Storm): Disparará falsas interrupciones de hardware (EXTI) a cientos de hercios. Queremos comprobar si nuestra ISR estúpida y el Semáforo Binario resisten sin comerse toda la CPU y causar Inanición (Starvation).
  2. Saturación de Colas (Queue Flooding): Llenará nuestra Cola de Comandos con basura. Queremos comprobar que nuestro Productor Real (el WiFi) no se bloquee ni colapse (HardFault) cuando la función osMessageQueuePut devuelva error de buzón lleno.
  3. Secuestro de Mutex (Mutex Hogging): Adquirirá el Mutex del bus I2C y se irá a dormir sin liberarlo por 100ms. Verificaremos que la Herencia de Prioridad funcione y que la Pantalla y la EEPROM no crasheen al esperar.
PRUEBA DE ESTRÉS: INYECCIÓN DE RUIDO (CHAOS MONKEY) Sistema de Producción Metrología (High) Pantalla (Normal) ISR (Hardware) Inyección "Chaos Monkey" Thread_Chaos 1. SPAM: NVIC_SetPendingIRQ() Sobrecarga ISR (1kHz) 2. FLOOD: QueuePut() Masivo Queue FULL 3. HOG: MutexAcquire() Lento Mutex Lock DEFENSA KERNEL RTOS No Crasha

⚙️ Ejercicios Prácticos

Ejercicio 1: Introduciremos una nueva Tarea en nuestro main.c. Esta tarea se ejecutará solo si definimos una constante de prueba. Usará la generación de números aleatorios para elegir un método de ataque distinto cada pocos milisegundos, simulando la entropía del universo real.


/**
 * @file chaos_monkey.c
 * @brief Tarea de Inyección de Estrés (Chaos Engineering para RTOS)
 */

#include "stm32f401xe.h"
#include "cmsis_os2.h"
#include <stdlib.h> // Para rand()

// Switch maestro de pruebas (En producción se comenta)
#define TEST_MODO_STRESS_ACTIVO 1

extern osMessageQueueId_t queue_comandos_id;
extern osMutexId_t bus_hardware_mutex_id;

// =======================================================
// LA TAREA DEL CAOS (Prioridad Normal/Baja)
// =======================================================
#if TEST_MODO_STRESS_ACTIVO
void Thread_ChaosMonkey(void *argument) {
    
    // Semilla para caos pseudoaleatorio
    srand(osKernelGetTickCount()); 
    Comando_t basura_cmd = { .id = 99, .param = 0.0f };
    
    for (;;) {
        // Elegir un ataque al azar (0, 1 o 2)
        int ataque = rand() % 3;
        
        switch (ataque) {
            case 0:
                // ATAQUE 1: Saturación de Cola (Flooding)
                // Intenta meter 20 mensajes de golpe en una cola que solo soporta 10.
                // Si la Metrología no tiene protección de errores, colapsará.
                for (int i=0; i<20; i++) {
                    // El timeout 0 evita que el mono se bloquee a sí mismo
                    osMessageQueuePut(queue_comandos_id, &basura_cmd, 0, 0);
                }
                UART_Enviar_String("[CHAOS] Cola Saturada intencionalmente.\r\n");
                break;
                
            case 1:
                // ATAQUE 2: Retención de Mutex (Mutex Hogging)
                // Toma la llave del I2C/SPI y "finge" ser un periférico muy lento.
                if (osMutexAcquire(bus_hardware_mutex_id, 100) == osOK) {
                    UART_Enviar_String("[CHAOS] Mutex Secuestrado...\r\n");
                    
                    // Bloquea el bus durante 40ms. Las tareas de Pantalla y Logs 
                    // deberán entrar en Herencia de Prioridad o Bloquearse sin fallar.
                    osDelay(40); 
                    
                    osMutexRelease(bus_hardware_mutex_id);
                    UART_Enviar_String("[CHAOS] Mutex Liberado.\r\n");
                }
                break;
                
            case 2:
                // ATAQUE 3: Tormenta de Interrupciones (Interrupt Spam)
                // Forzamos al microcontrolador a creer que el sensor de flujo (EXTI0)
                // mandó un pulso eléctrico. Lo hacemos 50 veces seguidas.
                // Esto bombardeará el Semáforo Binario de la Metrología.
                UART_Enviar_String("[CHAOS] Tormenta Eléctrica iniciada!\r\n");
                for (int i=0; i<50; i++) {
                    // Magia Negra de ARM: Disparar ISR por software
                    NVIC_SetPendingIRQ(EXTI0_IRQn); 
                    // Pequeño delay manual (busy-wait) para simular ruido de 10kHz
                    for(volatile int j=0; j<1000; j++); 
                }
                break;
        }
        
        // El Mono descansa un rato aleatorio antes del siguiente ataque (50 a 250ms)
        osDelay(50 + (rand() % 200)); 
    }
}
#endif

// =======================================================
// INICIALIZACIÓN (Modificada)
// =======================================================
int main(void) {
    // ... Todo el código del Día 199 intacto ...
    
#if TEST_MODO_STRESS_ACTIVO
    const osThreadAttr_t attr_mono = {
        .name = "ChaosTask",
        .stack_size = 512,
        .priority = osPriorityNormal // Importante que compita con la Pantalla
    };
    osThreadNew(Thread_ChaosMonkey, NULL, &attr_mono);
#endif

    osKernelStart();
    while (1);
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Validación final de la Arquitectura RTOS en Condiciones Hostiles.

¡Has llegado al Día 200 de tu jornada! A partir de hoy, no estás diseñando un prototipo escolar; has forjado una pieza de armamento de software industrial.

Al ejecutar y sobrevivir el `Thread_ChaosMonkey`, observaste la pantalla LCD conectada a tu STM32. Viste cómo la UART gritaba "[CHAOS] Tormenta Eléctrica!" y "[CHAOS] Cola Saturada!". Sin embargo, los litros de Gas LP en la pantalla siguieron avanzando suavemente, sin congelarse, y la válvula se cerró en el milisegundo exacto en que alcanzó su meta. El Kernel de FreeRTOS, escudado por tus Mutexes bien programados y el procesamiento diferido de tus Semáforos, absorbió el ataque sin piedad. El TCB (Task Control Block) contuvo los errores. La Tarea Centinela validó que ninguna tarea muriera de Inanición. Has demostrado empíricamente que tu máquina es digna de la certificación de seguridad SIL-3. Está lista para el mundo real.

📝 Resumen del Día