Selbsttests für embedded-Systeme

Software checkt Hardware und sich selbst

9. Juli 2021, 15:50 Uhr | Von Colin Walls
Diesen Artikel anhören

Fortsetzung des Artikels von Teil 1

Softwarefehler

Typischerweise ist der komplexeste Teil eines eingebetteten Systems die Software. Diese Komplexität bedeutet unweigerlich eine hohe Fehlerwahrscheinlichkeit. Obwohl ein sorgfältiges Entwickeln, gefolgt von umfassendem Debugging und Testen, Fehler minimieren kann, ist es sehr unwahrscheinlich, dass es alle Möglichkeiten für Fehler ausschließt. Durch eine defensive Codierung und das Einbauen von Prüfungen können die Auswirkungen von verbleibenden Codierungsfehlern aber minimiert werden. Es gibt zwei Hauptarten von Softwarefehlern: Datenfehler und Codeschleifen.

Datenfehler

Die häufigste Ursache für Datenfehler in C-Code ist die Verwendung von Zeigern. Zeiger sind eine sehr mächtige Funktion der Sprache, aber diese Macht kann auch gefährlich sein. Es gibt drei häufige Arten, wie Zeiger Probleme verursachen:

  • Die Verwendung eines abgelaufenen Zeigers. Üblicherweise ist ein Zeiger nur für eine bestimmte Zeit gültig und die Verwendung nach dieser Zeit kann unvorhersehbare Folgen haben. Es ist gute Praxis, einen Zeiger auf NULL zu setzen, sobald seine Verwendung abgelaufen ist. Ein Trap-Handler würde dann eine ungültige Verwendung danach abfangen.
  • Mangelnde Kompetenz bei der Zeigerarithmetik. Insbesondere in Embedded-Anwendungen versuchen Entwickler möglicherweise »clevere« Dinge mit Zeigern, um ihre Ziele zu erreichen. Dies kann zu Fehlern führen, insbesondere wenn der Programmierer die Zeigerarithmetik nur unzureichend beherrscht.
  • Übermäßiger Einsatz von Indirektion. Ein Zeiger kann auf einen Zeiger zeigen, der wiederum auf einen anderen Zeiger zeigen kann, und so weiter. Einige Ebenen der Indirektion sind nützlich, um komplexe Daten zu handhaben. Eine übermäßige Komplexität führt jedoch unweigerlich zu Fehlern.

Es gibt keine festen Regeln, aber eine strikte Begrenzung: die Indirektion auf nicht tiefer als Zeiger auf Zeiger aufZeiger kann sinnvoll sein. Wenn eine Memory Management Unit (MMU) zur Verfügung steht, kann sie verwendet werden, um den Speicher vor Zugriffen zu schützen und damit jegliche Datenfehler einzudämmen.

Das Überlaufen von aggregierten Datenstrukturen – insbesondere des Stacks und der Arrays – ist eine häufige Ursache für Datenfehler. Vor allem Stacks sind problematisch. Das Festlegen der Stack-Größen in einer Multithread-Anwendung kann eine Herausforderung sein, auch wenn es Tools gibt, die dabei helfen. Wenn ein Stack überläuft, wird die Aufgabe vermutlich ohne Probleme fortgesetzt. Allerdings beschädigt der Überlauf wahrscheinlich den Stack eines anderen Tasks, der möglicherweise abstürzt. Diese Art von Fehler ist sehr schwer zu lokalisieren.

Ein Ansatz zur Abschwächung von Stack-Überläufen ist die Verwendung von »Schutzwörtern« (Guard Words). Dies sind zusätzliche Wörter an beiden Enden des Stacks, die mit einem bekannten Wert geladen werden. Dieser Wert sollte eine eher zufällige, ungerade Zahl sein. Im Hintergrund laufender Code kann die Schutzwörter überwachen und Maßnahmen ergreifen, wenn ihr Wert geändert wird – bei einem 32-bit-System besteht nur eine Wahrscheinlichkeit von 4 Milliarden zu 1, dass ein Datenfehler übersehen wird (Bild).

passend zum Thema

Mit Schutzworten – eine zufällige, ungerade Zahl – am Anfang und Ende eines Stacks lässt sich sehr einfach überwachen, ob der Stack überläuft
Bild. Mit Schutzworten – eine zufällige, ungerade Zahl – am Anfang und Ende eines Stacks lässt sich sehr einfach überwachen, ob der Stack überläuft.
© Walls

Wenn der Stack voll ist, zeigt der Stack-Zeiger auf das Schutzwort. Wenn ein weiteres Element auf den Stack geschoben wird, wird das Schutzwort beschädigt. Der Überwachungscode kann Maßnahmen ergreifen, bevor es zu einem Absturz (eines anderen Tasks) kommt.

Der gleiche Ansatz kann auf Verletzungen von Array-Grenzen angewendet werden. Der häufigste Fehler ist auch hier das Überlaufen eines Arrays, sodass ein Schutzwort ebenfalls effektiv sein kann.

Schleifen im Code

Mit Ausnahme der äußeren Schleife eines immer laufenden Tasks sollte es im Code für ein Embedded-System niemals eine Endlosschleife geben. Wenn Code in einer Schleife festhängt, handelt es sich um einen Codierungsfehler, oder der Code wartet auf eine Antwort der Schaltung (Hardware), die nicht kommt.

Der einzige mögliche Schutz vor Codierungsfehlern, die Schleifen verursachen, ist eine Art »Watchdog«. Dies ist typischerweise eine Hardwareeinrichtung. Die Schaltung benötigt einen periodischen Zugriff, andernfalls kommt es zu einer Zeitüberschreitung und der Watchdog »beißt«; dies kann zu einem Reset oder vielleicht zu einem nicht maskierbaren Interrupt führen.

Ein häufiger Fehler ist es, den Watchdog-Servicecode in eine Timer-Interrupt-Service-Routine zu packen. Das bedeutet, dass der Watchdog auch dann bedient wird, wenn der Code des Hauptprogramms (Main) in einer Schleife läuft.

In einer Multithreading-Umgebung (Multitasking) könnte ein Task die Rolle des Watchdogs übernehmen, vorausgesetzt, das Betriebssystem ist präemptiv.

Wenn Code in einer Schleife läuft, während er auf eine Antwort von einem Peripheriegerät wartet, sollte eine Zeitüberschreitung (Timeout) in die Schleife eingebaut werden. Die Möglichkeit eines Hardwareausfalls sollte immer berücksichtigt werden.

Fehlerbehebung und -meldung

Das Ausmaß, in dem ein Fehler gemeldet werden kann, hängt stark von dem jeweiligen System ab. Das Gleiche gilt für die mögliche Wiederherstellung.

In tief eingebetteten Systemen gibt es möglicherweise keine Benutzerschnittstelle, sodass die einzige Möglichkeit im Falle eines Fehlers darin besteht, das System zurückzusetzen, in der Hoffnung, dass das Problem dadurch behoben wird. Möglicherweise ist es machbar, den Fehler für eine spätere Referenz zu protokollieren. Wenn es irgendeine Art von Benutzeroberfläche gibt, bieten sich andere Möglichkeiten:

  • Wenn eine Textanzeige vorhanden ist, kann eine Meldung oder eine Grafik den Benutzer warnen.
  • Eine Tonausgabe ist eine weitere Option.
  • Wenn das Gerät vernetzt ist, gibt es verschiedene Möglichkeiten, einschließlich des Versendens einer »Notruf«-E-Mail durch das Gerät.
  • Eine einfache LED, insbesondere eine mehrfarbige, kann effektiv eingesetzt werden und ist selbst bei tief eingebetteten Systemen ziemlich verbreitet.

Wenn nur eine einzelne LED zur Verfügung steht, kann diese blinken, um den Status des Systems anzuzeigen. Blinken ist besser als gleichmäßiges Leuchten, da es zeigt, dass etwas passiert.

Ein guter Ansatz ist ein gleichmäßiger langsamer »Herzschlag«, um zu zeigen, dass das System normal funktioniert. Schnellere Blinkraten können verwendet werden, um einen Fehler anzuzeigen. Verschiedene Tastverhältnisse – Serien von Blinksignalen gefolgt von einer Pause – können verwendet werden, um verschiedene Fehler anzuzeigen (Listing 3).

Das Blinken einer LED kann den normalen Betrieb kennzeichnen (langsames Blinken) und auf Fehler hinweisen (schnelles Blinken). Über ein codiertes Blinken, vergleichbar dem Morse-Code, lassen sich sogar Fehlerarten spezifizieren
Listing 3. Das Blinken einer LED kann den normalen Betrieb kennzeichnen (langsames Blinken) und auf Fehler hinweisen (schnelles Blinken). Über ein codiertes Blinken, vergleichbar dem Morse-Code, lassen sich sogar Fehlerarten spezifizieren
© Walls

Selbsttests sind für die meisten Embedded-Systeme eine Überlegung wert. Die erste Regel ist, zu akzeptieren, dass ein Fehler möglich ist, und dann gilt es alles in Betracht zu ziehen, was schief gehen kann. Für den Selbsttest kann zusätzlicher Code hinzugefügt werden, um den Zustand des Systems zu überwachen, und es können Mittel zur Abschwächung oder Behebung von Fehlern in Betracht gezogen werden, inklusive der Warnhinweise an den Benutzer.

 

Der Autor

 

 

Colin Walls ist beim Siemens-EDA
Colin Walls, Siemens EDA.
© Walls

Colin Walls

verfügt über mehr als vierzig Jahre Erfahrung in der Elektronikindustrie, wobei er sich hauptsächlich mit Embedded-Software beschäftigt. Er hält häufig Vorträge auf Konferenzen und Seminaren und ist Autor zahlreicher technischer Artikel und dreier Bücher über Embedded-Software. Zuletzt war Walls als Embedded-Software-Technologe bei Siemens Embedded, zuvor Mentor, tätig.


  1. Software checkt Hardware und sich selbst
  2. Softwarefehler

Lesen Sie mehr zum Thema


Das könnte Sie auch interessieren

Jetzt kostenfreie Newsletter bestellen!

Weitere Artikel zu Siemens AG Erlangen

Weitere Artikel zu Betriebssysteme

Weitere Artikel zu Industrie-Computer / Embedded PC