Hallo, ich habe einen SAME53, AT Studio7 und ICE-Debugger. Das Problem ist, dass der Prozessor nach 3 Sek. im DummyHandler() landet. Gibt es eine Möglichkeit zu erkennen, welcher Interrupt vorher ausgelöst wurde?
Klar, das steht im IPSR Register. __get_IPSR ist Dein Freund.
@ Max H. Vielen Dank für die schnelle Hilfe. Gibts irgendwo Doku zum Register? Kann das der Debugger nicht lesen / anzeigen?
Alex schrieb: > Gibts irgendwo Doku zum Register Ja, im "ARMv7-M Architecture Reference Manual" auf Seite 517. Die Bedeutung der Zahl ist auf S. 525 abgebildet: - Wert 0 bedeutet kein Interrupt aktiv - Wert 1 bedeutet Reset wird gerade durchgeführt, kann eigentlich nie angezeigt werden - Wert 2 bedeutet NMI Interrupt - Wert 3 bedeutet HardFault Usw. - Werte ab 16 sind die "normalen" Interrupts, also die die von der Peripherie ausgelöst werden. Bei deinem Controller sind diese hier definiert, auf die dortige Angabe von "Line" musst du 16 aufaddieren: https://onlinedocs.microchip.com/oxy/GUID-F5813793-E016-46F5-A9E2-718D8BCED496-en-US-14/GUID-DA8CB38A-18D7-4512-965B-BB439142B281.html Heißt also, IPSR=16 ist PM - Power Manager Interrupt, IPSR=17 ist MCLK - Main Clock usw. Alex schrieb: > Kann das der Debugger nicht lesen / anzeigen? Kann er grundsätzlich, weiß nicht wie Microchip das macht, eventuell zeigt der Debugger nur das xPSR an. Das IPSR sind die unteren 9 Bits vom xPSR. Schau dich mal in der Debugger-GUI um. Notfalls schreibst du sowas hin:
1 | void DummyHandler(void) { |
2 | volatile uint32_t myIPSR = __get_IPSR (); |
3 | }
|
Dank "volatile" wird die Variable nicht wegoptimiert sodass du sie im Debugger auslesen kannst. Das Register ist kein "normales" Peripherieregister mit Speicheradresse, sondern ein Spezialregister des Prozessors, welches über die "mrs" Instruktion ausgelesen werden muss, was in der __get_IPSR Funktion passiert. Der Debugger hat aber einen direkten Zugriff darauf.
OK, IPSR ist 3237. Das wäre INT5? Die KI meint das sei TC1-INT, wenn ich aber in die startupxxx schaue: /* 5 OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */ Kommt mir alles komisch vor... Hi-Hi-Hilfe...
ICSR meldet INT3 aktiv, also XOSCFAIL1 ??? Was ist da los, dass nach 3 Sek. der stabile Osc auf einmal ausfällt?
Alex schrieb: > ICSR meldet INT3 aktiv, Die unteren 9 Bits vom ICSR haben den gleichen Inhalt von IPSR - aber was genau hast du jetzt ausgelesen? Welcher Wert genau steht drin? Wenn 3 drin steht ist es wie gesagt der HardFault Handler. Das ist meistens (immer?) die Folge eines Software-Fehlers, also z.B. Zugriff auf ungültige Adressen/Pointer oder Ausführung einer ungültigen Instruktion. In den Registern CFSR, BFAR, MMFAR, HFSR finden sich mehr Informationen zum Fehler. Nur wenn 19 drin steht ist es ein XOSCFAIL1 oder XOSCRDY1. Übrigens: Meistens kannst du im Debugger einen Backtrace/Stacktrace sehen, also von wo aus die aktuelle Funktion aufgerufen wurde, von wo diese wiederum aufgerufen wurde usw. bis zur main(). Bei Exceptions/Interrupts, inklusive dem BusFault, gilt das auch, d.h. du kannst dort sehen welche Codestelle unterbrochen wurde als der Interrupt aufgetreten ist, außer der Speicher/Stack ist durch den Fehler zu sehr "zerwürfelt" worden. Aber Achtung: Manche HardFault-Interrupts treten erst ein paar Instruktionen nach dem eigentlichen Fehler auf, der Fehler kann also etwas über der angezeigten Codestelle sein. Eventuell kannst du im Stacktrace also sofort sehen wo etwas schief gelaufen ist, also z.B. Zugriff auf ungültigen Pointer.
@Niklas G. Vielen,vielen Dank für deine ausführlichen Infos. Im Debugger im Fenster "Prozessor Status" findet man "Interupt Program Status" (aka. IPSR!). Hier wird der Wert 3 - Hard Fault - angezeigt. Genau das hatte ich schon, dass bei einer &Var-Adressberechnung einfach ein Nullpointer erzeugt wurde, weil die Variable nicht volatile gemacht wurde... PS: __get_IPSR liefert dagegen 0xCA5 ????
Alex schrieb: > Genau das hatte ich schon, dass bei einer &Var-Adressberechnung einfach > ein Nullpointer erzeugt wurde, weil die Variable nicht volatile gemacht > wurde... Kann nicht sein, Variablen werden nicht wegoptimiert wenn man ihre Adresse anfordert, außer die Adresse wird nirgends genutzt. Alex schrieb: > __get_IPSR liefert dagegen 0xCA5 ???? Dann hat der Debugger wohl die Variable nicht richtig "erkannt", der Ausführungsschritt ist an der falschen Stelle oder es wurde was wegoptimiert. Alex schrieb: > Hier wird der Wert 3 - Hard Fault - angezeigt. Dann also doch kein XOSCFAIL1/XOSCRDY1 😉
Ja genau! So, die Frage ist nun, wo er den Nullpointer benutzen wollte. Im Debugger des Atmel Studios 7 habe ich nirgends ein Fenster mit dem Aufrufstack gefunden.
Alex schrieb: > Im Debugger des Atmel Studios 7 habe ich nirgends ein Fenster mit dem > Aufrufstack gefunden. https://www.microchip.com/content/dam/mchp/documents/atmel-start/Atmel-Studio-7-User-Guide.pdf S. 187 Call Stack shows the hierarchical information of callers of the current method. By default, the Call Stack window displays the name of each function. To display Call Stack, Click the menu, Debug → Windows → Call Stack. Den Call Stack sollte man eigentlich immer im Blick haben, der ist extrem wertvoll. Andere IDEs zeigen den standardmäßig immer an beim Debugger, keine Ahnung warum das bei Atmel Studio nicht so ist. Ist ja auch schon ziemlich alt...
:
Bearbeitet durch User
Vieelen Dank für deine Geduld! Ich hätte die Tomaten vor meinen Augen zum Mittag essen sollen... OK. Jetzt sagt er: .elf Line 548. Äh, ja super. Sicher gibt es irgend einen Trick aus elf-Datei die Quellcode-Datei und Zeile zu finden? Es müsste eine µC-Sherlock Holmess-Zusatzausbildung geben.
Alex schrieb: > Jetzt sagt er: .elf Line 548 Zeig mal nen Screenshot. Alex schrieb: > Äh, ja super. Sicher gibt es irgend einen Trick aus elf-Datei die > Quellcode-Datei und Zeile zu finden Das macht der Debugger eigentlich vollautomatisch, wenn du mit Debuginformationen kompiliert hast, also -g an den Compiler. Es kann aber sein dass aufgrund deines ursprünglichen Fehlers die Stack-Informationen kaputt sind und die vom Debugger gelesene Adresse ganz falsch ist, dann bringt die Debug Information nix. Alex schrieb: > Es müsste eine µC-Sherlock Holmess-Zusatzausbildung geben. Hihi, ja Debuggen ist eine Kunst.
...Grr. Eine Zeile 548 ist "zufälliger Weise" die erste Zeile (IPSR_r= __get_IPSR; ) im Dummy-Handler! Na wer hätte das gedacht. Ich hab noch Program Counter Trace Fenster gefunden. Nur wie schaltet man das Recording ein?
Alex schrieb: > .Grr. > Eine Zeile 548 ist "zufälliger Weise" die erste Zeile (IPSR_r= > __get_IPSR; ) im Dummy-Handler! Das ist halt der oberste Level vom Call Stack. Relevant sind die Level darunter. Zeig doch bitte mal einen Screenshot direkt von dem Moment wo es im DummyHandler gelandet ist, mit folgendem sichtbar: - Sourcecode - Call Stack - Register View (Debug → Windows → Register View). Lese hier bitte den Inhalt des Stack Pointer aus (SP oder MSP oder r13 genannt) - Memory View (Debug → Windows → Memory view). Gebe den eben ausgelesenen Inhalt des Stack Pointer bei "Address" ein. Falls möglich stell beim Ausgabeformat 32bit hexadecimal unsigned o.ä. ein. Lese die Register CFSR, BFAR, MMFAR, HFSR aus. Sonst ist das alles Kaffeesatzlesen. Alex schrieb: > Nur wie schaltet man das Recording ein? Siehe Kapitel 4.19 der zuvor verlinkten Anleitung.
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.