mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-16 10:43:29 +00:00
runtime: improve hardfault handler and stack reporting on Cortex-M
- Add reference to the current goroutine stack (PSP) when showing the hardfault info on Cortex-M.
This commit is contained in:
committed by
Ron Evans
parent
7cbbfd6fc5
commit
8e36d2758b
@@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) {
|
|||||||
// microcontrollers
|
// microcontrollers
|
||||||
{"hifive1b", "examples/echo", 3817, 299, 0, 2252},
|
{"hifive1b", "examples/echo", 3817, 299, 0, 2252},
|
||||||
{"microbit", "examples/serial", 2820, 356, 8, 2248},
|
{"microbit", "examples/serial", 2820, 356, 8, 2248},
|
||||||
{"wioterminal", "examples/pininterrupt", 7206, 1510, 120, 7248},
|
{"wioterminal", "examples/pininterrupt", 7286, 1534, 120, 7248},
|
||||||
|
|
||||||
// TODO: also check wasm. Right now this is difficult, because
|
// TODO: also check wasm. Right now this is difficult, because
|
||||||
// wasm binaries are run through wasm-opt and therefore the
|
// wasm binaries are run through wasm-opt and therefore the
|
||||||
|
|||||||
@@ -42,3 +42,8 @@ func SystemStack() uintptr {
|
|||||||
runtimePanic("scheduler is disabled")
|
runtimePanic("scheduler is disabled")
|
||||||
return 0 // unreachable
|
return 0 // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GoroutineStack() uintptr {
|
||||||
|
// No separate goroutine stack without a scheduler.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,3 +11,14 @@ uintptr_t SystemStack() {
|
|||||||
);
|
);
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t GoroutineStack() {
|
||||||
|
uintptr_t sp;
|
||||||
|
asm volatile(
|
||||||
|
"mrs %0, PSP"
|
||||||
|
: "=r"(sp)
|
||||||
|
:
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|||||||
@@ -70,3 +70,10 @@ func (s *state) pause() {
|
|||||||
//
|
//
|
||||||
//export SystemStack
|
//export SystemStack
|
||||||
func SystemStack() uintptr
|
func SystemStack() uintptr
|
||||||
|
|
||||||
|
// GoroutineStack returns the PSP (goroutine stack pointer). When a fault
|
||||||
|
// occurs in goroutine context, the hardware saves the exception frame to PSP;
|
||||||
|
// reading PSP+0x18 gives the actual faulting PC.
|
||||||
|
//
|
||||||
|
//export GoroutineStack
|
||||||
|
func GoroutineStack() uintptr
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package runtime
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"device/arm"
|
"device/arm"
|
||||||
|
"internal/task"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -106,6 +107,20 @@ func HardFault_Handler() {
|
|||||||
print(" pc=", sp.PC)
|
print(" pc=", sp.PC)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PSP holds the actual exception frame when the fault occurred in a
|
||||||
|
// goroutine (thread mode, PSP active). The MSP-based sp above is the
|
||||||
|
// scheduler's stack and its PC is garbage in that case.
|
||||||
|
pspVal := task.GoroutineStack()
|
||||||
|
|
||||||
|
// heapEndSymbol is defined in baremetal.go; we also ensure that the goroutine exception frame is within addressable memory.
|
||||||
|
if pspVal >= 0x20000000 && pspVal < (uintptr(unsafe.Pointer(&heapEndSymbol))-uintptr(unsafe.Sizeof(interruptStack{}))) {
|
||||||
|
pspFrame := (*interruptStack)(unsafe.Pointer(pspVal))
|
||||||
|
print(" psp=", pspFrame)
|
||||||
|
print(" psp_pc=", pspFrame.PC)
|
||||||
|
print(" psp_lr=", pspFrame.LR)
|
||||||
|
}
|
||||||
|
|
||||||
println()
|
println()
|
||||||
abort()
|
abort()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user