blob: 2cb3064ff83785ca27b4731f2b90d04cfff7673f [file] [log] [blame]
Armando Montaneza9ca9992021-01-26 17:06:10 -08001.. _module-pw_cpu_exception_cortex_m:
Armando Montanez5104cd62019-12-10 14:36:43 -08002
Armando Montaneza9ca9992021-01-26 17:06:10 -08003-------------------------
4pw_cpu_exception_cortex_m
5-------------------------
Armando Montanez5104cd62019-12-10 14:36:43 -08006This backend provides an ARMv7-M implementation for the CPU exception module
7frontend. See the CPU exception frontend module description for more
8information.
9
10Setup
11=====
12There are a few ways to set up the ARMv7-M exception handler so the
13application's exception handler is properly called during an exception.
14
15**1. Use existing CMSIS functions**
Armando Montaneza9ca9992021-01-26 17:06:10 -080016 Inside of CMSIS fault handler functions, branch to ``pw_cpu_exception_Entry``.
Armando Montanez5104cd62019-12-10 14:36:43 -080017
18 .. code-block:: cpp
19
20 __attribute__((naked)) void HardFault_Handler(void) {
21 asm volatile(
Armando Montaneza9ca9992021-01-26 17:06:10 -080022 " ldr r0, =pw_cpu_exception_Entry \n"
Armando Montanez5104cd62019-12-10 14:36:43 -080023 " bx r0 \n");
24 }
25
26**2. Modify a startup file**
27 Assembly startup files for some microcontrollers initialize the interrupt
28 vector table. The functions to call for fault handlers can be changed here.
29 For ARMv7-M, the fault handlers are indexes 3 to 6 of the interrupt vector
30 table. It's also may be helpful to redirect the NMI handler to the entry
31 function (if it's otherwise unused in your project).
32
33 Default:
34
35 .. code-block:: cpp
36
37 __isr_vector_table:
38 .word __stack_start
39 .word Reset_Handler
40 .word NMI_Handler
41 .word HardFault_Handler
42 .word MemManage_Handler
43 .word BusFault_Handler
44 .word UsageFault_Handler
45
46 Using CPU exception module:
47
48 .. code-block:: cpp
49
50 __isr_vector_table:
51 .word __stack_start
52 .word Reset_Handler
Armando Montaneza9ca9992021-01-26 17:06:10 -080053 .word pw_cpu_exception_Entry
54 .word pw_cpu_exception_Entry
55 .word pw_cpu_exception_Entry
56 .word pw_cpu_exception_Entry
57 .word pw_cpu_exception_Entry
Armando Montanez5104cd62019-12-10 14:36:43 -080058
59 Note: ``__isr_vector_table`` and ``__stack_start`` are example names, and may
60 vary by platform. See your platform's assembly startup script.
61
62**3. Modify interrupt vector table at runtime**
63 Some applications may choose to modify their interrupt vector tables at
64 runtime. The ARMv7-M exception handler works with this use case (see the
65 exception_entry_test integration test), but keep in mind that your
66 application's exception handler will not be entered if an exception occurs
67 before the vector table entries are updated to point to
Armando Montaneza9ca9992021-01-26 17:06:10 -080068 ``pw_cpu_exception_Entry``.
Armando Montanez5104cd62019-12-10 14:36:43 -080069
70Module Usage
71============
72For lightweight exception handlers that don't need to access
73architecture-specific registers, using the generic exception handler functions
74is preferred.
75
76However, some projects may need to explicitly access architecture-specific
Armando Montaneza9ca9992021-01-26 17:06:10 -080077registers to attempt to recover from a CPU exception. ``pw_cpu_exception_State``
Armando Montanez356bf972020-06-04 10:35:55 -070078provides access to the captured CPU state at the time of the fault. When the
Armando Montaneza9ca9992021-01-26 17:06:10 -080079application-provided ``pw_cpu_exception_DefaultHandler()`` function returns, the
Armando Montanez356bf972020-06-04 10:35:55 -070080CPU state is restored. This allows the exception handler to modify the captured
81state so that execution can safely continue.
Armando Montanez5104cd62019-12-10 14:36:43 -080082
83Expected Behavior
84-----------------
85In most cases, the CPU state captured by the exception handler will contain the
86ARMv7-M basic register frame in addition to an extended set of registers (see
87``cpu_state.h``). The exception to this is when the program stack pointer is in
88an MPU-protected or otherwise invalid memory region when the CPU attempts to
89push the exception register frame to it. In this situation, the PC, LR, and PSR
90registers will NOT be captured and will be marked with 0xFFFFFFFF to indicate
91they are invalid. This backend will still be able to capture all the other
92registers though.
93
94In the situation where the main stack pointer is in a memory protected or
95otherwise invalid region and fails to push CPU context, behavior is undefined.
96
97Nested Exceptions
98-----------------
99To enable nested fault handling:
100 1. Enable separate detection of usage/bus/memory faults via the SHCSR.
101 2. Decrease the priority of the memory, bus, and usage fault handlers. This
102 gives headroom for escalation.
103
104While this allows some faults to nest, it doesn't guarantee all will properly
105nest.
Armando Montanezcddab2d2021-01-11 19:11:05 -0800106
107Configuration Options
108=====================
109
110 - ``PW_CPU_EXCEPTION_EXTENDED_CFSR_DUMP``: Enable extended logging in
111 ``pw::cpu_exception::LogCpuState()`` that dumps the active CFSR fields with
112 help strings. This is disabled by default since it increases the binary size
113 by >1.5KB when using plain-text logs, or ~460 Bytes when using tokenized
114 logging. It's useful to enable this for device bringup until your application
115 has an end-to-end crash reporting solution.
Armando Montanez84acca82021-04-12 15:37:01 -0700116
117Exception Analysis
118==================
119This module provides Python tooling to analyze CPU state captured by a Cortex-M
Armando Montanez11ea2132021-04-13 13:16:54 -0700120core during an exception. This can be useful as part of a crash report analyzer.
Armando Montanez84acca82021-04-12 15:37:01 -0700121
122CFSR decoder
123------------
124The ARMv7-M and ARMv8-M architectures have a Configurable Fault Status Register
Armando Montanez11ea2132021-04-13 13:16:54 -0700125(CFSR) that explains what illegal behavior caused a fault. This module provides
126a simple command-line tool to decode CFSR contents (e.g. 0x00010000) as
127human-readable information (e.g. "Encountered invalid instruction").
128
129For example:
Armando Montanez84acca82021-04-12 15:37:01 -0700130
131 .. code-block::
132
133 $ python -m pw_cpu_exception_cortex_m.cfsr_decoder 0x00010100
134 20210412 15:11:14 INF Exception caused by a usage fault, bus fault.
135
136 Active Crash Fault Status Register (CFSR) fields:
137 IBUSERR Bus fault on instruction fetch.
138 UNDEFINSTR Encountered invalid instruction.
139
140 All registers:
141 cfsr 0x00010100
142
143.. note::
144 The CFSR is not supported on ARMv6-M CPUs (Cortex M0, M0+, M1).