146 lines
4.8 KiB
Python
146 lines
4.8 KiB
Python
"""Source this file into gdb `source ../../tools/cortex-m-fault-gdb.py` then run
|
|
`cortex-m-fault` to print basic info about the fault registers."""
|
|
|
|
SCS = 0xE000E000
|
|
SCB = SCS + 0x0D00
|
|
CPUID = SCB + 0x000 # (R/ ) CPUID Base Register */
|
|
ICSR = SCB + 0x004 # (R/W) Interrupt Control and State Register */
|
|
VTOR = SCB + 0x008 # (R/W) Vector Table Offset Register */
|
|
AIRCR = SCB + 0x00C # (R/W) Application Interrupt and Reset Control Register */
|
|
SCR = SCB + 0x010 # (R/W) System Control Register */
|
|
CCR = SCB + 0x014 # (R/W) Configuration Control Register */
|
|
SHCSR = SCB + 0x024 # (R/W) System Handler Control and State Register */
|
|
CFSR = SCB + 0x028 # (R/W) Configurable Fault Status Register */
|
|
HFSR = SCB + 0x02C # (R/W) HardFault Status Register */
|
|
DFSR = SCB + 0x030 # (R/W) Debug Fault Status Register */
|
|
MMFAR = SCB + 0x034 # (R/W) MemManage Fault Address Register */
|
|
BFAR = SCB + 0x038 # (R/W) BusFault Address Register */
|
|
AFSR = SCB + 0x03C # (R/W) Auxiliary Fault Status Register */
|
|
|
|
PARTS = {0xC27: "Cortex M7", 0xC60: "Cortex M0+"}
|
|
|
|
EXCEPTIONS = {
|
|
0: "Thread mode",
|
|
2: "Non Maskable Interrupt",
|
|
3: "Hard Fault",
|
|
4: "MemManage Fault",
|
|
5: "Bus Fault",
|
|
6: "Usage Fault",
|
|
11: "SVCAll",
|
|
14: "PendSV",
|
|
15: "SysTick",
|
|
}
|
|
|
|
|
|
class CortexMFault(gdb.Command):
|
|
def __init__(self):
|
|
super(CortexMFault, self).__init__("cortex-m-fault", gdb.COMMAND_USER)
|
|
|
|
def _read(self, address):
|
|
i = gdb.selected_inferior()
|
|
return i.read_memory(address, 4).cast("I")[0]
|
|
|
|
def _armv6m_fault(self):
|
|
vtor = self._read(VTOR)
|
|
print("vtor", hex(vtor))
|
|
|
|
icsr = self._read(ICSR)
|
|
vectactive = icsr & 0x1FF
|
|
print("icsr", hex(icsr), vectactive)
|
|
if vectactive != 0:
|
|
if vectactive in EXCEPTIONS:
|
|
vectactive = EXCEPTIONS[vectactive]
|
|
else:
|
|
vectactive -= 16
|
|
|
|
print("Active interrupt:", vectactive)
|
|
|
|
vectpending = (icsr >> 12) & 0x1FF
|
|
if vectpending != 0:
|
|
if vectpending in EXCEPTIONS:
|
|
vectpending = EXCEPTIONS[vectpending]
|
|
else:
|
|
vectpending -= 16
|
|
|
|
print("Pending interrupt:", vectpending)
|
|
|
|
def _armv7m_fault(self):
|
|
icsr = self._read(ICSR)
|
|
if (icsr & (1 << 11)) != 0:
|
|
print("No preempted exceptions")
|
|
else:
|
|
print("Another exception was preempted")
|
|
print("icsr", hex(icsr))
|
|
vectactive = icsr & 0x1FF
|
|
if vectactive != 0:
|
|
if vectactive in EXCEPTIONS:
|
|
print(EXCEPTIONS[vectactive])
|
|
else:
|
|
print(vectactive - 16)
|
|
vectpending = (icsr >> 12) & 0x1FF
|
|
if vectpending != 0:
|
|
if vectpending in EXCEPTIONS:
|
|
print(EXCEPTIONS[vectpending])
|
|
else:
|
|
print(vectpending - 16)
|
|
|
|
vtor = self._read(VTOR)
|
|
print("vtor", hex(vtor))
|
|
# print(hex(self._read(SHCSR)))
|
|
cfsr = self._read(CFSR)
|
|
ufsr = cfsr >> 16
|
|
bfsr = (cfsr >> 8) & 0xFF
|
|
mmfsr = cfsr & 0xFF
|
|
print("ufsr", hex(ufsr), "bfsr", hex(bfsr), "mmfsr", hex(mmfsr))
|
|
if (bfsr & (1 << 7)) != 0:
|
|
print("Bad address", hex(self._read(BFAR)))
|
|
if (bfsr & (1 << 3)) != 0:
|
|
print("Unstacking from exception error")
|
|
if (bfsr & (1 << 2)) != 0:
|
|
print("Imprecise data bus error")
|
|
if (bfsr & (1 << 1)) != 0:
|
|
print("Precise data bus error")
|
|
if (bfsr & (1 << 0)) != 0:
|
|
print("Instruction bus error")
|
|
|
|
if (mmfsr & (1 << 7)) != 0:
|
|
print("Bad address", hex(self._read(MMFAR)))
|
|
if (mmfsr & (1 << 3)) != 0:
|
|
print("Unstacking from exception error")
|
|
if (mmfsr & (1 << 1)) != 0:
|
|
print("Data access violation")
|
|
if (mmfsr & (1 << 0)) != 0:
|
|
print("Instruction access violation")
|
|
|
|
if (ufsr & (1 << 8)) != 0:
|
|
print("Unaligned access")
|
|
if (ufsr & (1 << 0)) != 0:
|
|
print("Undefined instruction")
|
|
hfsr = self._read(HFSR)
|
|
if (hfsr & (1 << 30)) != 0:
|
|
print("Forced hard fault")
|
|
if (hfsr & (1 << 1)) != 0:
|
|
print("Bus fault when reading vector table")
|
|
print("VTOR", hex(vtor))
|
|
|
|
def invoke(self, arg, from_tty):
|
|
cpuid = self._read(CPUID)
|
|
implementer = cpuid >> 24
|
|
if implementer != 0x41:
|
|
raise RuntimeError()
|
|
variant = (cpuid >> 20) & 0xF
|
|
architecture = (cpuid >> 16) & 0xF
|
|
revision = cpuid & 0xF
|
|
part_no = (cpuid >> 4) & 0xFFF
|
|
print(PARTS[part_no])
|
|
|
|
if architecture == 0xF:
|
|
self._armv7m_fault()
|
|
elif architecture == 0xC:
|
|
self._armv6m_fault()
|
|
else:
|
|
raise RuntimeError(f"Unknown architecture {architecture:x}")
|
|
|
|
|
|
CortexMFault()
|