DÍA 164 DE 365

Fase 3: Comunicaciones y Redes Industriales

📖 Teoría a Estudiar

Detección vs. Corrección

Proteger los datos puede hacerse en dos niveles:

REDUNDANCIA MODULAR TRIPLE (TMR) EN MEMORIA RAM Rayo Cósmico / EMI (Bit Flip Event) Memoria SRAM Global Copia A (Precio) 10.55 ❌ (12.55) Copia B (Precio) 10.55 ✅ Copia C (Precio) 10.55 ✅ VOTADOR (Software) B == C Salida Segura a Lógica Valor = 10.55 Autocorrección

⚙️ Ejercicios Prácticos

Ejercicio 1: Desarrollaremos una estructura Variable_TMR_t. El Súper Bucle jamás leerá el "Precio" o el "Total de Litros" directamente. Utilizará una función envoltorio (Getter) que lee las 3 variables. Si las tres coinciden, retorna feliz. Si una difiere (ej. por radiación), asume que las dos iguales tienen la razón (Mayoritario), sobrescribe a la corrupta reparando la RAM, y le entrega al programa el valor seguro.


/**
 * @file ecc_tmr.c
 * @brief Implementación de Paridad Par y Triple Modular Redundancy (TMR)
 */

#include "stm32f401xe.h"
#include <stdint.h>
#include <stdbool.h>

extern void Bloqueo_Legal_Fatal(uint32_t codigo_error); // Día 158
#define ERR_CORRUPCION_RAM_FATAL 0xF005

// =========================================================================
// 1. CÁLCULO DE PARIDAD (Para detección simple en buses internos)
// =========================================================================

/**
 * @brief Calcula el bit de paridad Par de una variable de 32 bits.
 *        Muy útil si almacenas datos en EEPROM externa sin espacio para TMR.
 * @return 0 si los bits '1' son pares, 1 si son impares.
 */
uint8_t Calcular_Paridad_Par_32b(uint32_t data) {
    // Usamos el poder aritmético del procesador ARM
    // Colapsamos los 32 bits a 1 solo bit mediante corrimientos XOR
    data ^= data >> 16;
    data ^= data >> 8;
    data ^= data >> 4;
    data ^= data >> 2;
    data ^= data >> 1;
    
    return (uint8_t)(data & 1);
}

// =========================================================================
// 2. TRIPLE MODULAR REDUNDANCY (TMR) PARA VARIABLES CRÍTICAS EN RAM
// =========================================================================

// Estructura que protege un solo valor multiplicándolo por 3
typedef struct {
    uint32_t copia_A;
    uint32_t copia_B;
    uint32_t copia_C;
} Variable_TMR_t;

/**
 * @brief Escribe un valor en la variable protegida (Actualiza las 3 copias)
 */
void TMR_Escribir(Variable_TMR_t *var, uint32_t valor_nuevo) {
    // Para evitar que una interrupción rompa la atomicidad
    __disable_irq(); 
    
    var->copia_A = valor_nuevo;
    var->copia_B = valor_nuevo;
    var->copia_C = valor_nuevo;
    
    __enable_irq();
}

/**
 * @brief Lee la variable aplicando el algoritmo del "Votador" (Voter)
 *        Detecta y corrige errores de bit simples instantáneamente.
 */
uint32_t TMR_Leer(Variable_TMR_t *var) {
    
    uint32_t a = var->copia_A;
    uint32_t b = var->copia_B;
    uint32_t c = var->copia_C;
    
    // Escenario Perfecto: Ningún rayo cósmico ha golpeado la RAM
    if (a == b && b == c) {
        return a;
    }
    
    // ALERTA: Ocurrió un Bit-Flip. Aplicamos lógica de Voto Mayoritario (2 de 3)
    
    if (a == b) {
        // C está corrupta. La reparamos y retornamos.
        var->copia_C = a; 
        return a;
    }
    
    if (b == c) {
        // A está corrupta. La reparamos y retornamos.
        var->copia_A = b; 
        return b;
    }
    
    if (a == c) {
        // B está corrupta. La reparamos y retornamos.
        var->copia_B = a; 
        return a;
    }
    
    // Escenario Apocalíptico: Un fallo eléctrico masivo ha destruido toda 
    // la sección de la SRAM. Ninguna variable se parece a la otra.
    // Detener la máquina expendedora incondicionalmente.
    Bloqueo_Legal_Fatal(ERR_CORRUPCION_RAM_FATAL);
    return 0; // Inalcanzable, el bloqueo detiene el programa
}

// =========================================================================
// APLICACIÓN EN EL DESPACHADOR DE GAS
// =========================================================================

// Esta es la variable más crítica de todo el sistema. Si se corrompe y 
// baja su valor, el operador de la gasolinera pierde dinero. Si sube, roba al cliente.
Variable_TMR_t precio_por_litro_oficial;

int main(void) {
    
    // Al inicializar el sistema (Ej. descargando el precio del servidor SCADA)
    uint32_t precio_descargado = 1055; // $10.55 MXN
    TMR_Escribir(&precio_por_litro_oficial, precio_descargado);
    
    while(1) {
        
        // Supongamos que la máquina está calculando la venta en la pantalla...
        // ... Un contactor trifásico cercano genera un chispazo y un bit
        // de la "copia_A" de nuestra RAM cambia de 0 a 1 por la interferencia EMI.
        
        // El Súper Bucle NO accede a la RAM directamente. Usa el "Votador".
        uint32_t precio_seguro = TMR_Leer(&precio_por_litro_oficial);
        
        // El votador silenciosamente notó que la Copia A estaba mal. 
        // Usó las copias B y C para arreglar la A en tiempo real, 
        // y nos devolvió el 1055 perfecto. El cliente nunca nota nada, 
        // el código jamás colapsa.
        
        // uint32_t importe_total = litros * precio_seguro;
        // lcd_actualizar_venta(importe_total);
    }
    
    return 0;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Certificación de Misión Crítica (SIL-3 Hardware Inmunity).

A nivel industrial, la protección no termina en aislar la placa en una caja metálica. La vibración, el calor extremo y los campos magnéticos severos causarán fallos transitorios en el silicio (Soft Errors) eventualmente. Si programas las variables críticas de la máquina (`Precio`, `Odómetro_Fiscal`, `Estado_Valvula`) como simples float o int, un solo bit invertido en la RAM convertirá un precio de $10.00 en $266.00.

Al introducir la estructura **TMR (Redundancia Modular Triple)**, has dotado a tu firmware de capacidad "Self-Healing" (Autosanación). Aunque el hardware interno del STM32 sea bombardeado por EMI durante el encendido del compresor de gas, el software detectará la celda de memoria corrupta y la planchará con el dato correcto usando la mayoría de votos. Has elevado el nivel de tu arquitectura metrológica al estándar exigido por reguladores médicos, automotrices (ISO 26262) y de seguridad de instrumentación pesada (SIL-3).

📝 Resumen del Día