DÍA 220 DE 365

Fase 4: FreeRTOS y Conectividad IoT

📖 Teoría a Estudiar

Checksum vs CRC32: La Caza de Errores

¿Cómo validas que un archivo de 150,000 bytes es idéntico a su original sin enviarlo de regreso a la nube?

El Motor Criptográfico del STM32

Calcular un polinomio de 32 bits sobre 150 KB usando ciclos de CPU en C (por software) tardaría demasiados milisegundos y bloquearía a FreeRTOS. Por fortuna, tu STM32F401 tiene un periférico llamado Hardware CRC Engine. Al igual que el DMA o el UART, es un trozo de silicio dedicado exclusivamente a calcular CRCs. Solo tienes que escupirle los bytes y él calcula la matemática a la misma velocidad del reloj del sistema (84 MHz), costando 0% de esfuerzo a tu lógica de aplicación.

FLUJO DE VALIDACIÓN DE INTEGRIDAD BINARIA (HW CRC32) Metadatos de AWS Enviados por MQTT antes de iniciar la descarga. CRC Esperado: 0x8A4F11B2 Flash Bank B 150 KB Descargados Bit Corrupto HAL_CRC Hardware CRC Procesador Paralelo Cálculo Local: 0x3B99E00A == ? Sí WRITE MAGIC WORD & REBOOT MACHINE No (Mismatch) ERASE BANK B & ABORT UPDATE

⚙️ Ejercicios Prácticos

Circuito / Hardware: En CubeMX o en tu código de inicialización, asegúrate de activar el reloj del periférico CRC (__HAL_RCC_CRC_CLK_ENABLE()). Si no lo haces, la función devolverá cero siempre.

Ejercicio 1: Interceptaremos el final de la Máquina de Estados FOTA (Día 219). Antes de escribir la palabra mágica que ordena al Bootloader arrancar la actualización, alimentaremos los 150 KB del Bank B al motor de hardware CRC, y solo procederemos si el resultado coincide con el metadato esperado.


/**
 * @file fota_validator.c
 * @brief Validación de Integridad por Hardware CRC32 post-descarga
 */

#include "stm32f401xe.h"
#include "cmsis_os2.h"
#include "fota_map.h"
#include <stdio.h>

// Manejador del periférico CRC del STM32 (Inicializado en main.c)
extern CRC_HandleTypeDef hcrc;

// =======================================================
// EL MOTOR MATEMÁTICO EN SILICIO
// =======================================================
/**
 * @brief  Calcula el CRC32 de un bloque completo de memoria Flash usando el HW Engine
 * @param  start_address: Dirección física en la Flash donde inicia el firmware
 * @param  length_bytes: El peso total del archivo binario descargado
 * @retval uint32_t: La firma criptográfica CRC32 resultante
 */
uint32_t FOTA_Calcular_CRC_Hardware(uint32_t start_address, uint32_t length_bytes) {
    
    // 1. Limpiamos cualquier cálculo residual en los registros de hardware
    __HAL_CRC_DR_RESET(&hcrc);
    
    // 2. El motor del STM32 procesa de a 32 bits (Words), no bytes. 
    // Por ende, dividimos el peso total de bytes entre 4.
    uint32_t length_words = length_bytes / 4;
    
    // 3. Alimentamos el motor DMA/CRC.
    // Aunque le pasemos 150 KB, esta función toma apenas milisegundos 
    // porque se procesa en hardware de silicio dedicado, no en software.
    uint32_t crc_calculado = HAL_CRC_Calculate(&hcrc, (uint32_t*)start_address, length_words);
    
    // 4. Retornamos la Huella Digital
    return crc_calculado;
}

// =======================================================
// INTEGRACIÓN EN EL BUCLE FOTA (Continuación Día 219)
// =======================================================
/**
 * @brief Rutina de finalización de descarga FOTA
 * @param expected_crc: El CRC que AWS nos avisó vía MQTT antes de empezar
 * @param firmware_size: El tamaño exacto del archivo bajado de S3
 */
void FOTA_Finalizar_y_Validar(uint32_t expected_crc, uint32_t firmware_size) {
    
    UART_Enviar_String("[FOTA] Descarga HTTP finalizada. Iniciando validación CRC32...\r\n");
    
    // Invocamos a la bestia matemática
    uint32_t crc_real = FOTA_Calcular_CRC_Hardware(FOTA_BANK_B_START_ADDR, firmware_size);
    
    char msg[64];
    snprintf(msg, sizeof(msg), "[FOTA] CRC AWS: 0x%08lX | CRC Local: 0x%08lX\r\n", expected_crc, crc_real);
    UART_Enviar_String(msg);
    
    // LA PRUEBA DE FUEGO
    if (crc_real == expected_crc) {
        
        UART_Enviar_String("[FOTA] ¡INTEGRIDAD DEL 100%! El archivo es un clon perfecto.\r\n");
        UART_Enviar_String("[FOTA] Sellando Partición y reiniciando sistema...\r\n");
        
        // Desbloqueamos la Flash para escribir el Sello
        HAL_FLASH_Unlock();
        
        // Escribimos la palabra 0xDEADBEEF para que el Bootloader haga su trabajo
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FOTA_FLAG_ADDRESS, FOTA_MAGIC_WORD_PENDING);
        
        HAL_FLASH_Lock();
        osDelay(1000); // Un segundo para que el buffer UART termine de imprimir
        
        // Apretar el gatillo de suicidio seguro. Nos vemos en el Bootloader.
        NVIC_SystemReset();
        
    } else {
        
        UART_Enviar_String("[FOTA] ERROR CRÍTICO: Discrepancia de CRC detectada.\r\n");
        UART_Enviar_String("[FOTA] El archivo está corrupto. Abortando actualización...\r\n");
        
        // LA SANIDAD DEL SISTEMA PRIMERO
        // Borramos el Bank B inmediatamente para que no haya basura, y 
        // NO escribimos la palabra mágica. El Bootloader ignorará el Bank B.
        FOTA_Borrar_Bank_B(); 
        
        // Devolvemos el control a la FSM principal para que intente descargarlo 
        // de nuevo más tarde o envíe un JSON de alarma "FOTA_FAILED" a AWS.
        return;
    }
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Seguridad Operativa (Safety-Critical Check) y Prevención de Bricking Remoto.

Imagina que la actualización que empujaste contenía la nueva norma de calibración volumétrica requerida por Profeco. Durante la descarga de la máquina "Guadalajara-Norte", la conexión celular 4G sufre inestabilidad y un paquete TCP se corrompe silenciosamente. Si la máquina se reinicia y aplica este firmware ciegamente, un error en los cálculos de flotantes podría causar que la válvula electro-proporcional permanezca abierta permanentemente, sobrellenando un cilindro de Gas LP y provocando una catástrofe industrial (explosión).

Al implementar el **Hardware CRC32 Integrado**, has creado un escudo impenetrable contra la entropía. Tu máquina de estados ahora exige una prueba matemática absoluta antes de ceder el control. Si el servidor AWS te promete que el nuevo firmware tiene un peso de 145,920 bytes y una firma `0xA1B2C3D4`, tu STM32 calcula el polinomio sobre los bytes recién guardados en su Bank B. Si la firma difiere en un solo valor hexadecimal, significa que la integridad del código binario está comprometida. Tu sistema abortará automáticamente, borrará la partición infectada y mantendrá vivo el firmware original del Bank A (Fallback), preservando intacta la seguridad y la contabilidad de la gasolinera. Tu hardware acaba de volverse a prueba de fallos de telecomunicación.

📝 Resumen del Día