17 KiB
| 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)
- Camino de bajada hasta el MCU — que los bytes que manda el servidor lleguen a un RX del STM32.
- 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.
- 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.
- 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.
- 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
$PHLGgana campos al final (regla de solo agregar): ranura activa, versión, campaña, pedazostengo/totaly estado (bajando · lista · prueba · confirmada · regresó).- La imagen nueva arranca en prueba. El servidor la confirma con un marco
CONFIRMARdirigido al UID cuando ve la unidad sana N minutos: NMEA a 1 Hz,$PHLGcon 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 ASpor 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-VALSETen 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 luegoAT+HTTPREADpor pedazos directo a la ranura B, oAT+HTTPREADFILEal sistema de archivos del módem yAT+CFTRANTX/AT+FSREAD(manual A76XX, cap. 12, 13 y 16). TLS conAT+CSSLCFGy el certificado cargado conAT+CCERTDOWN. El tamaño libre del sistema de archivos se revisa conAT+FSMEMen 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_OFFSETyVECT_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 ejemplohbox-v56-fabrica_0.7.x.bin). Un.bin0.6.x viejo grabado en0x0800 0000borra 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:
- Seguir por USB en cada visita, como hoy. Son 33 unidades.
- Reemplazarlas por V5.6 / V5.7 conforme lleguen, si van a seguir en servicio después del primer trimestre.
- Experimento (30 min de banco, prueba F0-d): canal lateral por el F9P. Con
UBX-RXM-RTCMactivado 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. - 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#M2MWRITEen 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:
- ¿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).
- ¿Un usuario NTRIP por unidad (para inyectar solo a quien toca y saber quién está conectado)?
- ¿Quién guarda la llave de firma y dónde?
- ¿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) |