Forum: Mikrocontroller und Digitale Elektronik Hard Fault ARM Cortex-M4


von Andi K. (fry12)


Lesenswert?

Hallo Leute!

Ich frage mich gerade, was man (ganz Allgemein) bei einem Hard Fault 
eines Cortex-M4 (oder -M3) noch machen kann.

Klar, man kann sich im Hard Fault Handler den Stack Frame und damit den 
Program Counter etc. sowie verschiedene Statusregister zu dein einzelnen 
Faults anschauen. Aber was bleiben dann noch für Möglichkeiten zu einer 
vernünftigen "Lösung" des Problems übrig?

* Fehlermeldung bspw. an den PC per USB ausgeben: Funktioniert nicht, da 
USB auf Interrupts angewiesen ist (zumindest das von mir verwendete 
Modul vom Atmel Software Framework) und diese Interrupts nicht 
ausgeführt werden, da sie eine niedrigere Priorität als der Exception 
Handler haben.

* Softwarereset des Controllers: Funktioniert nicht, falls Reset-Pin 
extern beschalten ist und auf High gezogen wird.

Was sagen die Profis zu dem Thema? Gibt es Ideen, was an Maßnahmen 
überhaupt möglich ist?

Ich habe leider kein konkretes Anwendungsszenario, deswegen musste ich 
meine Fragestellung so allgemein halten ;)

Vielen Dank schon mal :)

von (prx) A. K. (prx)


Lesenswert?

Andi K. schrieb:
> Aber was bleiben dann noch für Möglichkeiten zu einer
> vernünftigen "Lösung" des Problems übrig?

Normerweise kriegst du den Hard Fault, wenn es keine vernünftige Lösung 
mehr gibt. Aber drauf achten, dass in Standardeinstellung ein paar 
andere Faults nicht selbst auftreten, sondern effektiv auf dem Hard 
Fault gemappt werden. Das kann man ändern.

von (prx) A. K. (prx)


Lesenswert?

Andi K. schrieb:
> * Softwarereset des Controllers: Funktioniert nicht, falls Reset-Pin
> extern beschalten ist und auf High gezogen wird.

Gegen Konstruktionsfehler ist kein Kraut gewachsen. Der Reset Pin sollte 
OC/OD beschaltet werden.

von holger (Gast)


Lesenswert?

>* Fehlermeldung bspw. an den PC per USB ausgeben: Funktioniert nicht, da
>USB auf Interrupts angewiesen ist

Man kann Fehlermeldungen per UART ausgeben da man den auch
ohne Interrupt benutzen kann.

von Jim M. (turboj)


Lesenswert?

Andi K. schrieb:
> * Softwarereset des Controllers: Funktioniert nicht, falls Reset-Pin
> extern beschalten ist und auf High gezogen wird.

Bei welchem Controller? NVIC_SystemReset() sollte überall funktionieren, 
das ist ein internes Signal. Es gibt auch noch ein VECTRESET Bit, das 
nur den Core selbst resettet - aber das will man praktisch nie.

von Lothar (Gast)


Lesenswert?

Andi K. schrieb:
> Fehlermeldung bspw. an den PC per USB ausgeben: Funktioniert nicht, da
> USB auf Interrupts angewiesen ist

Doch das funktioniert:

1. Zwei Stacks verwenden: PSP für den Task und MSP für die Handler (also 
auch Interrupts)

2. Aus dem Hard Fault Handler (MSP) zu einer Speicherstelle mit SVC zur 
Fehlerbehandlung "zurückkehren"

3. Im SVC Handler (MSP) die USB Ausgabe machen.

Abgesehen davon sollte vor dem Hard Fault noch der MemManage Fault 
implementiert werden, meistens läuft nämlich "nur" der Stack über.

von Ingo (Gast)


Lesenswert?

Der Hardfault tritt auch sehr schnell bei zu hoher Frequenz auf, wenn 
man sich mal mit der PLL vertut ;)

von W.S. (Gast)


Lesenswert?

Andi K. schrieb:
> Aber was bleiben dann noch für Möglichkeiten zu einer
> vernünftigen "Lösung" des Problems übrig?

Das hängt von deiner Anwendung ab.

In den meisten Fällen benutzen die Anfänger im Programmieren eben den 
Startup-Code, den sie als Default bei der IDE ihrer Wahl eben so 
vorfinden. Und so führt jeder blöde Fehler (NMI, Hardfault, Spurious, 
Data Abort und so weiter je nach konkreter CPU) zu einem "B ." was 
m.M.n. die dümmste aller Varianten ist.

Ich mache das zumeist so, daß jeder dieser unabgedeckten Interrupts das 
ganze System neu startet, also einen Warmstart auslöst. Obendrein setze 
ich noch ein Fehlerflag, so daß später in main bei Bedarf nachgeschaut 
werden kann, was denn passiert war. Auf diese Weise kommt der µC 
wenigstens wieder so gut es geht auf die Beine und spielt nicht toter 
Mann.

Also: alle [weak] Interrupts bei dem fertigen Projekt abfangen und ggf. 
nen Neustart auslösen. Für evtl. Debugging zuvor kann man es hingegen 
halten wie man will.

W.S.

von Dr. Sommer (Gast)


Lesenswert?

W.S. schrieb:
> In den meisten Fällen benutzen die Anfänger im Programmieren eben den
> Startup-Code, den sie als Default bei der IDE ihrer Wahl eben so
> vorfinden.

Und genau das kann man auch behalten, wenn man die Faults behandeln 
will. Das muss man nämlich nicht in Assembler und auch nicht im 
Startupcode tun. Außerdem ist ein Fault ein Programm-Fehler und nicht 
eine temporäre Befindlichkeit des Prozessors. Daher sollte man die in 
vielen Anwendungen nicht einfach ignorieren und neu starten, sondern die 
Hardware in einen sicheren Zustand bringen und dann doch in 
Endlosschleife stehen bleiben.
Wenn es für das Funktionieren deiner Geräte unerlässlich ist, bei einem 
Fehler neuzustarten, solltest du vielleicht mal überlegen die 
tatsächlichen Fehler im Code zu korrigieren ...

von Schaulus Tiger (Gast)


Lesenswert?

W.S. schrieb:

> Ich mache das zumeist so, daß jeder dieser unabgedeckten Interrupts
> das ganze System neu startet, also einen Warmstart auslöst.

und zwar nicht sofort, sondern nach einigen Sekunden bis zu etlichen 
Minuten. In der Zwischenzeit wird eine mehr oder weniger ausführliche 
Fehlermeldung ausgegeben, wenigstens mit LED-Blinkcode. Falls der Fehler 
wiederholt auftritt, müsste man das eigentlich beim Startup abfangen. 
Ansonsten kann so eine Pause das Gerät vor allzu großem Dauerstress 
bewahren.

von W.S. (Gast)


Lesenswert?

Schaulus Tiger schrieb:
> und zwar nicht sofort

Das hängt - wie bereits geschrieben - von der konkreten Anwendung ab. Es 
gibt ne Menge Anwendungen, wo es verdammt wichtig ist, zu allererst mal 
einen möglichst sicheren Zustand herbeizuführen - und das sollte in 
solchen Fällen möglichst direkt im Startupcode und möglichst ohne 
UP-Call's passieren, denn es könnte ja z.B. sein, daß der RAM ne Macke 
hat.

Naja - und das mit der Fehlerlampe ist auch so eine Sache. Viele µC 
stecken an Stellen, wo niemals irgend einer hinschaut bzw. hinschauen 
kann. Da hilft ne LED oder ne V24-Ausgabe auch bloß nicht.

W.S.

von Andi K. (fry12)


Lesenswert?

Vielen Dank für eure Anregungen! Ich merk schon, dass ich doch noch 
nicht so fortgeschritten bin wie gedacht, sondern eher ein blutiger 
Anfänger ;)

Sehr interessant ist natürlich, dass einige einen Neustart für sinnvoll 
halten, nachdem die Hardware in einen sicheren Zustand gebracht wurde, 
während anderen genau davon abraten und das Gegenteil, d.h. eine 
Endlosscheleife präferieren.

Jim Meba schrieb:
> Bei welchem Controller? NVIC_SystemReset() sollte überall funktionieren,
> das ist ein internes Signal. Es gibt auch noch ein VECTRESET Bit, das
> nur den Core selbst resettet - aber das will man praktisch nie
Ich habs nochmal genauer überprüft und NVIC_SystemReset() funktioniert 
wie es soll ;)

von Schaulus Tiger (Gast)


Lesenswert?

Andi K. schrieb:

> Sehr interessant ist natürlich, dass einige einen Neustart für sinnvoll
> halten, nachdem die Hardware in einen sicheren Zustand gebracht wurde,
> während anderen genau davon abraten und das Gegenteil, d.h. eine
> Endlosscheleife präferieren.

Wobei "einige" für "einige Geräte", nicht für "einige Leute" steht ;)
Und was ein sicherer Zustand ist, kann auch noch vom aktuellen 
Betriebszustand abhängen. Schon eine normale Heizungspumpe soll man 
nicht abschalten, wenn der Brenner läuft. Aber wenn das Oel alle ist, 
möchte man nicht sinnlos die Wärme aus dem Speichertank pumpen.

Aber eine Endlosschleife ohne jede Meldung geht garnicht. Na gut, 
meinetwegen wenn ein Debugger angeschlossen ist. Das gesagt habend, 
fällt mir ein Überwachungsgerät ein. Da lasse ich als "endgültigen" 
Reset die eigene Sicherung durchbrennen... Aber dann geht immer noch die 
24V-LED aus!

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.