DÍA 351 DE 365

Fase 6: Concurrencia y RTOS

📖 Teoría a Estudiar

El Aislamiento Espacial en Software (Spatial Isolation)

En un microcontrolador clásico operando en Bare-Metal, el código C tiene acceso irrestricto a toda la memoria RAM. Esto es un peligro mortal en sistemas concurrentes. Si instalas un RTOS y la "Tarea de Pantalla" tiene un error aritmético (desbordamiento de puntero), puede escribir datos accidentalmente en la dirección de memoria donde reside la variable estado_valvula de la "Tarea de Metrología". El despachador se abrirá solo. Para evitar esto, las normativas de aviación exigen que cada tarea esté encapsulada físicamente.

La Unidad de Protección de Memoria (MPU)

El ARM Cortex-M4 cuenta con un coprocesador de seguridad integrado llamado MPU (Memory Protection Unit). El MPU te permite definir regiones de memoria estrictas para cada tarea del RTOS. Cuando el planificador (Scheduler) cambia el contexto a la Tarea A, reconfigura instantáneamente el MPU para que la Tarea A solo pueda leer y escribir en su propio bloque de RAM. Si la Tarea A intenta tocar la RAM del Kernel o la RAM de la Tarea B, el hardware dispara una interrupción inmediata llamada MemManage_Handler, cortando la ejecución de la tarea corrupta en un solo ciclo de reloj, antes de que el daño ocurra.

AISLAMIENTO ESPACIAL MEDIANTE MPU (MEMORY PROTECTION UNIT) SRAM DEL SISTEMA RTOS KERNEL SPACE Privileged Access Only TASK 1 (Metrología) MPU Region: Read/Write volumen_acumulado TASK 2 (Pantalla LCD) MPU Region: Read/Write lcd_render_buffer HARDWARE MPU Guardián de Silicio CPU CORE (M4) Ejecutando Task 2 Unprivileged Mode ALLOW BLOCK (FAULT) Intento de corrupción de memoria

⚙️ Procedimiento Práctico: Implementación MPU en C

Paso 1: Uso de SafeRTOS o FreeRTOS-MPU.
El repositorio estándar de FreeRTOS opera sin protección de memoria para ser rápido. Para sistemas industriales certificados (IEC 61508), debes compilar la variante FreeRTOS-MPU. Esta variante fuerza a que las tareas se creen en modo no privilegiado (Unprivileged) y te obliga a pasarle al planificador un arreglo con las direcciones de RAM exactas donde la tarea tiene permitido vivir.

Paso 2: Interceptar el `MemManage_Handler`.
Cuando el hardware detecta una violación, invoca esta interrupción. En un entorno de aviación, esta función no se queda en un bucle infinito; guarda el registro del fallo en la memoria EEPROM/SRAM de respaldo (Continuous Journaling), apaga los actuadores de inmediato y reinicia el procesador (Hard Reset) para purgar la corrupción en microsegundos.

💻 Firmware: Configuración de la MPU

Observa cómo la programación abandona el paradigma de "declarar variables libres" y se convierte en la delimitación estricta de áreas físicas en el silicio.


/**
 * @file rtos_mpu_isolation.c
 * @brief Configuración de Hardware MPU para aislamiento espacial de tareas en FreeRTOS
 */

#include "stm32f4xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"

// Definición estricta de límites de RAM para la Tarea de Pantalla (Peligrosa/Inestable)
#define LCD_TASK_RAM_BASE   0x20008000
#define LCD_TASK_RAM_SIZE   MPU_REGION_SIZE_4KB

// =========================================================================
// CONFIGURACIÓN DE LA UNIDAD DE PROTECCIÓN DE MEMORIA (MPU)
// =========================================================================
/**
 * @brief Configura el hardware MPU antes de arrancar el RTOS Scheduler.
 */
void System_MPU_Config(void) {
    MPU_Region_InitTypeDef MPU_InitStruct = {0};

    // 1. Deshabilitar MPU para configuración segura
    HAL_MPU_Disable();

    // 2. Región 1: Área de ejecución de la Tarea LCD (Aislada)
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER1;
    MPU_InitStruct.BaseAddress = LCD_TASK_RAM_BASE;
    MPU_InitStruct.Size = LCD_TASK_RAM_SIZE;
    
    // PERMISOS DE ACCESO CRÍTICOS:
    // MPU_REGION_PRIV_RW_URO: El Kernel (Privileged) puede leer y escribir.
    // La Tarea (Unprivileged User) solo puede Leer. NO PUEDE escribir fuera de sus límites.
    MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RW_URO; 
    
    // Propiedades físicas para prevención de ejecución de código malicioso en RAM
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; 
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
    
    HAL_MPU_ConfigRegion(&MPU_InitStruct);

    // 3. Activar el MPU con la región de fondo (Background Region)
    // para permitir acceso total a las interrupciones del Kernel.
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

// =========================================================================
// EL TRIBUNAL DE HARDWARE (Manejador de Faltas de Memoria)
// =========================================================================
/**
 * @brief Interrupción disparada físicamente en 1 ciclo de reloj si una tarea
 * intenta tocar memoria que no le pertenece.
 */
void MemManage_Handler(void) {
    // 1. Apagar electroválvula inmediatamente por seguridad de hardware
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
    
    // 2. Leer registros de estado de falla para saber qué tarea intentó el hack/corrupción
    uint32_t fault_address = SCB->MMFAR; // MemManage Fault Address Register
    
    // 3. Guardar en Journaling (Registro BKP RTC)
    // (Ej. log_fault_to_rtc(fault_address));
    
    // 4. Reinicio táctico del sistema
    NVIC_SystemReset();
}
        

🚀 Impacto en el Proyecto: Aislamiento Industrial Metrológico

Objetivo del día: Garantizar la integridad operativa mediante hardware enforcing en entornos RTOS concurrentes.

Hemos diseñado tu Despachador de Gas LP para soportar explosiones externas, apagones y hackeos mTLS. Pero, ¿quién vigila al vigilante? Al abandonar la simplicidad del bucle secuencial (Bare-Metal) e instalar un RTOS para manejar interfaces gráficas o redes, invitas al caos de la concurrencia a tu memoria RAM. En lenguajes de bajo nivel como C, la ausencia de control automático de límites (Bounds Checking) significa que un desbordamiento de búfer al dibujar la pantalla LCD podría sobreescribir la memoria donde se almacenan los mililitros exactos que el cliente está pagando.

Al implementar la **MPU (Unidad de Protección de Memoria)** en conjunto con una versión fortificada de FreeRTOS, creas murallas de silicio infranqueables entre tus procesos. El hardware del STM32 actúa como un juez implacable. Si la tarea del Wi-Fi enloquece e intenta leer la variable secreta de las válvulas, la MPU detendrá el procesador en nanosegundos disparando el `MemManage_Handler`. El daño está contenido. La válvula se cierra automáticamente. Has elevado el software de una simple máquina a una arquitectura de supervivencia matemática requerida por la aeronáutica.

📝 Resumen del Día