Hersteltijd van ESP32-firmware-updates

Omdat OTA's de volledige software in ons systeem vervangen, zijn ze delicaat: er zijn talloze momenten waarop het mechanisme mis kan gaan. Dit is de reden waarom je soms de melding ziet: "zet het apparaat niet uit totdat de update is toegepast".

Vanwege het belang van het OTA-mechanisme moet het volledig betrouwbaar zijn. Er mag geen manier zijn om het mechanisme te breken, ongeacht hoeveel we ons best doen. Zelfs als we slechts een gedeeltelijke OTA downloaden, of als de stroom op het slechtst denkbare moment uitvalt, mag er niets kapotgaan. Bovendien moeten we zo snel mogelijk kunnen herstellen.

OTA's zijn zo cruciaal dat ze bij elke wijziging in het systeem automatisch getest moeten worden. We moeten onze apparaten door de ergste scenario's leiden om te zien of ze nog steeds werken. De update moet ofwel volledig worden toegepast, of helemaal niet: als de update mislukt, moeten we terugkeren naar een bekende, stabiele staat.

We moeten het volgende garanderen:

  • Overleven van de onderbreking: Het apparaat moet na een onderbroken OTA-update nog steeds functioneren en de oorspronkelijke versie van de code draaien.
  • Herstellen van de onderbreking: Het apparaat moet de OTA-update opnieuw kunnen uitvoeren, om zo uiteindelijk op de nieuwe versie van de code uit te komen.

We moeten dus testen of een update ofwel schoon wordt afgerond, of dat hij wordt onderbroken. Denk aan stroomuitval tijdens het downloaden, een spontane reboot van het apparaat, of iemand die op het verkeerde moment op reset drukt. In dat geval moet het apparaat zelfstandig herstellen en de taak alsnog voltooien.

In dit artikel gebruiken we het Groundrun-systeem om OTA-updates op een ESP32-C6 systeem bewust te saboteren en te controleren of we telkens succesvol kunnen herstellen. We onderbreken de OTA op drie verschillende manieren:

  1. Een software-reset midden in de update.
  2. Een hardware-reset midden in de update.
  3. Het uittrekken van de stekker van het gehele systeem midden in de update.

Vervolgens controleren we of het systeem in staat is om te herstellen, de update te herstarten en deze te voltooien. We meten de tijd die nodig is voor dit herstel. Dit is een proces dat elk verbonden product als onderdeel van de ontwikkelingsworkflow zou moeten doorlopen om maximale stabiliteit te garanderen na elke wijziging.

Hoe Over-the-Air updates werken

Een over-the-air update pusht nieuwe firmware naar een apparaat via de netwerkverbinding, waarna het apparaat de nieuwe firmware zelf installeert. Het nieuwe image komt uit een cloud-backend, die weet welke versie elk apparaat momenteel draait en naar welke versie het apparaat moet worden bijgewerkt.

Afhankelijk van het product wordt de update direct opgehaald (stil op de achtergrond) of verschijnt deze eerst in een app, zodat de gebruiker kan beslissen wanneer de update wordt geaccepteerd. In beide gevallen downloadt het apparaat het nieuwe image, past dit toe en herstart het systeem.

Het proces in vogelvlucht:

  • Nieuw image is klaar in de cloud → Verzonden op de achtergrond OF getoond in de app → Apparaat downloadt het image → Apparaat past het toe en herstart.

Het lastige deel is wanneer het OTA-proces wordt onderbroken. In het ergste geval kan een firmware-image die halverwege het schrijven is onderbroken, ervoor zorgen dat een apparaat helemaal niet meer kan opstarten. Dit staat bekend als een 'bricked' apparaat: een apparaat dat net zo nuttig is als een baksteen.

Elk OTA-mechanisme moet voorkomen dat een apparaat 'bricked' raakt. De meest gebruikte verdediging is om de firmware die het apparaat momenteel draait nooit aan te raken totdat het nieuwe image is bevestigd. Het nieuwe image wordt eerst in een aparte opslag geplaatst en geverifieerd voordat er iets wordt omgeschakeld. Als het nieuwe image nooit wordt voltooid, valt het apparaat terug op de vorige versie. Vandaag de dag biedt elke chipfabrikant een OTA-mechanisme met dit productieniveau. In ons geval is dat de ESP-IDF van Espressif, waar de ESP32 in dit experiment op draait. Met het standaardmechanisme kan een onderbroken update niet leiden tot een apparaat dat niet meer kan booten.

Omdat het OTA-mechanisme ons beschermt tegen het 'bricken' van het apparaat, is de slechtste staat waarin we kunnen belanden een apparaat dat vastzit op de oude versie, zonder dat er iets is dat een nieuwe poging forceert. Ons systeem moet dit kunnen detecteren en herstellen. We moeten automatisch een nieuwe poging starten met als doel dat het apparaat uiteindelijk op de doelversie uitkomt.

De ESP32

De ESP32 is een familie van Wi-Fi en Bluetooth microcontrollers van Espressif. De ESP32 is een zeer veelvoorkomende microcontroller, gebruikt in slimme stekkers, sensoren, huishoudelijke apparaten en vele andere verbonden producten. Het bord in dit experiment is een ESP32-C6, een van de nieuwere chips in de lijn, die naast Wi-Fi en Bluetooth Low Energy ook Thread ondersteunt op dezelfde chip. De firmware draait op ESP-IDF, het eigen ontwikkelingsframework van Espressif.

Hoe de ESP32 OTA-herstel afhandelt

ESP-IDF implementeert het bovenstaande patroon met twee flash-partities: ota0 en ota1. Het apparaat boot van de partitie waar de bootloader momenteel naar wijst, en een update wordt gedownload naar de partitie die inactief is.

Het bord in dit experiment maakt verbinding met Wi-Fi op dezelfde manier als een verzonden apparaat dat verbinding maakt met een thuisnetwerk. De update zelf komt van een gewone HTTPS-server, via hetzelfde pad dat esphttpsota() gebruikt in een echte implementatie.

De update wordt gedownload naar het inactieve slot, wordt geverifieerd, en pas daarna schakelt de bootloader de boot-pointer om en herstart het apparaat. Als het nieuwe image boot en zichzelf bevestigt, markeert de bootloader het als geldig. Als dat niet gebeurt, stuurt CONFIGBOOTLOADERAPPROLLBACKENABLE het apparaat automatisch terug naar het slot waar het vandaan kwam, zonder dat daar firmware voor nodig is.

De partities van de ESP32:

  • Vóór update: ota0 draait v1 (actief), ota1 is ongebruikt. De boot-pointer wijst naar ota_0.
  • Na succesvolle update: ota0 bevat v1, ota1 draait v2 (actief). De boot-pointer wijst naar ota_1.

Drie manieren om de update te onderbreken

Een schone run van deze update, zonder verstoring, duurt ongeveer negentig seconden op het netwerk van de testopstelling. Op een bepaald punt tijdens het downloaden onderbreken we de update op drie verschillende manieren:

  1. Software reset: Verstuurt een force_reboot commando naar de console van het bord midden in de download; dit lijkt op een crash elders in de firmware.
  2. Reset-pin toggle: Geeft een impuls op de hardware-resetlijn, dezelfde debug-hardware die wordt gebruikt om het bord te flashen.
  3. Hard power cut: De stroomschakelaar van de opstelling onderbreekt de stroomtoevoer naar het bord, vergelijkbaar met een brownout of iemand die de stekker uit het stopcontact trekt. Dit is een echt hardwaredefect, automatisch uitgevoerd door de opstelling.

Elk van deze methoden heeft hetzelfde effect: ze stoppen de OTA halverwege het schrijven van het nieuwe image naar het inactieve slot. Ze onderbreken het proces vóór het punt waarop de bootloader de boot-pointer zou wijzigen. Hierdoor draait het apparaat dat herstart nog steeds de oude firmware, met het rollback-mechanisme klaar om een nieuwe poging te faciliteren. Hoewel de effecten vergelijkbaar zijn, kunnen ze het systeem potentieel op verschillende manieren breken. We willen zeker weten dat het systeem in elk geval overleeft en herstelt.

Hoe te herstellen van een mislukte update

Herstel betekent in dit scenario het volgende: het apparaat herstart, bevestigt dat het nog steeds op de oude versie zit, voltooit een nieuwe update naar de nieuwe versie, en behoudt die versie na een tweede, bewuste reset. Die tweede reset sluit een aanhoudende PENDING_VERIFY status uit, waarbij de bootloader nog zou denken dat het nieuwe image mogelijk moet terugrollen.

In elke test waarbij de onderbreking plaatsvond, gebeurde precies dit. Het bord startte opnieuw op de oude versie, accepteerde een tweede update-poging zonder problemen en bleef daarop staan. Het rollback-mechanisme van ESP-IDF deed al het werk; er was geen tussenkomst nodig van de zijde van Groundrun in geen van de achttien tests.

Om echter echt grondig te zijn, gaat een test een stap verder dan het bevestigen dat het apparaat v2 draait: er wordt nog een update uitgevoerd, van v2 naar v3, om te controleren of v2 zijn eigen vermogen om toekomstige updates te ontvangen niet is verloren.

Vergelijking van hersteltijden

Er zijn in totaal achttien runs uitgevoerd op echte hardware (drie interruptiemethoden, twee rollback-instellingen, drie tests per scenario). De cijfers geven de gemiddelde hersteltijd aan, van het moment dat de update start tot de bevestigde tweede reset.

InterruptiemethodeRollback ingeschakeldRollback uitgeschakeld
Hard power cut99.6s93.5s
Software reset165.7s155.3s
Reset-pin toggle157.5s158.5s

De hersteltijd is sterker gecorreleerd aan de manier waarop de update werd onderbroken dan aan de vraag of rollback was ingeschakeld. Een 'hard power cut' herstelde het snelst (onder de twee minuten), omdat die herstelrun een schone tweede poging is zonder dat her-provisioning nodig is. Software reset en de reset-pin toggle duurden langer (ongeveer twee en een half minuut), omdat hun herstelrun ook opnieuw verbinding moet maken met Wi-Fi.

Variëren van het moment van onderbreking

Om nog grondiger te zijn, varieerden we het punt waarop de onderbreking plaatsvindt. Dit verandert de correctheid van het experiment niet (we kunnen nog steeds telkens herstellen), maar het beïnvloedt wel de tijd die herstel kost.

We gebruikten hiervoor de reset-pin toggle, omdat dit de snelste methode is om toe te passen, waardoor we de timing op milliseconden kunnen beheersen. Eerst maten we drie schone, ononderbroken downloads als baseline: 89 seconden. Daarna timden we de reset-pin toggle om te vallen bij 25%, 50% en 75% van die baseline, met rollback ingeschakeld.

Alle negen tests met verschillende onderbrekingspunten herstelden automatisch. Wat veranderde was de duur:

  • Herstel bij 25% van de download duurde iets meer dan drie minuten.
  • Herstel bij 75% van de download groeide naar bijna drie driekwart minuut.

De extra hersteltijd volgt nauwgezet de extra vertraging: het is de voortgang van de download die twee keer opnieuw moet worden gedaan—één keer vóór de onderbreking en één keer daarna.

Conclusies

Ons experiment toont aan dat we zowel kunnen overleven als herstellen van onderbroken OTA-pogingen. Dit was wat we verwachtten: we gingen ervan uit dat het basis-OTA-mechanisme in de Espressif IDF solide zou zijn. In elke configuratie die we onderbraken, vond het apparaat zijn weg terug via het rollback-mechanisme van ESP-IDF. Ongeacht het gekozen pad van onderbreking herstelt het systeem betrouwbaar, ongeacht configuratiekeuzes zoals het in- of uitschakelen van het rollback-mechanisme.

De waarde van dit experiment ligt in het vertrouwen dat het mechanisme biedt. We kunnen deze scenario's nu herhaaldelijk uitvoeren met de zekerheid dat, wat we ook doen, ons belangrijkste mechanisme altijd blijft werken.