cfg: ftdi icdi enable srst open drain config
[fw/openocd] / testing / examples / cortex / fault.c
1 /*
2  * COMPILE:  arm-none-eabi-gcc -mthumb -march=armv7-m ...
3  *      ... plus, provide at least a default exception vector table.
4  *
5  * RUN:  this is best run from SRAM.  It starts at main() then triggers
6  * a fault before more than a handful of instructions have executed.
7  * Run each test case in two modes:
8  *
9  * (1)  Faults caught on the Cortex-M3.  Default handlers are usually
10  *      loop-to-self NOPs, so a debugger won't notice faults until they
11  *      halt the core and examine xSPR and other registers.
12  *
13  *      To verify the fault triggered, issue "halt" from OpenOCD; you
14  *      should be told about the fault and (some of) its details.
15  *      Then it's time to run the next test.
16  *
17  *      NOTE however that "reset" will restart everything; verify that
18  *      case by observing your reset handler doing its normal work.
19  *
20  * (2)  Faults intercepted by OpenOCD "vector_catch ..." commands.
21  *
22  *      OpenOCD should tell you about the fault, and show the same
23  *      details, without your "halt" command.
24  *
25  * Someday, a fancy version of this code could provide a vector table and
26  * fault handlers which use semihosting (when that works on Cortex-M3) to
27  * report what happened, again without needing a "halt" command.
28  */
29
30
31 /* These symbols match the OpenOCD "cortex_m3 vector_catch" bit names. */
32 enum vc_case {
33         hard_err,
34         int_err,
35         bus_err,
36         state_err,
37         chk_err,
38         nocp_err,
39         mm_err,
40         reset,
41 };
42
43 /* REVISIT come up with a way to avoid recompiling, maybe:
44  *  - write it in RAM before starting
45  *  - compiled-in BKPT, manual patch of r0, then resume
46  *  - ...
47  */
48
49 #ifndef VC_ID
50 #warning "no VC_ID ... using reset"
51 #define VC_ID reset
52 #endif
53
54 int main(void) __attribute__ ((externally_visible, noreturn));
55
56 /*
57  * Trigger various Cortex-M3 faults to verify that OpenOCD behaves OK
58  * in terms of its vector_catch handling.
59  *
60  * Fault handling should be left entirely up to the application code
61  * UNLESS a "vector_catch" command tells OpenOCD to intercept a fault.
62  *
63  * See ARMv7-M architecure spec table B1-9 for the list of faults and
64  * their mappings to the vector catch bits.
65  */
66 int main(void)
67 {
68         /* One test case for each vector catch bit.  We're not doing
69          * hardware testing; so it doesn't matter when some DEMCR bits
70          * could apply in multiple ways.
71          */
72         switch (VC_ID) {
73
74         /* "cortex_m3 vector_catch hard_err" */
75         case hard_err:
76                 /* FORCED - Fault escalation */
77
78                 /* FIXME code this */
79                 break;
80
81         /* "cortex_m3 vector_catch int_err" */
82         case int_err:
83                 /* STKERR -- Exception stack BusFault */
84
85                 /* FIXME code this */
86                 break;
87
88         /* "cortex_m3 vector_catch bus_err" */
89         case bus_err:
90                 /* PRECISERR -- precise data bus read
91                  * Here we assume a Cortex-M3 with 512 MBytes SRAM is very
92                  * unlikely, so the last SRAM byte isn't a valid address.
93                  */
94                 __asm__ volatile(
95                         "mov r0, #0x3fffffff\n"
96                         "ldrb r0, [r0]\n"
97                         );
98                 break;
99
100         /* "cortex_m3 vector_catch state_err" */
101         case state_err:
102                 /* UNDEFINSTR -- architectural undefined instruction */
103                 __asm__ volatile(".hword 0xde00");
104                 break;
105
106         /* "cortex_m3 vector_catch chk_err" */
107         case chk_err:
108                 /* UNALIGNED ldm */
109                 __asm__ volatile(
110                         "mov r0, #1\n"
111                         "ldm r0, {r1, r2}\n"
112                         );
113                 break;
114
115         /* "cortex_m3 vector_catch nocp_err" */
116         case nocp_err:
117                 /* NOCP ... Cortex-M3 has no coprocessors (like CP14 DCC),
118                  * but these instructions are allowed by ARMv7-M.
119                  */
120                 __asm__ volatile("mrc p14, 0, r0, c0, c5, 0");
121                 break;
122
123         /* "cortex_m3 vector_catch mm_err" */
124         case mm_err:
125                 /* IACCVIOL -- instruction fetch from an XN region */
126                 __asm__ volatile(
127                         "mov r0, #0xe0000000\n"
128                         "mov pc, r0\n"
129                         );
130                 break;
131
132         /* "cortex_m3 vector_catch reset" */
133         case reset:
134                 __asm__ volatile(
135                         /* r1 = SYSRESETREQ */
136                         "mov r1, #0x0004\n"
137                         /* r1 |= VECTKEY */
138                         "movt r1, #0x05fa\n"
139                         /* r0 = &AIRCR */
140                         "mov r0, #0xed00\n"
141                         "add r0, #0xc\n"
142                         "movt r0, #0xe000\n"
143                         /* AIRCR = ... */
144                         "str r1, [r0, #0]\n"
145                         );
146                 break;
147         }
148
149         /* don't return */
150         while (1)
151                 continue;
152 }