Michael B. schrieb:
> An dieser Stelle sei angemerkt, dass mit "Fehlerursache per printf
> ausgeben" hier nicht gemeint ist, dass dann dort steht: "Sie haben einen
> falschen Speicherbereich beschrieben", sondern du bekommst die aktuellen
> Registerwerte ausgegeben und vielleicht kannst du dir auch noch die
> aufrufende Codezeile ausgeben lassen (wenn dein Debugger das nicht
> sowieso tut).
Es ist wesentlich mehr als die aktuellen Registerwerte. Je nach Fault
wird in den Fault Status Registern ziemlich genau die Stelle
beschrieben. Es kommt der Sache, die Du vermisst, ziemlich nahe.
Beispielsweise erzeugt einen "read from invalid memory adddress" einen
synchronen Fault, so dass die Instruktion und die Zugriffsadresse exakt
in den Statusregistern steht ("precise").
Beim Schreiben erzeugt er einen asynchronen Fault (wg. eines Puffers),
der Fault schlägt ein paar Instruktionen später auf ("imprecise").
Beispiel für "read from invalid memory access"
1 | ERR Hard fault
|
2 | ERR R0 : 0x2000002a
|
3 | ERR R1 : 0x80035e1
|
4 | ERR R2 : 0x30000000
|
5 | ERR R3 : 0x30000000
|
6 | ERR R12 : 0x1000000
|
7 | ERR LR : 0x8001e35
|
8 | ERR PC : 0x8001e3a
|
9 | ERR xPSR : 0x61000200
|
10 | ERR CCR : 0x218 0b1000011000
|
11 | ERR Bit 3: Trap unalign : 1
|
12 | ERR Bit 4: Trap div by zero: 1
|
13 | ERR Bit 9: Stack align : 1
|
14 | ERR SHCSR: 0x0 0b0
|
15 | ERR Bit 0: Mem fault : 0
|
16 | ERR Bit 1: Bus fault : 0
|
17 | ERR Bit 3: Usage fault: 0
|
18 | ERR CFSR : 0x8200 0b1000001000000000
|
19 | ERR UFSR: 0b0
|
20 | ERR Bit 16: Undef instr: 0
|
21 | ERR Bit 17: Inv state : 0
|
22 | ERR Bit 24: Unaligned : 0
|
23 | ERR Bit 25: Div by zero: 0
|
24 | ERR BFSR: 0b10
|
25 | ERR Bit 8: Instr bus error : 0
|
26 | ERR Bit 9: Precise : 1
|
27 | ERR Bit 10: Imprecise : 0
|
28 | ERR Bit 15: BFAR contains addr: 1
|
29 | ERR MFSR: 0x0
|
30 | ERR Bit 0: Instr access violation: 0
|
31 | ERR Bit 1: Data access violation : 0
|
32 | ERR Bit 7: MFAR contains addr : 0
|
33 | ERR HFSR : 0x40000000 0b1000000000000000000000000000000
|
34 | ERR Bit 30: Escalation to hard fault: 1
|
35 | ERR DFSR : 0x9 0b1001
|
36 | ERR Bit 0: Halted: 1
|
37 | ERR Bit 1: BKPT : 0
|
38 | ERR Bit 3: VCATCH: 1
|
39 | ERR AFSR: 0x0 0b0
|
40 | ERR Mem fault addr MMFAR: 0x30000000
|
41 | ERR Bus fault addr BFAR : 0x30000000
|
"PC" zeigt die Adresse des Befehls,
"Precise" sagt aus, dass diese Adresse exakt stimmt.
"BFAR contains addr" sagt aus, das im BFAR exakt die Zieladresse des
Zugriffes steht.
Diese Fehlerrückmeldung sind m. E. einer der wichtigsten Dinge bei einer
µC-Architektur (beim PIC32 sind das m. W. die "Exceptions").
Wichtig ist, dass diese Fehler einen Fault auslösen, und dass dieser
angezeigt werden kann. Es ist ziemlich gefährlich, wenn der µC einfach
weitermacht, und (viel) später auf die Nase fällt.
Das Thema hat eine gewisse Komplexität. Der initiale Aufwand lohnt sich,
da man mittelfristig ein Werkzeug zur Hand hat, das m. A. nach wichtiger
als ein Debugger ist - denn dieser hängt im Zweifel nicht am µC, wenn es
knallt.
Beim CM0 ist das sehr viel reduzierter (Statusregister), so dass es sich
lohnt, während der Entwicklung einen CM3/CM4 einzusetzen. Beim letzteren
kommen noch weitere Statusregister für die FPU dazu.
LTC1043 schrieb im Beitrag #2989639:
> Gibt sicher auch noch andere Quellen für Infos.
Die (und ich) haben vermutlich alle von Joseph Yiu abgeschrieben,
welcher "The Definitive Guide to the ARM Cortex-M3" geschrieben hat.
Das sieht man daran, dass in der Deklaration "unsigned int" verwendet
wird, aber beim cast "unsigned long". Das ist beim 32-Bitter das
gleiche, es wäre aber ziemlich zufällig, dass dies nicht durch "Copy &
Paste" enstanden ist :-)
1 | unsigned int stacked_r0;
|
2 | unsigned int stacked_r1;
|
3 | unsigned int stacked_r2;
|
4 | unsigned int stacked_r3;
|
5 | unsigned int stacked_r12;
|
6 | unsigned int stacked_lr;
|
7 | unsigned int stacked_pc;
|
8 | unsigned int stacked_psr;
|
9 |
|
10 | stacked_r0 = ((unsigned long) hardfault_args[0]);
|
11 | stacked_r1 = ((unsigned long) hardfault_args[1]);
|
12 | stacked_r2 = ((unsigned long) hardfault_args[2]);
|
13 | stacked_r3 = ((unsigned long) hardfault_args[3]);
|