Forum: Mikrocontroller und Digitale Elektronik STM32: EEPROM schreiben im Hard-Fault-Zustand


von Martin M. (gga)


Lesenswert?

Hallo,

ich möchte gerne wissen, ob ein Hard-Fault aufgetreten ist. Leider liegt 
die Versorgungsspannung nicht dauerhaft am Gerät an, sondern immer nur 
kurzzeitig.

Kann man im Hard-Fault ein Byte im EEPROM schreiben? Interrupts wie z.B. 
Timer gehen in diesem Zustand ja nicht mehr. Zeiten müßte man mit 
While-Schleifen erzeugen. Ports schalten müssten ja im Hard-Fault noch 
gehen. Aber auch Register der SPI-Schnittstelle?

Die komplette SPI-Kommunikation müßte man dann mit etlichen 
Einzelbefehlen machen (recht aufwändig). EEPROM ist ein M95010-RDW6TP 
(128 Byte).

Hat jemand so etwas schon mal gemacht?

Gruß
Martin

von Rolf M. (rmagnus)


Lesenswert?

Martin M. schrieb:
> Kann man im Hard-Fault ein Byte im EEPROM schreiben? Interrupts wie z.B.
> Timer gehen in diesem Zustand ja nicht mehr.

Hard Fault ist kein Zustand, sondern eine Exception bzw. Interrupt. Der 
Hard-Fault hat eine höhere Priorität als alle anderen Interrupts, 
deshalb kommt nix anderes durch, solange du in der ISR bist. Ansonsten 
arbeitet der Prozessor ganz normal wie sonst auch.

von Martin M. (gga)


Lesenswert?

Rolf M. schrieb:
> Hard Fault ist kein Zustand, sondern eine Exception bzw. Interrupt. Der
> Hard-Fault hat eine höhere Priorität als alle anderen Interrupts,
> deshalb kommt nix anderes durch, solange du in der ISR bist. Ansonsten
> arbeitet der Prozessor ganz normal wie sonst auch.

Gibt es eine Möglichkeit (abgesehen von Reset), aus dem ISR des 
Hard-Faults raus zu kommen?

von A. F. (artur-f) Benutzerseite


Lesenswert?

Martin M. schrieb:
> Gibt es eine Möglichkeit (abgesehen von Reset), aus dem ISR des
> Hard-Faults raus zu kommen?

Ja bestimmt, aber besser wäre es dem Grund nachzugehen und schauen, dass 
es nicht passiert....

von Martin M. (gga)


Lesenswert?

Gibt es eine Art Flip-Flop als Bauteil, das ohne Versorgungsspannung den 
Zustand behält? Sollte recht klein und preiswert sein.

Dann könnte man dies beim Auftreten des Hard-Faults triggern und den 
Zustand des Ausgangs beim nächsten Booten überprüfen und das Flip-Flop 
resetten.

Aktuell ist nicht klar, ob ein Hard-Fault ab und zu auftritt oder nicht. 
Daher muß das Ganze nun eingegrenzt werden.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Im Hardfault geht alles bis auf Interrupts, wie schon von Rolf erwähnt.
Allerdings kann man vom Hardfault zurück springen in "normalen" Code.
Vor dem Rücksprung also die Rücksprungadresse auf dem Stack austauschen.
Wobei der Stackpointer selbst ja auch kaputt sein kann, daher nen neuen 
Stack aufbauen (mit dem passenden Rücksprung) und dann diesen nutzen.
Du weist ja nicht wieso es geknallt hat.
Dort dann ein Notfallprogramm starten inkl. neuer Init.

Ist aber etwas sehr kompliziert.
Daher lieber den SPI per Polling nutzen und für den EEPROM brauchts doch 
auch kein Timer.
Die haben ja ein Statusregister welches man auch pollen kann.

Der SCB enthält dann ein paar Infos was passiert sein kann, das sollte 
auch abgespeichert sein.
Die MPU sollte auch aktiviert werden, das fängt dann direkt NULL Pointer 
ab.

Etwas Code für dich:
Beitrag "ARM Cortex-M3/4/7 Faulthandler"

Das nutzt den UART im Pollbetieb, musste eben auf EEPROM umbauen.

A. F. schrieb:
> Ja bestimmt, aber besser wäre es dem Grund nachzugehen und schauen, dass
> es nicht passiert....

Weswegen will er es wohl abspeichern ;)?
Wenn im Feld sich das Ding mal erhängt, dann lässtz sich anhand der 
gesammeltden Daten das Post Mortem rausfinden.
Man hat zwar den Anspruch fehlerfrei zu coden, aber die Realität sieht 
anders aus.

von Nop (Gast)


Lesenswert?

Martin M. schrieb:

> Gibt es eine Möglichkeit (abgesehen von Reset), aus dem ISR des
> Hard-Faults raus zu kommen?

Ja sicher. Einfach die ISR verlassen. Wenn die Ursache allerdings nicht 
behoben wurde, wird das vermutlich gleich wieder passieren. Deswegen 
läßt man sich nach dem Abarbeiten von was immer man da tun will z.B. auf 
den Watchdog fallen.

> Dann könnte man dies beim Auftreten des Hard-Faults triggern und den
> Zustand des Ausgangs beim nächsten Booten überprüfen und das Flip-Flop
> resetten.

Du hast die Register im RTC-Bereich, wo Du alles speichern kannst, was 
Du möchtest, auch über Resets hinweg, und ohne das EEPROM abzunudeln. 
Wenn Du Vbat mit einer Batterie oder Supercap pufferst, geht das sogar 
über Stromausfälle hinweg.

Du kannst beim Hochfahren außerdem ermitteln, wieso Du resettet hast: 
Reset-Pin, Watchdog, Power-on.

von M. Н. (Gast)


Lesenswert?

Nop schrieb:
> Ja sicher. Einfach die ISR verlassen.

das ist u.U. eine schlechte Idee. Wenn der Stack korrupt ist, misaligned 
o. ä. geht der return aus der ISR komplett schief.

Im Hardfault kannst du theoretsich nichtmal davon ausgehen, dass deine 
lokalen Variablen noch funktionieren, da diese auch auf dem Stack 
liegen. und wenn der Stack pointer 0x00 ist (ist bei mir schonmal durch 
eine nicht gewollte Rekursion passiert).

Ich habe den Hardfault schon auf mehrere Varianten gelöst:

1) While(1) im Hardfault und vom Watchdog rausholen lassen. Nach dem 
Reset prüfen, ob der Reset vom Watchdog kam und dementsprechend 
Fehlerzustand einnehmen.

2) Assembler Handler für Hardfault, der den Stack geraderückt. 
(reinitialisierung auf oberes Ende des SRAMs) und dann einen C Handler 
aufruft, der die interessanten Daten im Backup RAM speichert.

Dieser ist recht rudimentär gehardcodet um möglichst wenig 
Abhängigkeiten in diesem Hardfault-Zustand zu benötigen. Es werden hier 
auch sämtliche Config register für Clocks etc. konfiguriert, da man sich 
nie sicher sein kann, in welchem Zustand alle Peripheriemodule sind.
Dann Systemreset. Nach Reset wird erkeannt, dass die entsprechenden 
Flags im Backup-Ram gesetzt sind und das Fehlerhandling eingeleitet. 
Eventuell schreibe ich hier dann den Fehler in ein externes EEPROM.

Zur Überwachung von bspw. Stack Überlauf/Heap Überlauf, lege ich im 
Linkerskript einen n Wörter großen Bereich an, den ich mit dem RNG fülle 
und dann CRC prüfe. Sollte der Stack zu weit nach unten wachsen, oder 
der heap nach oben überschritten werden, wird der Bereich 
höchstwahrscheinlich invalid und die CRC Prüfung erkennt das. Diese CRC 
wird im Programm regelmäßig geprüft.

von Nop (Gast)


Lesenswert?

M. H. schrieb:

> Zur Überwachung von bspw. Stack Überlauf/Heap Überlauf, lege ich im
> Linkerskript einen n Wörter großen Bereich an, den ich mit dem RNG fülle
> und dann CRC prüfe. Sollte der Stack zu weit nach unten wachsen

Ich halte davon nicht soviel, weil der Canary-Ansatz nicht zuverlässig 
ist. Den Stack sollte man an den Anfang des RAMs legen und nicht ans 
Ende, damit man zuverlässig einen Hardfault bekommt. Das geht nicht bei 
allen Architekturen, weil mitunter ganz unten die Control-Register 
liegen, aber bei Cortex-M geht es.

Außerdem eine saubere Stackanalyse machen, weil die (anders als jede 
Runtime-Methode) auch den worst case erfaßt. Beispielsweise, wenn sich 
Interrupts maximal ungünstig ausgerechnet an der Stelle maximalen 
Stackverbrauchs des Hauptprogramms aufaddieren. Ist erstmal mehr Arbeit, 
die man aber beim Debuggen wieder einspart.

von M. Н. (Gast)


Lesenswert?

Nop schrieb:
> Ich halte davon nicht soviel, weil der Canary-Ansatz nicht zuverlässig
> ist. Den Stack sollte man an den Anfang des RAMs legen und nicht ans
> Ende

Das stimmt natürlich. Aber es gibt auch anforderungen, wo der Stack 
nicht unten sein kann. Es ist alles in allem ein Geraffel. Der Stack 
darf in erster Linie einfach nicht so groß werden. das ist ja auch am 
Rechner ein Problem. Der Bereich zwischen Stack und Heap ist zwar 
protected und löst eine Speicherverletzung aus. Wenn man jetzt aber ein 
array auf den Stack legt, das größer ist als diese Barriere (bei 32 bit 
systemen durchaus erreichbar), dann steht der Stackpointer voll im Heap 
ohne den Zwischenbereich durchlaufen zu haben. Der obige Ansatz ist 
keinesfalls eine rundum sorglos Methode.

Die beste Methode ist natürlich immer ein externer Monitoring Chip. Da 
haben wir mal einen aus nem ganz kleinen FPGA gebaut, der externer 
Watchdog etc. spielt und dann über weitere Abschaltwege auch die 
Möglichkeit hat bei komplett zerstörtem uC alles abzuschalten.

von M. Н. (Gast)


Lesenswert?

Mw E. schrieb:
> Vor dem Rücksprung also die Rücksprungadresse auf dem Stack austauschen.

Hierbei ist auch zu beachten, dass der Cortex-M relativ viel seines 
Stack-Handlings magisch in HW macht. Das ist aus SW Sicht sehr schön, da 
man eigentlich keine Assemblerroutinen braucht und alles in C 
realisierbar ist. Im Interrupt steht beispielsweise keine 
Rücksprungadresse auf dem Stack bzw im Link Register. Da steht eine 
Magic Number, die ihm sagt, wie er wieder aus dem Interrupt rauskommt 
und ob er floating point regster wieder herstellen muss etc. Da muss man 
etwas aufpassen.

Aus meiner Sicht macht es keinen Sinn aus dem Hardfault wieder in ein 
Programm zurückzuspringen, dass offensichtlich ja nicht richtig 
funktioniert an dieser Stelle.

Hardfaults sind in der Regel entweder Programmierfehler, die in der 
Entwicklung ausgeräumt werden müssen, oder tatsächlich unhandlebare 
Fehler, bei denne man einfach nur noch schauen kann, dass man einen 
sicheren Zustand einnimmt und möglichst viel vom Fehler für die Nachwelt 
festhält. Aber in das Programm zurückzuspringen ist meist keine gute 
Idee.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

M. H. schrieb:
> Im Interrupt steht beispielsweise keine
> Rücksprungadresse auf dem Stack bzw im Link Register. Da steht eine
> Magic Number, die ihm sagt, wie er wieder aus dem Interrupt rauskommt
> und ob er floating point regster wieder herstellen muss etc. Da muss man
> etwas aufpassen.

Die Number steht im Linkregister und sagt dem u.a. NVIC wo er zu gucken 
hat nach der Rücksprungadresse, die steht dann wiederrum auf dem Stack. 
Beim Cortex-M gibts ja 2 Stacks.
Ich hab oben nur aufgezeigt, dass es ginge, aber eben auch 
überkompliziert wäre.

M. H. schrieb:
> Aus meiner Sicht macht es keinen Sinn aus dem Hardfault wieder in ein
> Programm zurückzuspringen, dass offensichtlich ja nicht richtig
> funktioniert an dieser Stelle.

Der Ansatz oben springt ja auch nicht ins abgestürzte Programm zurück, 
sondern zu einer quasi neuen Init Methode, einem Notprogramm.

Im Endeffekt sind wir uns ja einig, dass ein Rücksrprung (egal wo hin) 
unnötig ist un es im Hardfault Handler ohne IRQs abgehandelt werden 
sollte.

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.