Cuando subes tu código al STM32 con el ST-Link, usas el 100% del espacio para un solo programa. Si intentaras hacer una actualización remota borrando ese espacio y escribiendo el nuevo firmware desde el WiFi, y en el minuto 2 se va la energía eléctrica en la gasolinera, tendrías un chip con medio programa viejo borrado y medio programa nuevo corrupto. La máquina jamás volvería a encender. Se convierte en un "ladrillo" (Brick).
Para lograr FOTA (Firmware Over-The-Air) seguro, debemos dividir la memoria Flash de nuestro microcontrolador en tres zonas estrictas:
Dividir la memoria no es tan fácil como partir un pastel a la mitad. La memoria Flash de los microcontroladores ARM está dividida en "Sectores" de borrado con tamaños irregulares. En el STM32F401RE (512 KB totales), los sectores son así: Cuatro de 16KB, uno de 64KB, y tres de 128KB. Nuestro trabajo como Arquitectos es agrupar estos sectores para crear particiones simétricas (o casi simétricas) sin desperdiciar silicio.
Configuración Crítica del Enlazador (Linker Script): Para que tu Firmware actual deje espacio al Bootloader, no puedes dejar que inicie en la dirección 0x08000000 como viene de fábrica. Debemos decirle al compilador GCC (en el archivo .ld) que su nuevo "Piso 0" es la dirección de Bank A (0x08004000).
Ejercicio 1: Abriremos el archivo STM32F401RETX_FLASH.ld de nuestro proyecto y modificaremos la declaración de memoria. Además, crearemos un archivo cabecera fota_map.h para que nuestro código C en el futuro sepa dónde están los límites de los bancos.
/* =======================================================
* 1. MODIFICACIÓN DEL LINKER SCRIPT (.ld)
* Archivo: STM32F401RETX_FLASH.ld
* ======================================================= */
/* --- ANTES (Configuración de Fábrica) --- */
/*
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
}
*/
/* --- DESPUÉS (Arquitectura FOTA Bank A) --- */
/* Le quitamos 16KB al ORIGIN para dejarle el Sector 0 al Bootloader.
Y reducimos el LENGTH a 240K para no invadir el Bank B. */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
FLASH (rx) : ORIGIN = 0x08004000, LENGTH = 240K
}
/**
* @file fota_map.h
* @brief Definiciones absolutas del Mapa de Memoria Dual-Bank
*/
#ifndef FOTA_MAP_H
#define FOTA_MAP_H
// =======================================================
// MAPA DE PARTICIONES (STM32F401RE - 512KB)
// =======================================================
// 1. EL BOOTLOADER (Sector 0)
// Es intocable desde la aplicación principal.
#define FOTA_BOOTLOADER_START_ADDR 0x08000000
#define FOTA_BOOTLOADER_SIZE (16 * 1024) // 16 KB
// 2. BANK A - APLICACIÓN ACTIVA (Sectores 1, 2, 3, 4, 5)
// El firmware compilado debe estar linkeado a esta dirección.
#define FOTA_BANK_A_START_ADDR 0x08004000
#define FOTA_BANK_A_SIZE (240 * 1024) // 240 KB
// 3. BANK B - ZONA DE DESCARGA OTA (Sectores 6, 7)
// Aquí guardaremos los bytes que lleguen por WiFi antes del reinicio.
#define FOTA_BANK_B_START_ADDR 0x08040000
#define FOTA_BANK_B_SIZE (256 * 1024) // 256 KB
// =======================================================
// ESTRUCTURA DE LA BANDERA DE ACTUALIZACIÓN (HEADER)
// =======================================================
// Para que el Bootloader sepa si debe copiar B hacia A, pondremos
// un "sello" mágico en los últimos bytes del Bank B.
#define FOTA_MAGIC_WORD_PENDING 0xDEADBEEF
#define FOTA_MAGIC_WORD_DONE 0x00000000
// La firma de actualización residirá en la última palabra (4 bytes) de la Flash total.
#define FOTA_FLAG_ADDRESS (0x08080000 - 4)
#endif // FOTA_MAP_H
Objetivo del día: Ciclo de Vida del Producto (Lifecycle Management) y Zero Downtime.
En el modelo clásico de sistemas embebidos, cuando actualizas un firmware, detienes la máquina, borras la memoria, escribes el nuevo código y reinicias. Durante esos 3 a 5 minutos, la gasolinera no puede vender gas (Downtime). Peor aún, si la descarga por WiFi falla o se corta a la mitad, la máquina se destruye.
Al diseñar este **Mapa de Memoria Dual-Bank**, has implementado actualizaciones de Zero Downtime (Cero Tiempo de Inactividad). Cuando AWS empuje un nuevo firmware en el futuro, tu Despachador seguirá operando desde el **Bank A**, cerrando válvulas y cobrando dinero, mientras la Tarea WiFi va descargando pedacito a pedacito la actualización y escribiéndola en el **Bank B** (una zona inactiva y segura). Si el WiFi se cae, no pasa nada, la máquina sigue viva. Solo cuando se ha descargado el 100% y el cálculo matemático de integridad (CRC) coincide, la máquina se reinicia. El Bootloader despierta, detecta el "Sello Mágico" en el Bank B, copia la actualización al Bank A en menos de 2 segundos, y la máquina regresa a la vida evolucionada. El riesgo operativo y el costo de mantenimiento se reducen literalmente a cero.
0x08000000). Su trabajo exclusivo es verificar la integridad del Bank B; si detecta una actualización válida pendiente, copia los bytes de B hacia A, y finalmente hace un salto de puntero (Jump) hacia la dirección 0x08004000 para arrancar el sistema operativo principal..ld)** en el compilador GCC, cambiando el atributo ORIGIN de la FLASH para que las direcciones de memoria de las funciones y variables calcen perfectamente con la nueva ubicación física.