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
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.
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?
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....
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.
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.
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.
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.
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.
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.