arm: print an error when a HardFault occurs
This is very useful for debugging. It differentiates between a stack overflow and other errors (because it's easy to see when a stack overflow occurs) and prints the old stack pointer and program counter if available.
Этот коммит содержится в:
родитель
7b6ef65fe7
коммит
ba85c82fbb
3 изменённых файлов: 74 добавлений и 0 удалений
21
src/device/arm/cortexm.s
Обычный файл
21
src/device/arm/cortexm.s
Обычный файл
|
@ -0,0 +1,21 @@
|
||||||
|
.syntax unified
|
||||||
|
|
||||||
|
.section .text.HardFault_Handler
|
||||||
|
.global HardFault_Handler
|
||||||
|
.type HardFault_Handler, %function
|
||||||
|
HardFault_Handler:
|
||||||
|
// Put the old stack pointer in the first argument, for easy debugging. This
|
||||||
|
// is especially useful on Cortex-M0, which supports far fewer debug
|
||||||
|
// facilities.
|
||||||
|
mov r0, sp
|
||||||
|
|
||||||
|
// Load the default stack pointer from address 0 so that we can call normal
|
||||||
|
// functions again that expect a working stack. However, it will corrupt the
|
||||||
|
// old stack so the function below must not attempt to recover from this
|
||||||
|
// fault.
|
||||||
|
movs r3, #0
|
||||||
|
ldr r3, [r3]
|
||||||
|
mov sp, r3
|
||||||
|
|
||||||
|
// Continue handling this error in Go.
|
||||||
|
bl handleHardFault
|
|
@ -41,11 +41,61 @@ func preinit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func abort() {
|
func abort() {
|
||||||
|
// disable all interrupts
|
||||||
|
arm.DisableInterrupts()
|
||||||
|
|
||||||
|
// lock up forever
|
||||||
for {
|
for {
|
||||||
arm.Asm("wfi")
|
arm.Asm("wfi")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The stack layout at the moment an interrupt occurs.
|
||||||
|
// Registers can be accessed if the stack pointer is cast to a pointer to this
|
||||||
|
// struct.
|
||||||
|
type interruptStack struct {
|
||||||
|
R0 uintptr
|
||||||
|
R1 uintptr
|
||||||
|
R2 uintptr
|
||||||
|
R3 uintptr
|
||||||
|
R12 uintptr
|
||||||
|
LR uintptr
|
||||||
|
PC uintptr
|
||||||
|
PSR uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called at HardFault.
|
||||||
|
// Before this function is called, the stack pointer is reset to the initial
|
||||||
|
// stack pointer (loaded from addres 0x0) and the previous stack pointer is
|
||||||
|
// passed as an argument to this function. This allows for easy inspection of
|
||||||
|
// the stack the moment a HardFault occurs, but it means that the stack will be
|
||||||
|
// corrupted by this function and thus this handler must not attempt to recover.
|
||||||
|
//
|
||||||
|
// For details, see:
|
||||||
|
// https://community.arm.com/developer/ip-products/system/f/embedded-forum/3257/debugging-a-cortex-m0-hard-fault
|
||||||
|
// https://blog.feabhas.com/2013/02/developing-a-generic-hard-fault-handler-for-arm-cortex-m3cortex-m4/
|
||||||
|
//go:export handleHardFault
|
||||||
|
func handleHardFault(sp *interruptStack) {
|
||||||
|
print("fatal error: ")
|
||||||
|
if uintptr(unsafe.Pointer(sp)) < 0x20000000 {
|
||||||
|
print("stack overflow")
|
||||||
|
} else {
|
||||||
|
// TODO: try to find the cause of the hard fault. Especially on
|
||||||
|
// Cortex-M3 and higher it is possible to find more detailed information
|
||||||
|
// in special status registers.
|
||||||
|
print("HardFault")
|
||||||
|
}
|
||||||
|
print(" with sp=", sp)
|
||||||
|
if uintptr(unsafe.Pointer(&sp.PC)) >= 0x20000000 {
|
||||||
|
// Only print the PC if it points into memory.
|
||||||
|
// It may not point into memory during a stack overflow, so check that
|
||||||
|
// first before accessing the stack.
|
||||||
|
print(" pc=", sp.PC)
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
abort()
|
||||||
|
}
|
||||||
|
|
||||||
// Implement memset for LLVM and compiler-rt.
|
// Implement memset for LLVM and compiler-rt.
|
||||||
//go:export memset
|
//go:export memset
|
||||||
func libc_memset(ptr unsafe.Pointer, c byte, size uintptr) {
|
func libc_memset(ptr unsafe.Pointer, c byte, size uintptr) {
|
||||||
|
|
|
@ -19,5 +19,8 @@
|
||||||
"ldflags": [
|
"ldflags": [
|
||||||
"--gc-sections"
|
"--gc-sections"
|
||||||
],
|
],
|
||||||
|
"extra-files": [
|
||||||
|
"src/device/arm/cortexm.s"
|
||||||
|
],
|
||||||
"gdb": "arm-none-eabi-gdb"
|
"gdb": "arm-none-eabi-gdb"
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче