Skip to content

Commit 217664b

Browse files
committed
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.
1 parent 1a1506e commit 217664b

5 files changed

Lines changed: 37 additions & 1 deletion

File tree

builder/sizes_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) {
4444
// microcontrollers
4545
{"hifive1b", "examples/echo", 3680, 280, 0, 2252},
4646
{"microbit", "examples/serial", 2694, 342, 8, 2248},
47-
{"wioterminal", "examples/pininterrupt", 7074, 1510, 120, 7248},
47+
{"wioterminal", "examples/pininterrupt", 7150, 1534, 120, 7248},
4848

4949
// TODO: also check wasm. Right now this is difficult, because
5050
// wasm binaries are run through wasm-opt and therefore the

src/internal/task/task_none.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,8 @@ func SystemStack() uintptr {
4242
runtimePanic("scheduler is disabled")
4343
return 0 // unreachable
4444
}
45+
46+
func GoroutineStack() uintptr {
47+
// No separate goroutine stack without a scheduler.
48+
return 0
49+
}

src/internal/task/task_stack_cortexm.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,14 @@ uintptr_t SystemStack() {
1111
);
1212
return sp;
1313
}
14+
15+
uintptr_t GoroutineStack() {
16+
uintptr_t sp;
17+
asm volatile(
18+
"mrs %0, PSP"
19+
: "=r"(sp)
20+
:
21+
: "memory"
22+
);
23+
return sp;
24+
}

src/internal/task/task_stack_cortexm.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,10 @@ func (s *state) pause() {
7070
//
7171
//export SystemStack
7272
func SystemStack() uintptr
73+
74+
// GoroutineStack returns the PSP (goroutine stack pointer). When a fault
75+
// occurs in goroutine context, the hardware saves the exception frame to PSP;
76+
// reading PSP+0x18 gives the actual faulting PC.
77+
//
78+
//export GoroutineStack
79+
func GoroutineStack() uintptr

src/runtime/runtime_cortexm_hardfault_debug.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package runtime
44

55
import (
66
"device/arm"
7+
"internal/task"
78
"unsafe"
89
)
910

@@ -106,6 +107,18 @@ func HardFault_Handler() {
106107
print(" pc=", sp.PC)
107108
}
108109
}
110+
111+
// PSP holds the actual exception frame when the fault occurred in a
112+
// goroutine (thread mode, PSP active). The MSP-based sp above is the
113+
// scheduler's stack and its PC is garbage in that case.
114+
pspVal := task.GoroutineStack()
115+
if pspVal >= 0x20000000 && pspVal < 0x20040000 {
116+
pspFrame := (*interruptStack)(unsafe.Pointer(pspVal))
117+
print(" psp=", pspFrame)
118+
print(" psp_pc=", pspFrame.PC)
119+
print(" psp_lr=", pspFrame.LR)
120+
}
121+
109122
println()
110123
abort()
111124
}

0 commit comments

Comments
 (0)