El código Bare-Metal que escribimos en la Fase 3 es estrictamente secuencial. Esto significa que la CPU procesa una tarea tras otra. Las interrupciones (ISRs) pueden robar la atención por unos microsegundos, pero al final, el procesador debe volver al Súper Bucle (Super Loop) y seguir la lista de pendientes.
La regla de oro del Súper Bucle es: Ninguna tarea debe bloquear la CPU. Si necesitas encender un actuador por 1 segundo, no puedes usar delay(1000), porque el sistema entero se congela. Tienes que usar la técnica de Polling no bloqueante: revisar la hora (SysTick), seguir haciendo otras cosas, y regresar a apagarlo cuando la hora correcta haya llegado.
Cuando te conectas a Internet, la latencia es anárquica. Le envías un comando a un chip WiFi (ESP32) para abrir un socket TCP hacia la nube. ¿Cuánto tardará la respuesta? Puede ser 10 ms, o si la red está saturada, pueden ser 3000 ms. Intentar programar esto de forma no bloqueante convierte tu código en una pesadilla insostenible de cientos de condicionales if/else. Tu código sufre de Jitter (Fluctuación): tareas críticas pierden sus plazos de tiempo (Deadlines) porque la CPU estaba ocupada atendiendo la burocracia de la red WiFi.
Ejercicio 1: Analizaremos cómo el nuevo requerimiento de IoT destruye la Máquina de Estados (FSM) que orquestamos en la fase anterior. El jefe pidió enviar un Ticket JSON mediante un módulo WiFi ESP32 conectado al puerto UART. Observa cómo el código secuencial colapsa por culpa del mundo real.
/**
* @file main_con_falla_iot.c
* @brief Demostración de colapso de un Super Loop por latencia de Red WiFi.
*/
#include "stm32f401xe.h"
#include <stdbool.h>
// ... (Inclusiones omitidas)
// Función de red asíncrona - La pesadilla del Bare-Metal
bool ESP32_Enviar_HTTP_POST(const char* json_data) {
// 1. Envía comando AT al chip WiFi
UART_Enviar_Cadena("AT+HTTPPOST=...\r\n");
// 2. PROBLEMA GRAVE: Retardo bloqueante esperando respuesta de AWS
// En el mundo real, el WiFi puede tardar hasta 3 segundos en contestar.
uint32_t timeout = 3000;
uint32_t start_time = Obtener_Milisegundos();
// El procesador se queda girando aquí inútilmente
while((Obtener_Milisegundos() - start_time) < timeout) {
if (UART_Leer_Respuesta() == "200 OK") {
return true; // ¡Se envió!
}
}
return false; // Error de red
}
int main(void) {
SystemState_t estado = SYS_STATE_IDLE;
while(1) {
// El Súper Bucle Clásico
switch(estado) {
case SYS_STATE_DISPENSING:
if (Metro_LimiteVentaAlcanzado()) {
Valvula_SetApertura(0.0f); // ¡Cierra para no derramar!
estado = SYS_STATE_FINISHED;
}
break;
case SYS_STATE_FINISHED:
// NUEVO REQUERIMIENTO: Subir a la nube
char* ticket = Crear_Ticket_JSON();
// EL COLAPSO:
// Al llamar a esta función, el STM32 se encierra en el while() de arriba
// por 3 segundos. El Súper Bucle SE CONGELA POR COMPLETO.
// Si la válvula debía cerrarse por emergencia en este lapso, no lo hará.
ESP32_Enviar_HTTP_POST(ticket);
estado = SYS_STATE_IDLE;
break;
// ... otros estados ...
}
}
return 0;
}
El ingeniero inexperto intentará arreglar esto sin FreeRTOS agregando más y más "estados" a la FSM para no bloquear la máquina simulando multitarea. El resultado es un código espagueti incomprensible y propenso a errores catastróficos.
// INTENTO DE SOLUCIÓN SIN RTOS (Máquina de Estados de Red Anidada)
// El código se vuelve ilegible, frágil e insostenible a largo plazo.
case SYS_STATE_FINISHED:
if (fase_wifi == INICIANDO) {
UART_Enviar_Cadena("AT+HTTPPOST=...\r\n");
timer_wifi = Obtener_Milisegundos();
fase_wifi = ESPERANDO_RESPUESTA;
}
else if (fase_wifi == ESPERANDO_RESPUESTA) {
// No bloqueamos, revisamos rápido y salimos del switch
if (UART_Hay_Datos()) {
if (UART_Leer_Respuesta() == "200 OK") {
fase_wifi = COMPLETADO;
estado = SYS_STATE_IDLE;
}
}
else if ((Obtener_Milisegundos() - timer_wifi) > 3000) {
// Manejo complejo de timeouts inter-ciclos
fase_wifi = ERROR;
estado = SYS_STATE_IDLE;
}
}
break;
Objetivo del día: Diagnóstico de Cuellos de Botella y Transición al IoT.
Hasta ayer, tu máquina era una joya electromecánica puramente local. Pero hoy, vivimos en la era de la Industria 4.0. Las gasolineras necesitan telemetría en vivo, gestión de flotillas en la nube (AWS/Azure) y reportes remotos. Al intentar introducir conectividad WiFi mediante un coprocesador ESP32 conectado al bus UART de tu STM32, hemos tropezado con la barrera de cristal del entorno Bare-Metal: El Bloqueo por Latencia de Red.
Si la CPU pasa milisegundos invaluables "esperando" que un servidor de la nube en el otro lado del mundo le responda que el recibo de venta fue guardado, fallará en cerrar la válvula de seguridad a tiempo si hay una emergencia, derramando Gas LP inflamable. Modificar la Máquina de Estados Finita (FSM) para manejar la red de forma asíncrona es matemáticamente posible, pero llevaría a miles de líneas de código "espagueti". La solución industrial definitiva es cambiar el motor del sistema operativo. Necesitamos un **RTOS (Real-Time Operating System)**, capaz de suspender la tarea de red de golpe para darle la CPU a las tareas críticas.