Drogheda/02-Architecture-Software/2026-10-22_Drogheda_FOTA-por-4G_Factibilidad_ES_v1.0.md

17 KiB
Raw Blame History

title date
FOTA por 4G: qué hace falta y en qué tarjetas se puede 2026-10-22

FOTA por 4G — actualizar el firmware por el módem, tarjeta por tarjeta

22-oct-2026 · Claude, a pedido de Leo · v1.0. Pregunta: ¿qué hace falta para mandar actualizaciones de firmware por el módem 4G, y se puede en todas las versiones de la tarjeta?

Fuentes revisadas: board_v4.h, board_v5.h, board_v56.h y hbox_v5_bringup.ino (firmware 0.6.3), mapa de pines de la v6, el diagnóstico del 4G NTRIP Master del 8-oct (protocolo de su herramienta de carga), los binarios publicados (0.6.2 = 96 180 bytes) y el manual AT de la serie A76XX de SIMCom.

0. Veredicto

Tarjeta Unidades ¿FOTA por 4G? Por qué Qué falta
V3 (Blackpill en zócalo) 3 en campo No El MCU no recibe nada del módem: la salida del 4G NTRIP Master (DOUT) va solo al RX2 del F9P. El Blackpill (48 pines) ni siquiera tiene PC7. Seguir por USB en visita, o reemplazar
V4 (Blackpill en zócalo) 15 No Igual que la V3. Igual
V5.5 15 No PC7 está sin conectar (board_v5.h: «PC6..PC9 NC»); la toma RTCM llegó con la V5.6 (ECO del 27-sep). Tampoco controla el módem (solo SW4G1 o 24 V lo reviven). Igual
V5.6 / V5.7 108 + 322 (más el piloto de 5 + 5) Sí, sin tocar cobre Bajada: PIN_RTCM_TAP PC7 = USART6_RX ← R111 1 k ← DOUT_4G, a 115200. Subida: Modo B (PA9 → K1 NO → DIN_4G), por donde ya viaja $PHLG. Control del módem: MODEM_EN PC3, MODEM_RST PC1. Respaldo LTC4040 para escribir flash. Firmware (bootloader + receptor) y servidor (caster con inyección + campañas)
v6 130 + reemplazos Sí, la más limpia El MCU es dueño del A7670SA (PC6 → R148 0 Ω → RXD; PC7 ← TXD; K1 DNP): descarga por HTTPS con los comandos AT del propio módem. Va dentro de FW-3 (NTRIP por AT), que todavía no existe

Lo que decide el costo es la imagen que se graba en fábrica. Una unidad que sale de Querétaro sin bootloader y sin receptor solo se actualiza después con una visita y un cable USB, aunque su hardware pueda. Por eso la propuesta D-22-6 (§9): la imagen de fábrica de las 108 / 322 y de las 130 v6 lleva el bootloader A/B y el receptor desde el primer día. Los pilotos (5 + 5 y los 20 de la v6) no lo necesitan: se regraban por USB en el banco.

1. Qué hace falta para actualizar por aire (cualquier tarjeta)

  1. Camino de bajada hasta el MCU — que los bytes que manda el servidor lleguen a un RX del STM32.
  2. Camino de subida — que la unidad diga qué versión tiene, qué pedazos le faltan y si la imagen nueva arrancó bien. Sin esto el servidor manda a ciegas.
  3. Lugar en flash + bootloader — dos ranuras: corre una y se escribe la otra; el bootloader elige cuál arranca y regresa a la anterior si la nueva falla.
  4. Imagen firmada — la imagen pasa por el caster y por internet; sin firma, quien pueda meter bytes en el flujo puede regrabar la flota completa.
  5. Energía y recuperación — un corte a media escritura no debe dejar la unidad muerta (con dos ranuras no pasa: se escribe la que no corre), y siempre queda el DFU por USB en J11, que vive en la memoria de sistema del STM32 y no se puede borrar. En el peor caso una unidad requiere visita; nunca queda inservible.

El STM32F411 (RET6 en V5.x y v6, CEU6 en el Blackpill) tiene 512 KB de flash y el firmware 0.6.2 pesa 96 KB: caben dos ranuras con margen aunque el 0.7.x crezca (Ethernet, SC16IS752, ciclo de respaldo).

2. Lo que tiene cada tarjeta

V3 / V4 V5.5 V5.6 / V5.7 v6
Módem 4G NTRIP Master (Telit + app de ArduSimple) igual igual A7670SA soldado
Bajada hacia el MCU ✗ ✗ (PC7 sin conectar) ✓ PC7 toma RTCM, 115200 ✓ PC7 USART6_RX
Subida desde el MCU Modo B (PA9 → K1) Modo B Modo B PC6 directo (R148)
Control del módem ✗ ✗ MODEM_EN PC3 · MODEM_RST PC1 · MODEM_LED PC2 MODEM_PWR_EN PC10 · RST PC11 · PWRKEY PC8 · STATUS PC9
Si el MCU se muere K1 NC: NMEA y RTCM siguen pasando igual igual Nada reporta (K1 DNP, decisión B-13)
Flash 512 KB 512 KB 512 KB 512 KB

3. V5.6 / V5.7: FOTA a través del caster

3.1 La idea

El 4G NTRIP Master es un cliente NTRIP: lo que el caster manda después del encabezado sale por DOUT a 115200 hacia el RX2 del F9P y hacia PC7 (por R111). Si el caster es nuestro, puede intercalar entre los mensajes de corrección marcos RTCM 3 propios (un número de mensaje del rango propietario 4001–4095 que no use nuestra base) con pedazos de la imagen:

  • El F9P los descarta: es un tipo que no usa, y cada marco lleva su CRC-24Q. Se confirma en banco que el RTK no se mueve (prueba F0-b).
  • El MCU arma los marcos que ve en PC7, se queda con los suyos y escribe cada pedazo en la ranura que no corre.
  • No cambia nada en el módem ni en sus parámetros: mismo caster, mismo mountpoint.

Formato de cada marco (propuesta): D3 · longitud · tipo 4xxx (12 bits) + subtipo (4 bits) · campaña (2 B) · tarjeta (1 B) · destino (UID del MCU, o 0 = todas) · pedazo n / total · datos ≤ 900 B · CRC-24Q. El primer marco de cada campaña es el manifiesto: versión, tarjeta (V5.6 y V5.7 usan el mismo binario), ranura, tamaño, SHA-256 y firma Ed25519.

3.2 Carrusel y números

  • La línea DOUT da 11.5 KB/s (115200 8N1) y las correcciones ocupan una fracción. Con el carrusel limitado a 1 KB/s, 100 KB pasan en ≈ 2 min por vuelta.
  • Una unidad que se conecta a medio carrusel completa lo que le falta en la vuelta siguiente; los pedazos que se pierden (el loop del MCU bloqueado unos segundos, una reconexión LTE) se recuperan igual. Para no depender del loop, el receptor lee USART6 por DMA circular.
  • Datos por unidad y campaña: ≈ 0.1–0.3 MB (la imagen de 1 a 3 veces). Si el caster inyecta solo en las conexiones de las unidades objetivo, el resto de la flota no gasta nada. Para eso conviene un usuario NTRIP por unidad (AS+U), que además dice quién está conectado.

3.3 Subida y confirmación

  • $PHLG gana campos al final (regla de solo agregar): ranura activa, versión, campaña, pedazos tengo/total y estado (bajando · lista · prueba · confirmada · regresó).
  • La imagen nueva arranca en prueba. El servidor la confirma con un marco CONFIRMAR dirigido al UID cuando ve la unidad sana N minutos: NMEA a 1 Hz, $PHLG con la versión nueva y RTK ≥ 4 si la unidad lo tenía antes. Sin confirmación en 30 min, o con 3 reinicios seguidos, el bootloader regresa a la ranura anterior.
  • En V5.x, si la imagen nueva se cuelga, el IWDG (16 s) reinicia y K1 cae a NC: la unidad sigue reportando posición mientras tanto (invariante 2).

3.4 Escribir la flash sin perder posiciones

Borrar un sector de 128 KB detiene al núcleo ≈ 1–2 s (el F411 tiene un solo banco). El firmware ya suelta K1 antes de escribir flash (relayDisengage("flash_write")), así que la NMEA sigue directo por K1 NC y solo se pausa $PHLG. La ranura B son dos sectores de 128 KB: se borran al empezar la campaña, no a media descarga. No se escribe flash en batería baja (mismo umbral del gobernador de carga).

3.5 Lo que sale de regalo con el mismo camino

  • Parámetros del 4G NTRIP Master a distancia. El MCU puede mandar $$$AS+X=… por el Modo B: la app los acepta mientras corre y contesta $GPTXT,… STORED AS por DOUT → PC7 (prueba F0-c). Cambiar caster, mountpoint o APN sin visita, con regreso automático a los valores anteriores si no llegan correcciones a PC7 en N minutos (con MODEM_RST para aplicarlos). El archivo real de parámetros sigue sin ir al repo ni al sitio.
  • Configuración del F9P a distancia. El MCU habla con el UART1 del F9P (PA2/PA3): UBX-CFG-VALSET en RAM, BBR y flash. Cierra la clase de fallas «configuración solo en RAM» del 20-jun.
  • Comandos: reiniciar el módem, ciclar la etapa, pedir un volcado de diagnóstico.

4. v6: FOTA por HTTPS con el A7670SA

  • Sin 4G NTRIP Master, el MCU maneja el módem por AT: AT+HTTPINIT / AT+HTTPPARA / AT+HTTPACTION, y luego AT+HTTPREAD por pedazos directo a la ranura B, o AT+HTTPREADFILE al sistema de archivos del módem y AT+CFTRANTX / AT+FSREAD (manual A76XX, cap. 12, 13 y 16). TLS con AT+CSSLCFG y el certificado cargado con AT+CCERTDOWN. El tamaño libre del sistema de archivos se revisa con AT+FSMEM en el banco.
  • 100 KB por el UART a 115200 son ≈ 10 s más el protocolo AT; el enlace LTE no es el cuello de botella.
  • Con FW-3 como está planeado (el MCU entrega el RTCM al F9P por USART2), el canal AT queda libre para HTTP mientras corre NTRIP si el socket NTRIP se lee en modo no transparente (lectura manual del socket). Eso se decide al escribir FW-3, no después.
  • El firmware del propio A7670SA también se actualiza por aire (AT+CFOTA, paquetes delta de SIMCom). No es urgente.
  • Sin K1, si el MCU de la v6 se muere nada reporta. Por eso en la v6 el regreso a la imagen anterior lo decide el bootloader solo (contador de arranques + IWDG), sin esperar al servidor, y lo primero que hace la app nueva es levantar el enlace.
  • El manifiesto firmado lleva la tarjeta: el bootloader rechaza un binario de V5.6 en una v6 y al revés. Eso cubre el riesgo de D-08 (un build de V5.6 pone PC3 en alto contra el RTK_STAT del F9P) mejor que un strap.

5. Bootloader y mapa de flash (V5.6, V5.7 y v6)

Sectores Dirección Tamaño Uso
0–1 0x0800 0000 32 KB Bootloader (nunca se actualiza por aire)
2 0x0800 8000 16 KB Metadatos: ranura activa, estado de prueba, versión, hash (dos copias alternadas)
3 0x0800 C000 16 KB EEPROM emulada (hoy vive en el último sector; se mueve aquí)
4–5 0x0801 0000 192 KB Ranura A
6–7 0x0804 0000 256 KB Ranura B
  • Dos builds por versión, uno por ranura. STM32duino acepta un desplazamiento de flash (build.flash_offset → LD_FLASH_OFFSET y VECT_TAB_OFFSET); se confirma con un build de prueba en la Mac. El servidor manda el de la ranura que no corre (la unidad la reporta en $PHLG). No se copia ni se intercambia nada: cambiar de imagen es escribir un registro de metadatos, y regresar es inmediato.
  • Bootloader mínimo: deja los pines en estado seguro (PB5 bajo = K1 NC, etapa apagada: invariante 1), verifica SHA-256 + Ed25519 (Monocypher), cuenta los arranques en prueba en BKP12R–BKP13R (libres: el firmware usa BKP16–19 y el núcleo BKP1, BKP4 y BKP10), refresca el IWDG mientras verifica y salta.
  • La app nunca escribe por debajo de su ranura (guardia en el código). La protección por option bytes (WRP) de los sectores 0–1 se evalúa después del piloto: complica el regrabado por DFU de los técnicos.
  • BOR del STM32 en nivel 2 o 3 (option bytes) para no escribir flash con voltaje bajo; revisar el valor actual.
  • Imagen de fábrica: un solo .bin (bootloader + ranura A + metadatos) que se graba por DFU en J11 igual que hoy, con la tarjeta en el nombre (por ejemplo hbox-v56-fabrica_0.7.x.bin). Un .bin 0.6.x viejo grabado en 0x0800 0000 borra el bootloader: en V5.6, V5.7 y v6 solo se graban imágenes de fábrica.
  • La llave privada de firma no va al repo ni al servidor (invariante 6): la guarda Leo; el servidor solo tiene imágenes ya firmadas.

6. V3 / V4 / V5.5: por qué no y qué hacer

El MCU de estas tarjetas no tiene ningún RX conectado a la salida del módem. Opciones, de más a menos recomendada:

  1. Seguir por USB en cada visita, como hoy. Son 33 unidades.
  2. Reemplazarlas por V5.6 / V5.7 conforme lleguen, si van a seguir en servicio después del primer trimestre.
  3. Experimento (30 min de banco, prueba F0-d): canal lateral por el F9P. Con UBX-RXM-RTCM activado en su UART1, el F9P le reporta al MCU (PA3) el tipo de cada marco RTCM que recibe; hasta donde sé lo hace también con tipos que no soporta (por confirmar). Un servidor que manda marcos mínimos de 64 tipos distintos deletrea 6 bits por marco: a ≈ 100 marcos/s son ≈ 75 B/s, o sea 100 KB en ≈ 25 min más reenvíos. Sirve para comandos y quizá para FOTA lenta, pero igual pide una visita para grabar bootloader y receptor, y hay que probar que el RTK no sufre. Solo vale la pena si V4 / V5.5 se quedan mucho tiempo en campo.
  4. Cable en la V5.5 (DOUT_4G → 1 k → PC7, pin 38 del LQFP64 a 0.5 mm): posible en banco, no recomendado para equipo en puerto (vibración).

7. Lo que no se actualiza por aire en ninguna tarjeta

  • El firmware del ZED-F9P (herramienta de u-blox por USB o UART, en sitio; en la v6, por el puente de J11).
  • La app del 4G NTRIP Master (m2mapz.bin, 643 KB): no cabe en el MCU y el módulo queda fuera de línea mientras se carga (AT#M2MWRITE en su ventana de arranque). Sus parámetros sí se pueden cambiar (§3.5).
  • El bootloader, por diseño.

8. Riesgos y mitigaciones

Riesgo Mitigación
Imagen mala a toda la flota Campañas por etapas: 1 unidad de banco → 1 por sitio → 10 % → todas; confirmación del servidor; regreso automático
Imagen que arranca pero tumba el enlace Confirmación de extremo a extremo (el servidor ve la versión nueva reportando); sin ella, regreso a los 30 min
Alguien inyecta una imagen Firma Ed25519; la llave privada fuera del servidor
Binario de otra tarjeta Tarjeta dentro del manifiesto firmado; el bootloader lo rechaza
Se cae el caster propio Ya es punto único de las correcciones; el inyector va aparte del relevo, así que si el inyector falla las correcciones siguen
El carrusel estorba al RTK Límite de 1 KB/s, marcos completos entre mensajes de la base; prueba F0-b
Corte de energía a media campaña Se escribe la ranura que no corre; la descarga se reanuda por pedazos
El borrado de flash detiene el núcleo K1 suelto durante el borrado (ya es regla del firmware); borrado al inicio de la campaña
Datos de la SIM 0.1–0.3 MB por unidad y campaña, solo a las unidades objetivo
Un técnico graba un .bin viejo En V5.6+ solo imágenes de fábrica, con la tarjeta en el nombre

9. Esfuerzo, orden y decisión

Pieza Quién Estimado
F0 — pruebas rápidas de banco (§10) Jesús + Claude ½ día
F1 — bootloader, mapa de flash, firma e imagen de fábrica Claude 4–5 días
F2 — receptor V5.6 / V5.7 (PC7, ranura B, $PHLG, confirmación y regreso) Claude 4–5 días
F3 — caster con inyección por unidad + campañas en htracker + vista en el monitor Gibran + Claude 5–7 días
F4 — matriz de banco (corte en cada fase, imagen corrupta, tarjeta equivocada, imagen que no arranca, imagen que tumba el enlace, en batería, RTK con carrusel) Jesús + Claude 3–4 días
F5 — v6: HTTPS dentro de FW-3 Claude 2–3 días sobre FW-3

Son ≈ 3 semanas de calendario con dos personas en paralelo. No entra en el 0.7.0 (vence el 29-oct) para no moverlo. Sí alcanza para las 108 / 322: tienen NO-GO hasta que el piloto pase el banco, esperan el pago, y su imagen de fábrica se graba al ensamblar.

D-22-6 (propuesta; decide Leo). (1) La imagen de fábrica de las 108 V5.6, las 322 V5.7 y las 130 v6 lleva bootloader A/B firmado y receptor FOTA, y no se graban sin que F4 pase en banco. (2) En V5.6/V5.7 el transporte es el caster de Helgen con inyección; en la v6, HTTPS dentro de FW-3. (3) V3, V4 y V5.5 se quedan con actualización por USB en visita; el experimento F0-d decide si vale la pena más.

Preguntas abiertas para Leo:

  1. ¿Qué software corre hoy el caster de HelgenSRV? Si es nuestro, se le agrega el inyector; si es de terceros, se pone un relevo propio enfrente (base → relevo → unidades).
  2. ¿Un usuario NTRIP por unidad (para inyectar solo a quien toca y saber quién está conectado)?
  3. ¿Quién guarda la llave de firma y dónde?
  4. ¿Cuánto tiempo siguen en campo las V4 y V5.5?

10. Pruebas rápidas de banco (F0)

Prueba Pasa si
a Caster de prueba en HelgenSRV (otro mountpoint) que intercala un marco 4xxx propio cada segundo; unidad de banco apuntada a él El marco sale íntegro por DOUT (USB-serie en el pin 2 del XBee de cualquier V4/V5.5 de banco, o PC7 en una V5.6 del piloto)
b Carrusel a 1 KB/s durante 30 min con cielo abierto Fix 4 sostenido; UBX-RXM-RTCM sin fallas de CRC en los mensajes de la base
c $$$AS+R? mandado por el Modo B (MCU → K1 → DIN) La respuesta de la app aparece en DOUT
d Marcos de tipos que el F9P no soporta, con UBX-RXM-RTCM activado en UART1 El F9P los reporta (decide el experimento de §6)