IoT-Link · LevelStream · Bring-up matériel

Mise à jour OTA bloquée sur les prototypes M10

Analyse du bootloader, des deux pannes observées sur le terrain, des causes probables et des pistes de durcissement — appuyée sur le code source et la documentation u-blox.

Modem : u-blox SARA-R422M10S (FW 01.24) Bootloader : v0.1.9 MCU : STM32L412 Mis à jour : 23 juin 2026

En deux minutes

  • La mise à jour OTA échoue par intermittence sur les M10, toujours au même endroit : juste après le message Starting PDP, au moment d'ouvrir la connexion de données.
  • Deux visages d'un même problème : « no network service » au redémarrage aimant d'une sonde en service, et « operation not allowed » au premier allumage d'une carte neuve.
  • Cause de fond : le bootloader engage la phase de données avant que la pile réseau du modem ne soit prête, et il force AT+CGACT=1,1 — une activation explicite du contexte PDP, redondante en LTE-M où ce contexte s'active tout seul à l'attachement.
  • Point clé : le bootloader sait déjà refaire un cycle propre, mais il ne réessaie que dans un cas particulier. C'est pourquoi il faut aujourd'hui un power-off manuel — impossible sur une sonde montée.

1 Contexte & portée

Deux pannes de la chaîne OTA ont été observées au bring-up des prototypes M10 (modem u-blox SARA-R422M10S).

Ce document les décrit, propose un diagnostic appuyé sur la lecture du code et la documentation u-blox, distingue ce qui est vérifié de ce qui reste hypothèse, et liste les mesures et les tests à mener.

Méthode & honnêteté

L'analyse est statique : lecture du code source du bootloader (branche à jour, v0.1.9) et de la documentation u-blox. Elle n'a pas encore été confrontée à une trace réseau réelle ni à une mesure électrique. Les conclusions sont donc graduées (vérifié / probable / à tester), et la section Tests est conçue précisément pour lever les incertitudes avant de figer un correctif.

2 Le mécanisme OTA, étape par étape

À chaque démarrage, le bootloader exécute toujours la même séquence avant de passer la main à l'application.

  1. Allumage du modem Mise sous tension et séquence de power-on.
  2. Initialisation & attente d'enregistrement réseau Le modem doit être enregistré sur le réseau avant d'aller plus loin.
  3. Lecture de l'IMEI Identifiant unique utilisé pour interroger le serveur.
  4. Ouverture du contexte de données — « Starting PDP » C'est ici que se produisent les deux pannes. (La trace « Starting PDP » n'apparaît qu'en build verbeux APP_VERBOSE.)
  5. Connexion au serveur & comparaison de checksum Téléchargement du checksum de référence pour cet IMEI, comparaison avec le firmware déjà flashé, mise à jour si différence.

La séquence est lisible telle quelle dans la boucle principale du bootloader :

application.cApplication_Loop — lignes 416-470 (abrégé)
// 1. Power on SARA_R422
ret = SARA_R422_Power_On(&appdata->SARA_R422);
// 2. Initialize SARA_R422  (inclut l'attente d'enregistrement réseau)
ret = SARA_R422_Init(&appdata->SARA_R422);
// 3. Read and store IMEI
ret = SARA_R422_Get_IMEI(&appdata->SARA_R422, appdata->IMEI, ...);
debug_print("[DEBUG]Starting PDP...\r\n");
// 4. SARA R422 PDP activate  <-- POINT DE PANNE
ret = SARA_R422_PDP_Connect(&appdata->SARA_R422, APN);
// 5. Enable HTTP, puis GET du checksum, comparaison, upgrade...

L'ouverture du contexte (étape 4) repose sur ces deux commandes :

SARA_R422.cSARA_R422_PDP_Connect — lignes 809-842 (abrégé)
// Configure PDP Context
sprintf(buf, "AT+CGDCONT=1,\"IP\",\"%s\"\r\n", Apn);   // APN = "tsiot"
ret = SARA_R422_Execute_Cmd(SARA_R422, buf);
...
// Enable PDP Context
ret = SARA_R422_Execute_Cmd(SARA_R422, "AT+CGACT=1,1\r\n");   // <-- commande qui échoue

3 Les deux symptômes observés

Deux pannes distinctes, deux codes d'erreur différents — mais exactement la même zone de code, juste après Starting PDP.

Symptôme A — sonde en service

+CME ERROR: no network service CME 30
Déclencheur
Redémarrage par l'aimant.
Fréquence
Intermittent, ~2 fois sur 3.
Contournement
Un power-off complet puis redémarrage fonctionne.
Enjeu terrain
Une sonde montée ne peut plus être éteinte — seul l'aimant reste disponible.

Symptôme B — carte neuve

+CME ERROR: operation not allowed CME 3
Déclencheur
Tout premier allumage d'une carte jamais utilisée.
Fréquence
~2 fois sur 3 ; le BL « ne va pas plus loin ».
Contournement
Power-off + redémarrage aimant fonctionne à tous les coups.
Constat terrain

Les observations de terrain convergent : la phase qui suit l'ouverture du contexte de données (« Starting PDP ») se comporte de façon instable. C'est le cœur du diagnostic ci-dessous.

Le symptôme B (« operation not allowed », carte neuve) s'explique très probablement par un provisioning de première fois du modem : au tout premier allumage, le module doit initialiser la SIM/eSIM, faire sa première sélection d'opérateur et son premier attachement réseau. Tant que ce n'est pas terminé, une commande de données est refusée. Le deuxième démarrage réussit parce que le premier a amorcé ce provisioning — pas parce que la coupure d'alimentation aurait « nettoyé » quoi que ce soit. Le manuel AT définit d'ailleurs le code 3 comme « the MT is in a state which does not allow performing the entered command » (p. 48) — soit exactement « pas prêt pour cette commande ».

4 La racine commune

Dans les deux cas, le bootloader engage la phase de données alors que la pile réseau du modem n'est pas encore totalement prête — sans mécanisme robuste d'attente ou de nouvel essai à cet endroit.

Le levier choisi pour ouvrir la connexion est AT+CGACT=1,1, une commande standard (3GPP TS 27.007) d'activation explicite du contexte PDP, héritée du modèle GPRS où le contexte devait être activé à la main. Or :

Documentation u-blox — contexte PDP en LTE-M

Le manuel des commandes AT le pose noir sur blanc : « The initial EPS bearer established during LTE attach procedure is actually a default EPS bearer. » Le contexte de données par défaut (cid 1) est donc monté par l'attachement réseau lui-même. Forcer ensuite AT+CGACT=1,1 est redondant — et c'est la première commande de données émise, celle qui échoue dès que l'attachement n'est pas tout à fait terminé.

Réf. : LEXI-R4 / SARA-R4 series — AT commands manual (UBX-18068860, R31), chap. 13 « PDP contexts » p. 190 ; +CGACT §13.7 p. 201, +CGPADDR §13.9 p. 205.

Autrement dit, le code force une étape que le réseau fait déjà de lui-même, et l'émet au moment le plus fragile. Les deux codes d'erreur (« no network service » et « operation not allowed ») ne sont que deux façons, pour le modem, de dire « je ne suis pas prêt pour ça maintenant ».

5 Une fausse piste, écartée en toute transparence

Une première intuition — « le redémarrage aimant rallume le modem trop vite, il faut forcer un cycle d'alimentation plus propre » — ne résiste pas à la lecture du code.

Le bootloader force déjà un power-off complet à chaque échec. En fin de boucle, il coupe proprement le modem puis met la carte en veille profonde 5 minutes, alimentation modem coupée :

main.cboucle principale — lignes 112-123
while (1)
{
  ret = Application_Loop(&appdata);
  Modem_Reset(&appdata);                      // coupe proprement le modem (voir ci-dessous)
  // If an error occured, sleep to retry
  if (ret < 0 && appdata.FwIsConsistent != 1)
      Sleep(SLEEP_DURATION_SEC);             // 300 s = 5 min, alim modem coupée
  else
      Jump_To_App(&appdata);                 // démarre l'application
}
SARA_R422.cSARA_R422_Power_Off — lignes 422-458 (abrégé)
SARA_R422_Execute_Cmd(SARA_R422, "AT+CPWROFF\r\n");      // extinction logicielle
...
ret = SARA_R422_Wait_Powered(SARA_R422_AT_SUPPLY_OFF_DELAY, GPIO_PIN_RESET); // attend que VINT retombe — modem réellement OFF (2000 ms)
...
HAL_GPIO_WritePin(SARA_R422_POWER_SUPPLY, GPIO_PIN_RESET);  // coupe l'alimentation

Le firmware refait donc déjà, tout seul, l'essentiel de ce qu'un power-off manuel accomplit : coupure de l'alimentation modem + rail coupé 5 minutes + redémarrage à froid. « Forcer un cycle propre » est donc largement redondant — ce n'est pas là qu'est la solution. Cette correction est assumée : mieux vaut écarter une fausse piste que de coder un faux remède.

6 Le vrai trou : un nouvel essai conditionné au mauvais critère

Si le bootloader sait refaire un cycle propre, pourquoi faut-il quand même une intervention humaine ?

Parce que ce nouvel essai automatique ne se déclenche que si le firmware interne est jugé « non cohérent ». La condition exacte (revoir l'extrait section 5) est :

Ce qui ne va pas

if (ret < 0 && FwIsConsistent != 1) → Sleep(300s) ; else → Jump_To_App

Si le firmware en place est cohérent (FwIsConsistent == 1), un échec de connexion ne déclenche aucun nouvel essai : le bootloader démarre l'application et la tentative OTA est silencieusement abandonnée jusqu'au prochain redémarrage. C'est précisément ce qui oblige aujourd'hui à un power-off manuel.

Conséquence terrain — critique

Sur une sonde déjà montée, le power-off manuel est impossible. Sans nouvel essai interne de la phase de données, la mise à jour OTA peut donc tout simplement ne jamais aboutir, même si le réseau redevient disponible quelques secondes plus tard.

Le correctif en découle directement : il faut un nouvel essai de la phase de données, indépendant de la cohérence du firmware — c'est l'automatisation du geste manuel « power-off + redémarrage » constaté sur le terrain.

7 Ce que dit la documentation u-blox

Plusieurs recommandations du fabricant convergent vers le même constat : la séquence actuelle est conçue « à l'ancienne » et mérite d'être alignée sur les bonnes pratiques Cat-M1.

Ce que disent les manuelsImplication pour le bootloader
Le bearer EPS par défaut est établi par la procédure d'attachement LTE (manuel AT, p. 190).Forcer AT+CGACT=1,1 est redondant en Cat-M1 — le contexte est déjà monté par l'attachement.
AT+CGPADDR lit l'adresse IP attribuée au contexte (manuel AT, §13.9, p. 205).Vérifier l'obtention d'une IP (lecture non destructive) plutôt qu'activer le contexte de force.
+CEREG et son URC (AT+CEREG=2, avec TAC/cell-id) sont documentés pour le SARA-R422M10S (manuel AT, §13.14, p. 214-216).Suivre l'enregistrement par URC est plus fiable et plus sobre que le polling actuel toutes les 500 ms.
« VCC supply can be removed only after V_INT goes low » — sinon « unrecoverable faulty state » (System Integration Manual, p. 32).Déjà respecté à l'extinction ; en revanche le power-on ne confirme pas l'extinction avant de réalimenter (voir §8).
Sources

Références vérifiées dans les deux documents u-blox de référence : le LEXI-R4 / SARA-R4 series — AT commands manual (UBX-18068860, R31) et le SARA-R4 series — System Integration Manual (UBX-16029218, R32). Les pages sont citées au fil du texte.

8 Points à améliorer (par ordre de priorité)

Ce sont des spécifications. Elles vont du correctif direct du symptôme aux durcissements de fond.

① Remplacer l'activation forcée par une vérification d'IP priorité haute

Au lieu de AT+CGACT=1,1 (la commande qui échoue), interroger AT+CGPADDR en boucle jusqu'à obtenir une adresse IP valide (≠ 0.0.0.0), avec un délai généreux. C'est une lecture non destructive, conforme au LTE-M, et valable quelle que soit la cause. → Le meilleur correctif unique si on ne devait en faire qu'un.

SARA_R422.cSARA_R422_PDP_Connect — proposition (remplace la ligne 831)
// AVANT (à retirer) :
// AT+CGACT=1,1   -> "+CME ERROR: ..." si l'attachement n'est pas prêt

// APRÈS : attendre que le réseau ait attribué une IP (le contexte s'active seul en Cat-M1)
do {
    SARA_R422_Execute_Cmd(SARA_R422, "AT+CGPADDR=1\r\n");
    // lire "+CGPADDR: 1,<ip>"  -> succès si ip != 0.0.0.0
} while (ip_invalide && !timeout);

② Ajouter un nouvel essai de la phase de données, indépendant de FwIsConsistent priorité haute

Autour de l'appel à SARA_R422_PDP_Connect (application.c, lignes 462-470), prévoir 2 à 3 tentatives qui rejouent un cycle radio propre avant d'abandonner : AT+CFUN=0 puis AT+CFUN=1 force un nouvel attachement sans redémarrage complet. C'est l'automatisation du power-off manuel — la mesure la plus importante pour le terrain (sondes montées).

③ Attendre la disponibilité réelle de la donnée avant de l'utiliser durcissement

L'attente actuelle valide l'enregistrement réseau, mais rien ne garantit ensuite que le service paquet est prêt avant d'émettre la première commande de données. Vérifier explicitement l'attachement paquet (AT+CGATT? = 1) — et idéalement passer l'enregistrement en notification URC (AT+CEREG=2) — comble cet écart.

④ Reprendre la main sur la sélection d'opérateur au démarrage cas carte neuve

Pour le symptôme B, démarrer en mode « déconnecté » puis déclencher l'enregistrement de façon explicite évite que le bootloader ne tire des commandes de données pendant que le modem fait encore son provisioning de première fois.

⑤ Renforcer le power-on — seulement si les tests le prouvent dernier recours

Au power-on, la décharge avant réalimentation repose sur de simples temporisations aveugles (1 s avant réalimentation, 1 s après), sans jamais vérifier que le modem est réellement éteint :

SARA_R422.cSARA_R422_Power_On — lignes 394-420 (extrait abrégé)
HAL_GPIO_WritePin(SARA_R422_PWR_ON, GPIO_PIN_RESET);        // (L399)
HAL_GPIO_WritePin(SARA_R422_POWER_SUPPLY, GPIO_PIN_RESET);  // coupe l'alim (L400)
// Wait capacitors to discharge
HAL_Delay(SARA_R422_SUPPLY_ON_DELAY);                       // 1000 ms AVEUGLE, pas de contrôle VINT (L403)
HAL_GPIO_WritePin(SARA_R422_POWER_SUPPLY, GPIO_PIN_SET);    // réalimente (L406)
HAL_Delay(SARA_R422_SUPPLY_ON_DELAY);                       // encore 1000 ms aveugle (L407)

On pourrait attendre le passage à l'état bas de VINT (la primitive existe déjà) et allonger la marge de décharge — la règle u-blox « couper VCC seulement après VINT bas » figure au System Integration Manual, p. 32. Mais : comme le bootloader fait déjà un power-off complet au nouvel essai (§5), ce renforcement n'apporterait, au mieux, qu'un gain de temps au premier démarrage — et rien du tout si la cause réelle est ailleurs (radio, couverture, provisioning). À ne coder que si l'instrumentation prouve que le premier démarrage incomplet est bien en cause.

9 Tests à mener (avant de figer un correctif)

L'analyse est statique. Une instrumentation légère tranchera entre les causes possibles et confirmera (ou non) chaque hypothèse.

Instrumentation à ajouter

Faire enregistrer par le bootloader, juste avant l'ouverture du contexte de données et en numérotant le passage (1er démarrage / nouvel essai n°…) :

À capturerCe que ça révèle
AT+CMEE=2 (absent du code — à activer)Affiche le numéro d'erreur exact (3 vs 30)
Quelle commande échoue : CGDCONT (L814) ou CGACT (L831)Localise précisément le point de rupture
AT+CEREG?Enregistré / en recherche / refusé
AT+CGATT?Service paquet attaché ou non
AT+CSQQualité du signal (99 = pas de signal → piste radio)
AT+CGPADDRUne IP est-elle déjà attribuée ?
Le test décisif

Faire au moins 10 à 15 redémarrages aimant et regarder si l'échec persiste au deuxième passage automatique (après les 5 minutes de veille) :

  • S'il disparaît tout seul au second passage → c'est bien un problème de premier démarrage / décharge.
  • S'il persiste malgré un cycle complet → la cause est ailleurs (radio, couverture, eSIM) — inutile de toucher à l'alimentation.

Table de décision

ObservationCause probableCorrectif visé
CSQ bon + CEREG 1/5 mais CGACT KOContexte data / commande inadaptée① CGPADDR
CSQ=99 ou CEREG 0/2 persistantRadio / couverture / eSIM④ COPS, pas l'alim
Échec disparaît au 2e passagePremier démarrage incomplet⑤ power-on (et ② retry)
Erreur dès CGDCONT sur carte neuveProvisioning non terminé② retry + ④ COPS

Checklist

  • Activer AT+CMEE=2 et recompiler en mode verbeux.
  • Instrumenter le log (code CME, commande fautive, CEREG/CGATT/CSQ/CGPADDR, n° de passage).
  • Série de ≥10 redémarrages aimant — noter persistance ou non au 2e passage.
  • Idem sur carte neuve (symptôme B) pour confirmer la piste provisioning.
  • Décider, table en main, quels correctifs figer.

10 Niveaux de confiance

AffirmationConfiance
La phase post-« Starting PDP » est fragile, sans nouvel essai indépendant de la cohérence firmwareÉlevée — vérifié dans le code
Le BL fait déjà un power-off complet de 5 min au nouvel essaiÉlevée — vérifié dans le code
AT+CGACT=1,1 est le mauvais levier en Cat-M1Élevée — code + doc u-blox
Carte neuve = course de provisioning au premier boot (SIM/eSIM)Modérée — cohérent, à confirmer par l'instrumentation
« CGPADDR au lieu de CGACT » comme correctifModérée — la vérif IP est solide, le remplacement reste à valider au banc
Le renforcement du power-on changerait quelque choseÀ tester — dépend du test décisif
Cadrage

Le sujet est le durcissement de la fiabilité OTA — déterminant pour le déploiement terrain, où une sonde montée ne peut être relancée qu'à l'aimant. C'est un travail de robustesse, à confirmer par l'instrumentation avant tout correctif.

11 Carte du code (repères)

ÉlémentFichier — lignes
Boucle principale + logique de nouvel essaimain.c — 112-123
Séquence de la boucle applicative (étapes 1-5)application.c — 416-470
Critère de cohérence firmware (FwIsConsistent)application.c — 388, 400, 530, 615-616
Ouverture du contexte de données (point de panne)SARA_R422.c — 809-859
Attente d'enregistrement réseau (CREG + CEREG)SARA_R422.c — 190-241
Power-on (décharge aveugle, 2 × 1 s)SARA_R422.c — 394-420
Power-off (CPWROFF + attente VINT + coupure alim ; early-return si alim déjà coupée)SARA_R422.c — 422-458
Base de référence

Analyse réalisée sur le bootloader v0.1.9, branche rapatriée à jour. Les extraits ci-dessus sont des spécifications, pas des modifications appliquées.