Hi Leute,
ich habe ein source code fabriziert der nach einer weile in die
HardFault_Handler() funktion springt. jedoch weiss ich nicht was das
verursacht könnt ihr mir einige tipps geben wie ich das debuggen kann?
ich benutze IAR 5.30 und die standard lib 3.3.0 ,der controller ist der
stm32f103cb.
ich habe einiges dazu im internet gefunden leider war nix dabei was mir
wirklich weiter geholfen hat.
danke!
Der Spring da rein wenn man aus irgend einem Grund auf einer Adresse was
lese/schrieben möchte, auf der weder Flash noch Ram und auch keine
Pheriperie ist.
Vermutlich hast Du ein Zeiger, der irgend wo was lesen/schreiben soll
(z.B. Index-Variable eines Arrays, das einen falschen viel zu großen
Wert hat und somit ins nirvana Zeigt.
PS: Ich mag diese Fehlermeldung auch nicht, da man nicht weiß an welcher
Programmposition das auftrat. Zumindest habe ich das noch nicht
herausgefunden.
HI Leute,
WOW das ging ja schnell. Also es ist kein RTOS. und Ja der Code bleibt
jedesmal an der selben Stelle stehen.
Aber es muss doch eine Möglichkkeit geben das problem irgendwie zu
finden oder?
im moment habe ich ein "workaround" geschaffen in dem ich die Funktion
NVIC_SystemReset() jedesmal aufrufe, wenn ich in den Handler gerate,
jedoch würde ich gern herausfinden was die Ursache für den Handler ist
Es gibt ein paar System Exceptions, die je nach Einstellung von
Prioritäten nicht im dafür vorgesehenen Handler sondern automatisch im
Hardfault-Handler landen. Stellt man die anders ein, dann weiss man
schon mehr, nämlich welche Exception es wirklich war.
Ausserdem ist es nicht so, dass man im Handler komplett ahnungslos ist.
Die Returnadresse ist bekannt, so dass man rauskriegt an welcher
Programmposition man rausflog. Bei MemFaults kriegt an zudem raus, um
welchen Zugriff es sich handelte.
Das kann man beispielsweise über einen Debugger ermittelt. Manche
schreiben sich aber auch einen komplexen Fault-Handler, der alle
relevante Information einsammelt und irgendwohin dumpt.
Ein Hardfault ist eigentlich auch "nur" ein Interrupt. Das bedeutet,
dass sich auf dem Stack auch die Rücksprungadresse befindet. Und das ist
auch in etwa die Adresse, an der die Anweisung zu finden ist, welche den
Hardfault ausgelöst hat. Ganz genau passt das manchmal nicht, da die CPU
(sofern sie noch in der Lage dazu ist) ganz gern mal schon noch die
nächsten paar Befehlt ausführt, bis sie merkt, dass da ein Hardfault
war.
Aber trotzdem hilft es schonmal sehr viel im Hardfault Handler die CPU
anzuhalten und an SP+24 nachzuschauen: In der Nähe der dort zu findenden
Adresse wurde der Hardfault ausgelöst.
an Hannes S.: also ich stoppe den Debugger und kann jetzt wo
nachschauen
was in SP+24 steht?
ich habe unter IAR die Möglichkeit mir den CSTACK
anzuschauen.
wenn du das damit meinst, steht da jetzt eine Tabelle:
Location | Data
0x20000390 | 0x08
+1 | 0x00
. . .
. . .
. . .
+24 | 0x54
und was sagt mir das jetzt? sorry aber da fehlt mir einfach das know
how.
an A. K.:
also diesen thread habe ich mir jetzt angesehen und da steht was von
"void hard_fault_handler_c(unsigned int * hardfault_args)" aber ich habe
unter stm32f10x_it.c eine funktion die keine übergabe parameter hat
sondern nur void: void HardFault_Handler(void)
jetzt könnte ich das mit dem C code einfach kopieren aber wie sieht es
mit dem assembler bereich aus wie kann man dem jetzt die parameter
übergabe beibringen. wenn ich mich jetzt nicht irre müsste doch im
startup_stm32f10x_md.s die folgenden Zeilen irgendwie abgeändert werden:
PUBWEAK UsageFault_Handler
SECTION .text:CODE:REORDER(1)
UsageFault_Handler
B UsageFault_Handler
Yep, das CSTACK Fenster ist schonmal richtig. Jetzt musst Du nur noch
den Wert aus +27 bis +24 auslesen, beginnend bei +27 und Dir dann eine
Adresse draus bauen. Wahrscheinlich dürfte in +27=0x08 und
26=0x00 drinstehen. Das würde dann 0x0800xx54 bedeuten. Diese Adresse
suchst Du nun im Disassambly Window. Und schon bist Du an der Stelle, an
der das Unglück seinen Lauf nahm...
Ach ja: Im Hardfault Handler sollte kein Code drinstehen, der ein
sichern eines weiteren Registers auf dem Stack bedingt, denn dadurch
würde sich die Adresse verschieben. Sicherheitshalber also nur ein
__no_operation() in den Handler und dann den Brakpoint drauf.
also ich habe mal nachgeschaut und habe da jetzt folgende adresse
Location | Data
0x20000390 | 0x08
. . .
. . .
. . .
+24 | 0x54
+25 | 0xF6
+26 | 0x0B
+27 | 0xAC
also müsste ich auf 0xAC0BF654 ist das so richtig? Wie kommst du
eigentlich auf +24 bis +27?
und ist es normal das der inhalt (spalte Data) sich jedesmal ändert?
Mit etwas Glück und IARs Hilfe übernimmt diese Suche nach den Registern
und deren Decodierung dein Debugger bereits selbst. Jedenfalls tut das
der von Keil:
http://www.keil.com/appnotes/files/apnt209.pdf
An 0xAC0BF654 existiert kein Flash/RAM. Der Sprung an diese Adresse
dürfte dann auch der Grund für den Hardfault sein. Wieso das passiert?
Mir fällt da eigentlich nur ein Nicht/falsch initialisierter
Funktionspointer ein. Allerdings kann man in diesem Fall nicht so
einfach sagen, wo das passiert ist.
Wie ich auf +24 komme? Das ergibt sich aus der Sicherung der Register
bei jedem Aufruf eines Interrupts:
SP+0: R0
+4: R1
+8: R2
+12: R3
+16: R12
+20: LR
+24: PC
+28: xPSR
Wie schon gesagt: Sofern nötig, veranlasst der Compiler noch die
Sicherung weitere Register. Dies hängt vom Code im Handler ab.
Wenn der komplette Code im Flash liegt, sollten PC und LR immer Adressen
beginnend mit 0x080xxxxx enthalten.
Hallo zusammen,
wollte nochmal an den Thread anknüpfen, da ich gerade ein ähnliches
Problem habe.
Kommt man nur mit IAR in den SP+24? Oder ist das auch mit Eclipse
möglich?