Forum: Mikrocontroller und Digitale Elektronik assert() und error() auf einem Mikrocontrollerboard


von Walter Tarpan (Gast)


Lesenswert?

Hallo zusammen,
ich beschäftige mich im Moment mit AVR und STM32 mit AVR-GCC bzw 
ARM-GCC. Und
schon wieder bin ich auf eine Anfängerfrage gestoßen: Wie werden auf 
einem Mikrocontroller eigentlich error()- und assert()-Funktionen 
implementiert.

Momentan sieht es bei mir so aus, daß ich selbst eine Funktion void 
error(void) implmentiert habe, die alle Ausgänge hochohmig schaltet und 
dann in eine Dauer-while-Schleife übergeht. Irgendwann sieht man, daß 
das "heartbeat"-Signal ausbleibt und kann dann mit dem Debugger 
nachsehen.

Aber wie wird soetwas "richtig" gemacht?

Kennt ihr Quellen, die bewährte Verfahren beschreiben?

Viele Grüße
W.T.

von Klaus W. (mfgkw)


Lesenswert?

http://nongnu.org/avr-libc/user-manual/group__avr__assert.html
http://nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga63e28bec3592384b44606f011634c5a8

Wobei ich das noch nie gemacht habe. Wenn der Controller gar nichts mehr 
macht, hat man nicht viel davon.
Evtl. ist es sinnvoller, neu zu starten?

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

assert() hab ich auf einem uC noch nie verwendet.

Ich versuch aber immer eine LED an irgendeinen freien port zu hängen, 
die sendet im Normalfall eine Art "Heartbeat" (alle paar Sekunden kurz 
blinken), und dann hab ich immer noch ein "panic(uint8_t code)" 
Funktion, die blinkt mir zuerst ein SOS zu, und dann den code (meist nur 
die unteren vier Bit) als eine Art Morsecode (0=kurz, 1=lang) zu.

von Walter Tarpan (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> http://nongnu.org/avr-libc/user-manual/group__avr_...
> http://nongnu.org/avr-libc/user-manual/group__avr_...
>

Die beiden kannte ich schon. Leider fehlt mir die Erfahrung, um aus 
dieser Beschreibung best practices abzuleiten.

> Wobei ich das noch nie gemacht habe. Wenn der Controller gar nichts mehr
> macht, hat man nicht viel davon.
> Evtl. ist es sinnvoller, neu zu starten?

Das hängt davon ab, in welchem Entwicklungstadium sich die Firmware 
befindet. Wenn sie ausentwickelt ist, ist es sicherlich sinnvoll, wenn 
sie irgendwie weiterläuft oder neustartet, wenn ein Fehler aufgetreten 
ist (graceful degradation).

Im Stadium der Firmwareentwicklung will ich jedoch jeden Fehler so hart 
und deutlich wie möglich merken, um ihn möglichst einfach beheben zu 
können.

von Oliver S. (oliverso)


Lesenswert?

Na ja, so hart und deutlich wie möglich wäre 1 kg C4 mit Zünder an einem 
Ausgang, der im Fehlerfall gesetzt wird.

Ansosonsten hiflt nur das übliche: Simuator, Emulator, 
Debug-Textausgabe. Da kannst du dann aich assert-Macros der avr-libc 
nutzen.

Oliver

von Dr. Sommer (Gast)


Lesenswert?

Ich verwende am Cortex-M in Anlehnung an das normale assert() und Visual 
Studio's "VERIFY" gerne sowas:
1
inline void verify (bool cond) {
2
  if (!cond) {
3
    while (1) {
4
      asm volatile ("cpsid i\nbkpt");
5
    }
6
  }
7
}
8
9
#ifdef NDEBUG
10
// because eventual evaluation of the argument
11
#define assert(c)  static_cast<void>(0)
12
#else
13
inline void assert (bool cond) {
14
  verify (cond);
15
}
16
#endif
Die verify() -Funktion prüft ihr Argument immer, und schaltet im 
Fehlerfall Interrupts ab und ruft "BKPT" auf, sodass ein evtl. 
angeschlossener Debugger das als Breakpoint sieht und man wunderschön im 
Backtrace etc. sehen kann was schief gelaufen ist.
Das assert() ist nur im Debug-Modus aktiv (sonst macht es gar nichts) 
und prüft nur dann sein Argument. Man kann so in seinem Code auf 
Verdacht überall mit assert() alle möglichen Variablen prüfen, und im 
End-Programm nimmts keinen Platz/Rechenzeit weg. Hab so schon einige 
Bugs gefunden.

Eventuell kann man ja noch Code einfügen um Pins auf Floating zu 
schalten etc. Wenn man kein C++ sondern C verwendet muss man das 
static_cast und das "bool" ändern.

von Walter T. (nicolas)


Lesenswert?

Danke für die Antworten!

Aber das kann doch nicht alles sein?

Ich hätte gedacht, daß Fehlerbehandlung zu den Problemen für 
Fortgeschrittene gehört und es deshalb schön formulierte best practices 
gibt, damit wir Normalsterbliche nicht ziellos umherprogrammieren 
müssen.

Oder gibt es soetwas erst ab Systemen mit Betriebssystemen?

EDIT: Nanu, kursiv geht nicht, wenn ein Zeilenumbruch drin ist (?)

: Bearbeitet durch User
von Jan H. (j_hansen)


Lesenswert?

Walter Tarpan schrieb:
> Ich hätte gedacht, daß Fehlerbehandlung zu den Problemen für
> Fortgeschrittene gehört und es deshalb schön formulierte best practices
> gibt, damit wir Normalsterbliche nicht ziellos umherprogrammieren
> müssen.

Nun ja, ein "assert" kann man schwer als "Fehlerbehandlung" bezeichnen. 
Das ist sozusagen der Not-Aus, und in Produktivcode sollten sich meines 
Wissens nach auch keine Asserts mehr befinden. Das ist eher ein 
Testwerkzeug und muss auch nur anzeigen, wo etwas wie fehlgeschlagen 
ist. Je nach Vorliebe und Möglichkeiten eben mit LEDs o.a.

Was du mit "error()" meinst musst du vielleicht noch etwas genauer 
ausführen. Meinst du das als Synonym zu assert()? Oder im Sinne von 
Exception-Handling usw., also echter Fehlerbehandlung?

von Walter T. (nicolas)


Lesenswert?

OK, "assert" und "error" sind sicherlich keine Fehlerbehandlung für 
Fortgeschrittene.

Also hätte ich den Thread eher "bewährte Methoden der Fehlerbehandlung 
auf ARM und AVR" nennen sollen.

von Dr. Sommer (Gast)


Lesenswert?

Walter Tarpan schrieb:
> Also hätte ich den Thread eher "bewährte Methoden der Fehlerbehandlung
> auf ARM und AVR" nennen sollen.
Viele Programmiersprachen bieten mit Exceptions einen vereinheitlichten 
mächtigen Mechanismus zur Fehlerbehandlung; auf ARM's mit genug Speicher 
kann man die in C++ verwenden. Ansonsten muss man sich halt wie immer 
mit return codes behelfen. Da aber das typischer µC-Programm keine 100 
Aufruf-Ebenen hat, ist das da noch verkraftbar...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.