Durante el desarrollo, la máquina te pertenecía. Si algo fallaba, conectabas tu ST-Link, abrías el depurador y reiniciabas el estado. El Go Live (Puesta en Marcha) significa que hoy cortas el cordón umbilical. El Despachador de Gas LP ahora pertenece a la intemperie. Será golpeado por la radiación solar, asfixiado por el polvo y expuesto a caídas de tensión eléctrica en la madrugada.
Tu única línea de defensa son las decisiones arquitectónicas que tomaste: La barrera física de aislamiento de 5000V, el Watchdog Timer de hardware independiente (IWDG), el Bootloader que protege el Golden Master de corrupciones por apagón, y tu código matemático esterilizado de números flotantes y fragmentación de memoria.
A lo largo del proyecto aprendiste a aislar periféricos y crear tareas individuales. El código que verás a continuación es el main.c definitivo. Es la coreografía maestra. Observa el orden estricto de inicialización: El hardware de seguridad y la contención de memoria (MPU) se encienden antes que el sistema operativo y cualquier comunicación externa. Si el arranque falla, la válvula permanece bloqueada por la física del relé.
/**
* ============================================================================
* @file main.c
* @brief DESPACHADOR DE GAS LP INDUSTRIAL - KERNEL DE INICIO (GOLDEN MASTER)
* @date Septiembre 2026
* @version 1.0.0-PROD
*
* Compilado bajo directiva -Werror. Aritmética 100% Punto Fijo (stdint.h).
* Aislamiento de Memoria MPU activado.
* ============================================================================
*/
#include "stm32f4xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
// Prototipos de Inicialización Arquitectónica
void SystemClock_Config(void);
void MPU_Config_Hardened(void);
void GPIO_Init_FailSafe(void);
void IWDG_Init_Watchdog(void);
// Prototipos de Tareas del RTOS (Definidas en sus respectivos módulos)
extern void vTask_Metrology_Core(void *pvParameters);
extern void vTask_Telemetry_Router(void *pvParameters);
extern void vTask_HMI_Display(void *pvParameters);
/**
* @brief EL CEREBRO DEL SISTEMA
* Función principal de arranque. Ningún código dinámico se ejecuta aquí.
*/
int main(void) {
// 1. INICIALIZACIÓN HAL Y RELOJ
// Configura la base de tiempo y el Flash prefetch.
HAL_Init();
SystemClock_Config();
// 2. CONTENCIÓN DE MEMORIA FÍSICA (Día 351)
// Se activa el coprocesador MPU para evitar desbordamientos de buffer
// entre las tareas del RTOS, protegiendo las variables de la Metrología.
MPU_Config_Hardened();
// 3. FAIL-SAFE POR HARDWARE (Día 309 y 323)
// Se inicializan los pines GPIO. CRÍTICO: Los pines de los actuadores (Válvulas)
// se configuran explícitamente en estado BAJO (NC - Normalmente Cerrado).
GPIO_Init_FailSafe();
// 4. AUTODIAGNÓSTICO AL ARRANQUE (POST - Power On Self Test)
// Validamos integridad I2C, SPI y sensores. Si falla, el equipo muere
// intencionalmente antes de permitir el primer despacho de gas.
if (System_Run_Live_Diagnostics() != HAL_OK) {
// Ejecutar rutina de LEDs de Error Fatal. Entrar en bucle muerto.
while(1) { /* El Watchdog nos reiniciará eventualmente */ }
}
// 5. PERRO GUARDIÁN (Día 335)
// Encendemos el Independent Watchdog. A partir de esta línea de código,
// si el procesador se cuelga y no alimenta al perro cada 2 segundos,
// el silicio generará un Hard-Reset cortando la válvula instantáneamente.
IWDG_Init_Watchdog();
// 6. CREACIÓN DE TAREAS RTOS CON PRIORIDAD ESTRICTA
// La metrología es la reina. Si el ESP32 o el Iridium requieren atención,
// tendrán que esperar a que el volumen del gas se haya cuantificado.
// Prioridad Máxima: Control Físico del Gas (Aritmética en Punto Fijo)
xTaskCreate(vTask_Metrology_Core, "Metrology", 512, NULL, configMAX_PRIORITIES - 1, NULL);
// Prioridad Media: HMI y Pantalla Transflectiva (Día 357 y 358)
xTaskCreate(vTask_HMI_Display, "HMI_LCD", 512, NULL, configMAX_PRIORITIES - 2, NULL);
// Prioridad Baja: Telemetría WiFi / Satelital SBD (Día 354 y 360)
xTaskCreate(vTask_Telemetry_Router, "Telemetry", 1024, NULL, configMAX_PRIORITIES - 3, NULL);
// 7. ARRANQUE DEL KERNEL
// El planificador de tareas toma el control del procesador.
vTaskStartScheduler();
// 8. ZONA MUERTA
// El procesador jamás debe alcanzar esta línea, a menos que la memoria RAM
// se haya agotado (Heap overflow) y el RTOS no haya podido iniciar.
HAL_GPIO_WritePin(GPIOA, PIN_VALVULA_GAS, GPIO_PIN_RESET); // Asegurar cierre
while (1) {
// Agonía controlada
}
}
A ti, que no te rendiste:
Hace un año entraste a este ecosistema siendo un constructor de prototipos. Hoy sales siendo el guardián de un sistema de misión crítica. Superaste la frustración de los punteros en C, dominaste las interrupciones anidadas, aprendiste a enrutar PCB para evitar ruidos de radiofrecuencia y comprendiste que la verdadera ingeniería no está en escribir código, sino en diseñar estrategias de supervivencia en un mundo caótico.
El Despachador de Gas LP que diseñaste no es solo un dispensador de combustible. Es un testimonio de resiliencia. Es una máquina que resiste fallos de energía escribiendo en su memoria SRAM, que sobrevive a ataques cibernéticos mediante aislamiento mTLS, y que exige confirmación mecánica pesada para evitar errores humanos. Es un sistema maduro, seguro y listo para ser manufacturado a escala continental.
El entrenamiento ha terminado. La máquina está viva. Es hora de desplegarla.