pw_cpu_exception_cortex_m: Add deeper exception information
* Add more informational text about exception flags from the ARM user
guides
* Print the informational text upon exception analysis
* Update documentation example
* Update cortex-m exception analyzer unit test
Change-Id: I1fe27216681ad4eb02b25eaf29d231dad7484e83
Signed-off-by: Shiva Rajagopal <shivarajagopal@google.com>
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/44565
Reviewed-by: Keir Mierle <keir@google.com>
Reviewed-by: Armando Montanez <amontanez@google.com>
diff --git a/pw_cpu_exception_cortex_m/docs.rst b/pw_cpu_exception_cortex_m/docs.rst
index 2cb3064..f8718d4 100644
--- a/pw_cpu_exception_cortex_m/docs.rst
+++ b/pw_cpu_exception_cortex_m/docs.rst
@@ -134,8 +134,18 @@
20210412 15:11:14 INF Exception caused by a usage fault, bus fault.
Active Crash Fault Status Register (CFSR) fields:
- IBUSERR Bus fault on instruction fetch.
+ IBUSERR Instruction bus error.
+ The processor attempted to issue an invalid instruction. It
+ detects the instruction bus error on prefecting, but this
+ flag is only set to 1 if it attempts to issue the faulting
+ instruction. When this bit is set, the processor has not
+ written a fault address to the BFAR.
UNDEFINSTR Encountered invalid instruction.
+ The processor has attempted to execute an undefined
+ instruction. When this bit is set to 1, the PC value stacked
+ for the exception return points to the undefined instruction.
+ An undefined instruction is an instruction that the processor
+ cannot decode.
All registers:
cfsr 0x00010100
diff --git a/pw_cpu_exception_cortex_m/py/exception_analyzer_test.py b/pw_cpu_exception_cortex_m/py/exception_analyzer_test.py
index 8566c5b..78ec218 100644
--- a/pw_cpu_exception_cortex_m/py/exception_analyzer_test.py
+++ b/pw_cpu_exception_cortex_m/py/exception_analyzer_test.py
@@ -210,7 +210,11 @@
'Exception caused by a bus fault at 0xdeadbeef.',
'',
'Active Crash Fault Status Register (CFSR) fields:',
- 'PRECISERR Precise bus fault.',
+ 'PRECISERR Precise data bus error.',
+ ' A data bus error has occurred, and the PC value stacked for',
+ ' the exception return points to the instruction that caused',
+ ' the fault. When the processor sets this bit to 1, it writes',
+ ' the faulting address to the BFAR',
'BFARVALID BFAR is valid.',
'',
'All registers:',
diff --git a/pw_cpu_exception_cortex_m/py/pw_cpu_exception_cortex_m/cortex_m_constants.py b/pw_cpu_exception_cortex_m/py/pw_cpu_exception_cortex_m/cortex_m_constants.py
index b623c38..b44aa50 100644
--- a/pw_cpu_exception_cortex_m/py/pw_cpu_exception_cortex_m/cortex_m_constants.py
+++ b/pw_cpu_exception_cortex_m/py/pw_cpu_exception_cortex_m/cortex_m_constants.py
@@ -72,46 +72,120 @@
# TODO(amontanez): We could probably make a whole module on bit field handling
# in python.
-BitField = collections.namedtuple('BitField',
- ['name', 'bit_mask', 'description'])
+BitField = collections.namedtuple(
+ 'BitField', ['name', 'bit_mask', 'description', 'long_description'])
+
+# Information about faults from:
+# * ARM Cortex-M4 Devices Generic User Guide 4.3.10
+# * ARM Cortex-M33 Devices Generic User Guide 4.2.11
PW_CORTEX_M_CFSR_BIT_FIELDS = [
BitField('IACCVIOL', PW_CORTEX_M_CFSR_IACCVIOL_MASK,
- 'MPU violation on instruction fetch.'),
+ 'Instruction access violation fault.',
+ ('The processor attempted an instruction fetch from a location',
+ 'that does not permit execution. The PC value stacked for the',
+ 'exception return points to the faulting instruction.')),
BitField('DACCVIOL', PW_CORTEX_M_CFSR_DACCVIOL_MASK,
- 'MPU violation on memory read/write.'),
+ 'Data access violation fault.',
+ ('The processor attempted a load or store at a location that',
+ 'does not permit the operation. The PC value stacked for the',
+ 'exception return points to the faulting instruction. The',
+ 'processor has loaded the MMFAR with the address of the',
+ 'attempted access.')),
BitField('MUNSTKERR', PW_CORTEX_M_CFSR_MUNSTKERR_MASK,
- 'MPU violation on exception return.'),
+ 'MemManage fault on unstacking for a return from exception.',
+ ('Unstack for an exception return has caused one or more access',
+ 'violations. This fault is chained to the handler. This means',
+ 'that when this bit is 1, the original return stack is still',
+ 'present. The processor has not adjusted the SP from the',
+ 'failing return, and has not performed a new save. The',
+ 'processor has not written a fault address to the MMAR.')),
BitField('MSTKERR', PW_CORTEX_M_CFSR_MSTKERR_MASK,
- 'MPU violation on exception entry.'),
+ 'MemManage fault on stacking for exception entry.',
+ ('When this bit is 1, the SP is still adjusted but the values',
+ 'in the context area on the stack might be incorrect. The',
+ 'processor has not written a fault address to the MMAR.')),
BitField('MLSPERR', PW_CORTEX_M_CFSR_MLSPERR_MASK,
- 'FPU lazy state preservation failed.'),
+ 'MemManage Fault during FPU lazy state preservation.', ''),
BitField('MMARVALID', PW_CORTEX_M_CFSR_MMARVALID_MASK,
- 'MMFAR register is valid.'),
+ 'MMFAR register is valid.', ''),
BitField('IBUSERR', PW_CORTEX_M_CFSR_IBUSERR_MASK,
- 'Bus fault on instruction fetch.'),
+ 'Instruction bus error.',
+ ('The processor attempted to issue an invalid instruction. It',
+ 'detects the instruction bus error on prefetching, but this',
+ 'flag is only set to 1 if it attempts to issue the faulting',
+ 'instruction. When this bit is set, the processor has not',
+ 'written a fault address to the BFAR.')),
BitField('PRECISERR', PW_CORTEX_M_CFSR_PRECISERR_MASK,
- 'Precise bus fault.'),
+ 'Precise data bus error.',
+ ('A data bus error has occurred, and the PC value stacked for',
+ 'the exception return points to the instruction that caused',
+ 'the fault. When the processor sets this bit to 1, it writes',
+ 'the faulting address to the BFAR')),
BitField('IMPRECISERR', PW_CORTEX_M_CFSR_IMPRECISERR_MASK,
- 'Imprecise bus fault.'),
+ 'Imprecise data bus error.',
+ ('A data bus error has occurred, but the return address in the',
+ 'stack frame is not related to the instruction that caused the',
+ 'error. This is an asynchronous fault. Therefore, if it is',
+ 'detected when the priority of the current processes is higher',
+ 'than the BusFault priority, the BusFault becomes pending and',
+ 'becomes active only when the processor returns from all higher',
+ 'priority processes. If a precise fault occurs before the',
+ 'processor enters the handler for the imprecise BusFault, the',
+ 'handler detects both IMPRECISERR set to 1 and one of the',
+ 'precise fault status bits set to 1')),
BitField('UNSTKERR', PW_CORTEX_M_CFSR_UNSTKERR_MASK,
- 'Hardware failure on context restore.'),
+ 'BusFault on Unstacking for a return from exception.',
+ ('Unstack for an exception return has caused one or more',
+ 'BusFaults. This fault is chained to the handler. This means',
+ 'when the processor sets this bit to 1, the original return',
+ 'stack is still present. The processor does not adjust the SP',
+ 'from the failing return, does not perform a new save, and does',
+ 'not write a fault address to the BFAR')),
BitField('STKERR', PW_CORTEX_M_CFSR_STKERR_MASK,
- 'Hardware failure on context save.'),
+ 'BusFault on Stacking for Exception Entry.',
+ ('Stacking for an exception entry has caused one or more',
+ 'BusFaults. When the processor sets this bit to 1, the SP is',
+ 'still adjusted but the values in the context area on the stack',
+ 'might be incorrect. The processor does not write a fault',
+ 'address to the BFAR')),
BitField('LSPERR', PW_CORTEX_M_CFSR_LSPERR_MASK,
- 'FPU lazy state preservation failed.'),
- BitField('BFARVALID', PW_CORTEX_M_CFSR_BFARVALID_MASK, 'BFAR is valid.'),
+ 'BusFault during FPU lazy state preservation.', ''),
+ BitField('BFARVALID', PW_CORTEX_M_CFSR_BFARVALID_MASK, 'BFAR is valid.',
+ ''),
BitField('UNDEFINSTR', PW_CORTEX_M_CFSR_UNDEFINSTR_MASK,
- 'Encountered invalid instruction.'),
+ 'Undefined Instruction UsageFault.',
+ ('The processor has attempted to execute an undefined',
+ 'instruction. When this bit is set to 1, the PC value stacked',
+ 'for the exception return points to the undefined instruction.',
+ 'An undefined instruction is an instruction that the processor',
+ 'cannot decode.')),
BitField('INVSTATE', PW_CORTEX_M_CFSR_INVSTATE_MASK,
- ('Attempted to execute an instruction with an invalid Execution '
- 'Program Status Register (EPSR) value.')),
+ 'Invalid State UsageFault.',
+ ('The processor has attempted to execute an instruction that',
+ 'makes illegal use of the EPSR. The PC value stacked for the',
+ 'exception return points to the instruction that attempt',
+ 'illegal use of the EPSR')),
BitField('INVPC', PW_CORTEX_M_CFSR_INVPC_MASK,
- 'Program Counter (PC) is not legal.'),
+ 'Invalid PC Load UsageFault.',
+ ('The processor has attempted an illegal load of EXC_RETURN',
+ 'to the PC, as a result of an invalid context, or an invalid',
+ 'EXC_RETURN value. The PC value stacked for the exception',
+ 'return points to the instruction that tried to perform the',
+ 'illegal load of the PC')),
BitField('NOCP', PW_CORTEX_M_CFSR_NOCP_MASK,
- 'Coprocessor disabled or not present.'),
- BitField('STKOF', PW_CORTEX_M_CFSR_STKOF_MASK, 'Stack overflowed.'),
+ 'Coprocessor disabled or not present.', ''),
+ BitField('STKOF', PW_CORTEX_M_CFSR_STKOF_MASK, 'Stack overflowed.', ''),
BitField('UNALIGNED', PW_CORTEX_M_CFSR_UNALIGNED_MASK,
- 'Unaligned load or store. (This exception can be disabled)'),
- BitField('DIVBYZERO', PW_CORTEX_M_CFSR_DIVBYZERO_MASK, 'Divide by zero.'),
+ 'Unaligned access UsageFault.',
+ ('The processor has made an unaligned memory access. This fault',
+ 'can be enabled or disabled using the UNALIGN_TRP bit in the',
+ 'CCR. Unaligned LDM, STM, LDRD, and STRD instructions always',
+ 'fault irrespective of the CCR setting.')),
+ BitField('DIVBYZERO', PW_CORTEX_M_CFSR_DIVBYZERO_MASK, 'Divide by zero.',
+ ('The processor has executed an SDIV or UDIV instruction with',
+ 'a divisor of 0. The PC value stacked for the exception',
+ 'return points to the instruction that performed the divide',
+ 'by zero. This fault can be enabled or disabled using the',
+ 'DIV_0_TRP bit in the CCR.')),
]
diff --git a/pw_cpu_exception_cortex_m/py/pw_cpu_exception_cortex_m/exception_analyzer.py b/pw_cpu_exception_cortex_m/py/pw_cpu_exception_cortex_m/exception_analyzer.py
index c246a80..2810b64 100644
--- a/pw_cpu_exception_cortex_m/py/pw_cpu_exception_cortex_m/exception_analyzer.py
+++ b/pw_cpu_exception_cortex_m/py/pw_cpu_exception_cortex_m/exception_analyzer.py
@@ -126,6 +126,10 @@
fields = []
for field in self.active_cfsr_fields():
fields.append(f'{field.name:<11} {field.description}')
+ if isinstance(field.long_description, tuple):
+ long_desc = ' {}'.format('\n '.join(
+ field.long_description))
+ fields.append(long_desc)
return '\n'.join(fields)
def __str__(self):