1. Oktober 2008

Virtuelles EEPROM neu gedacht: 30 Sekunden Nachlauf, ein Löschvorgang zu viel

ZeitraumOkt 2008 – 2009
Kunde / KontextBeru, Bretten (Steuergerät) · via Gigatronik
RolleReverse-Code-Analyse, Architektur & Redesign (UML + Pseudo-Code)
Problem

Ein virtuelles EEPROM (Flash-Emulation) speicherte persistente Daten am Zündungsende. Der OEM verkürzte die Nachlaufzeit von 60/90 s auf 30 s — doch der alte Manager berechnete, schrieb und löschte alles erst am Ende und sprengte in der ungünstigen Konstellation (volle Page) das 30-s-Fenster.

Soll

Ein Speichermanagement, das die 30-s-Vorgabe sicher einhält — indem Zustandsermittlung und das teure Löschen aus dem Nachlauf heraus in die Laufzeit verlagert werden.

Ist / Ergebnis

Reverse-Code- & Element-Analyse, neue Architektur (UML + Pseudo-Code): eine niederpriore Idle-Task ermittelt fortlaufend den Zustand und erledigt Kompaktierung/Löschen im Hintergrund; am Zündungsende bleibt nur reines Anhängen der finalen Werte. Ping-Pong über zwei 1-kB-Pages.

Tech-Stack
Embedded CVirtuelles EEPROM / Data FlashReverse-Code-AnalyseUMLPseudo-CodeScheduling / Idle-Task
Mitgebrachte Fähigkeiten
Embedded CFlash-/SpeicherkenntnisseRTOS-/Scheduling-Denken (aus der Studienarbeit)
Entwickelte Fähigkeiten
Reverse Engineering & ArchitekturEchtzeit-RessourcenmanagementWear-LevelingSpezifikationsnahes Design (UML + Pseudo-Code)

Das hier ist mein Lieblingsprojekt aus der Gigatronik-Zeit — und der direkte Folgeauftrag aus der Beru-Diagnose-Testautomation. Es hat mir riesigen Spaß gemacht, weil es plötzlich ganz nah an dem war, was ich in meiner Studienarbeit über Echtzeitbetriebssysteme gelernt hatte: Es ging im Kern gar nicht um Speicher — sondern um Scheduling.

Warum ein Steuergerät überhaupt persistent speichert

Ein Steuergerät muss sich Dinge über den Zündungszyklus hinaus merken: den Zündungszykluszähler, Fehlerspeicher-Einträge (DTCs), über die Diagnose gesetzte Konfigurationsdaten. Dafür nutzt man ein EEPROM (E²) — persistenten Speicher.

Der Haken: Ein E² verträgt nur eine begrenzte Zahl an Schreibzyklen. Günstige Bausteine halten weniger aus als teure — und weil Steuergeräteentwicklung immer auch Kostenoptimierung ist, will man so selten wie möglich schreiben. Deshalb der klassische Ablauf: Beim Einschalten (Klemme 15 an) wird das E² einmal komplett ins RAM gelesen; gearbeitet wird im RAM; und am Zündungsende — in der Nachlaufzeit, während die Bordnetzspannung die Steuergeräte noch kurz versorgt — schreiben alle Steuergeräte ihre RAM-Daten einmal zurück ins E². Der OEM gibt diese Nachlaufzeit vor, z. B. 30 Sekunden.

Was ein virtuelles EEPROM besonders macht

Statt eines teuren echten E² nutzt man oft ein virtuelles EEPROM — eine Emulation im Data-Flash (z. B. von Renesas). Der entscheidende Unterschied: Flash kann man nicht beliebig byteweise überschreiben. Eine einmal beschriebene Stelle wird erst wieder frei, wenn die ganze Page gelöscht wird (in meinem Fall 1 kB pro Page).

Deshalb speichert man jede Variable als Record, den man nur anhängt — nie überschreibt:

Header Trailer ID / Key Größe Daten Check-summe Validierungs-Counter Welche Variable? · Wie groß? · Die Nutzdaten · Integrität · Wie aktuell? Höherer Counter = neuerer Wert. Vorsicht 8-Bit-Überlauf: nach 255 kommt 0 — dann ist 0 der neuere.
Jeder persistente Wert ist ein Record: eine ID sagt, um welche Variable es geht, ein Counter, wie aktuell sie ist. Dieselbe Variable darf mehrfach in der Page liegen — der Record mit dem höchsten Counter gewinnt.

Ein Update überschreibt also nichts, sondern hängt einen neuen Record an. Der alte bleibt als „Leiche” liegen, bis die Page gelöscht wird:

Page 0 (1 kB) — nur anhängen Zündzähler = 1 (veraltet) Config_A (gültig) Zündzähler = 2 (veraltet) DTC Unterspannung (gültig) Zündzähler = 3 (gültig, neuester) freier Platz Reihenfolge: anhängen aktuell gültig veraltet (ersetzt)
Der Zündzähler wird dreimal geschrieben — jedes Mal ein neuer Record. Nur der jüngste zählt; die älteren sind tote Bytes, die Platz belegen. So füllt sich die Page unweigerlich.

Irgendwann ist die Page voll. Dann muss man die neuesten gültigen Werte in eine zweite Page retten (Kompaktierung) und die alte Page löschen — das klassische Ping-Pong über zwei Pages:

Page 0 — VOLL Zündzähler=1 Config_A Zündzähler=2 DTC Unterspg. DTC Folgefehler Zündzähler=3 ① neueste gültige kopieren Page 1 — neu aktiv Config_A DTC Unterspg. Zündzähler=3 frei ② Page 0 löschen ⟳ (danach freie Spare-Page) nur die neuesten Werte, alte Duplikate bleiben zurück
Zwei Pages im Wechsel: Läuft eine voll, werden die aktuellen Werte in die andere gerettet, die volle danach gelöscht. Das Löschen ist die teuerste, langsamste Operation — und genau hier lag mein Problem.

Das Problem: 30 Sekunden, und die Uhr läuft

Der OEM hatte die Nachlaufzeit von vormals 60–90 s auf 30 s verkürzt — aus gutem Grund: Energie sparen, Batterie schonen. Der alte Manager machte aber alles erst am Zündungsende: Er berechnete die zu speichernden Zustände, schrieb sie und löschte — falls eine Page voll war — die alte Page. Und das EEPROM-Schreiben war im Nachlauf die letzte Task (sinnvoll, denn manchmal steht erst spät fest, was noch zu sichern ist). Es bekam also nur den Rest des ohnehin halbierten Fensters.

In der ungünstigen Konstellation — Page läuft am Zündungsende über — kippte das:

Klemme 15 AUS → Nachlauf 30 s (OEM-Limit) Task 1 Task 2 Task 3 EEPROM (letzte Task): rechnen+schreiben+LÖSCHEN Überlauf > 30 s Zeit →
Ist-Zustand: Die anderen Nachlauf-Tasks laufen zuerst, das EEPROM-Schreiben kommt zuletzt — und wenn es dann noch rechnen und löschen muss, ragt es über die 30-Sekunden-Grenze hinaus. Requirement verletzt.

Woran liegt’s? Löschen ist langsam und blockierend (ganze Page), und es lag zusammen mit der Berechnung im kritischen Nachlauf-Pfad. Genau das musste raus.

Die Idee: Speicherverwaltung ist ein Scheduling-Problem

Hier klickte es bei mir — das war fast dieselbe Fragestellung wie bei der Betriebssystem-Entwicklung: Eine teure, nicht-deterministische Operation gehört nicht in ein hartes Deadline-Fenster. Man verlagert sie dorthin, wo Zeit übrig ist.

Das Steuergerät läuft ja während des ganzen Zündungszyklus in einer zyklusüberwachten Hauptschleife. Die eigentliche Funktion (Zündung, Sicherheit) hat höchste Priorität — aber es gibt Idle-Zeit. Und: Nach jedem Main-Cycle kennen wir den Zustand — wir wissen fortlaufend, was gespeichert werden müsste und wie voll die Page ist. Warum also bis zum Nachlauf warten?

Hauptschleife — feste Cycle-Time Funktion Idle → Funktion Idle → Funktion Idle → ↑ hohe Priorität, nie verzögern Low-Prio-EEPROM-Task läuft nur in der Idle-Zeit pro Aufruf ein kleines Stück: Zustand ermitteln · kompaktieren · Löschen anstoßen & pollen
Der Kniff aus der Betriebssystem-Welt: eine kooperative, niederpriore Task, die nur die Idle-Zeit nutzt, feste Cycle-Time, pro Aufruf nur ein kleines Stück Arbeit — so wird die eigentliche Steuergerätefunktion nie verzögert.

Das neue Design

Laufzeit — Zündung AN (viele Sekunden bis Minuten) ① Zustand ermitteln (nach jedem Main-Cycle) ② Page fast voll → kompaktieren ③ alte Page löschen (im Hintergrund) — erledigt in der Idle-Zeit, WÄHREND das Auto läuft — Klemme 15 AUS → Nachlauf (30 s) 30 s Task 1 Task 2 Task 3 EEPROM: nur schreiben Reserve Kein Rechnen, kein Löschen mehr im Nachlauf → deterministisch kurz, passt sicher in 30 s
Neu-Design: Weil Zustandsermittlung, Kompaktierung und Löschen schon während der Laufzeit in der Idle-Task passiert sind, bleibt am Zündungsende nur das Anhängen der finalen Werte — mit komfortabler Reserve vor der 30-Sekunden-Grenze.

Konkret leistet der neue Manager:

  • Fortlaufende Zustandsermittlung (nach jedem Main-Cycle statt gebündelt am Ende).
  • Page-voll-Detection zur Laufzeit und Umschalten auf die zweite Page (Ping-Pong).
  • Löschen der deprecated Page im Hintergrund — asynchron angestoßen, Status in der Idle-Task gepollt.
  • Am Nachlauf nur noch Anhängen der vorbestimmten Endwerte.

Wie ich es angegangen bin — und was ich wirklich gebaut habe

Es gab keinen sauberen Neuanfang: Ich musste per Reverse-Code-Analyse und Element-Analyse verstehen, was die bestehende Software tat, und daraus eine neue Architektur entwickeln — dokumentiert in UML-Designs und einer Pseudo-Code-Implementierung (ganz ähnlich, wie es die GMW3110 vorgemacht hatte).

Und ehrlich: Die tatsächlich ausgelieferte Lösung war bewusst pragmatisch. Bei „Page voll” habe ich einfach alle gültigen Werte in die andere Page neu geschrieben — ohne die feinere Optimierung, Gültigkeit sauber zwischen alter und neuer Page aufzuteilen. Das sind ein paar Schreibvorgänge mehr als nötig, und die Lebensdauer (ein virtuelles EEPROM garantiert z. B. ~10.000 Löschzyklen) blieb dabei vergleichbar zur Vorgänger-Umsetzung — nicht besser. Aber: Es hielt die 30-Sekunden-Vorgabe sicher ein, und es war rechtzeitig fertig. Die elegantere Variante (minimale Umkopierung, Gültigkeit über beide Pages) blieb ein bewusster Ausblick — dafür fehlte schlicht die Zeit. Diese Abwägung „gut genug, pünktlich” gegen „perfekt, zu spät” ist mir bis heute präsent.

Was man daraus mitnehmen kann

  • Verlagere teure Arbeit weg von der Deadline. Der Kern war nicht schnelleres Löschen, sondern Löschen zur richtigen Zeit — in der Idle-Zeit statt im 30-s-Nachlauf. Dasselbe Prinzip steckt heute in Hintergrund-Jobs, Garbage Collection und asynchronen Queues.
  • Speicherverwaltung ist oft ein Scheduling-Problem. Wer Prioritäten, Idle-Zeit und kooperative Tasks denkt, löst Flash-Probleme mit denselben Werkzeugen wie Betriebssystem-Probleme.
  • „Gut genug und pünktlich” ist eine legitime Ingenieursentscheidung — solange man weiß, was man bewusst weglässt, und es dokumentiert.

Es war eines der Projekte, bei denen sich alles verband: hardwarenahes Flash-Wissen, Diagnose-Erfahrung, und das Scheduling-Denken aus meinem selbstgebauten Betriebssystem. Kein Wunder, dass es mein Lieblingsthema wurde.

Danke

Herzlichen Dank an Markus Kernwein, meinen Auftraggeber bei Beru, für die erfolgreiche und vertrauensvolle Zusammenarbeit — erst bei der Diagnose-Testautomation, dann bei diesem Redesign.

Markus Kernwein auf Xing

Weiterführend zur Mechanik virtueller EEPROMs: Silicon Labs AN703 „Simulated EEPROM" und die Renesas-Application-Note zum virtuellen EEPROM.

← Zurück zum Lab