Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions builder/sizes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ func TestBinarySize(t *testing.T) {
tests := []sizeTest{
// microcontrollers
{"hifive1b", "examples/echo", 3884, 280, 0, 2268},
{"microbit", "examples/serial", 2924, 388, 8, 2272},
{"wioterminal", "examples/pininterrupt", 7365, 1491, 116, 6912},
{"microbit", "examples/serial", 2852, 360, 8, 2272},
{"wioterminal", "examples/pininterrupt", 7337, 1491, 116, 6912},

// TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the
Expand Down
23 changes: 0 additions & 23 deletions src/device/arm/cortexm.S
Original file line number Diff line number Diff line change
@@ -1,29 +1,6 @@
.syntax unified
.cfi_sections .debug_frame

.section .text.HardFault_Handler
.global HardFault_Handler
.type HardFault_Handler, %function
HardFault_Handler:
.cfi_startproc
// 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
.cfi_endproc
.size HardFault_Handler, .-HardFault_Handler

// This is a convenience function for semihosting support.
// At some point, this should be replaced by inline assembly.
.section .text.SemihostingCall
Expand Down
3 changes: 3 additions & 0 deletions src/runtime/panic.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ func runtimePanicAt(addr unsafe.Pointer, msg string) {
trap()
}
if hasReturnAddr {
// Note: the string "panic: runtime error at " is also used in
// runtime_cortexm_hardfault.go. It is kept the same so that the string
// can be deduplicated by the compiler.
printstring("panic: runtime error at ")
printptr(uintptr(addr) - callInstSize)
printstring(": ")
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ func memzero(ptr unsafe.Pointer, size uintptr)
// the current stack pointer in a platform-independent way.
func stacksave() unsafe.Pointer

// Special LLVM intrinsic that returns the SP register on entry to the calling
// function.
//
//export llvm.sponentry.p0
func llvm_sponentry() unsafe.Pointer

//export strlen
func strlen(ptr unsafe.Pointer) uintptr

Expand Down
40 changes: 13 additions & 27 deletions src/runtime/runtime_cortexm_hardfault.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,25 @@

package runtime

import (
"unsafe"
)

// This function is called at HardFault.
// Before this function is called, the stack pointer is reset to the initial
// stack pointer (loaded from address 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/
//
//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)
}
//export HardFault_Handler
func HardFault_Handler() {
// Obtain the stack pointer as it was on entry to the HardFault. It contains
// the registers that were pushed by the NVIC and that we can now read back
// to print the PC value at the time of the hard fault, for example.
sp := (*interruptStack)(llvm_sponentry())

// Note: by reusing the string "panic: runtime error at " we save a little
// bit in terms of code size as the string can be deduplicated.
print("panic: runtime error at ", sp.PC, ": HardFault with sp=", sp)
// 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.
println()
abort()
}
9 changes: 7 additions & 2 deletions src/runtime/runtime_cortexm_hardfault_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ const (

// See runtime_cortexm_hardfault.go
//
//go:export handleHardFault
func handleHardFault(sp *interruptStack) {
//export HardFault_Handler
func HardFault_Handler() {
// Obtain the stack pointer as it was on entry to the HardFault. It contains
// the registers that were pushed by the NVIC and that we can now read back
// to print the PC value at the time of the hard fault, for example.
sp := (*interruptStack)(llvm_sponentry())

fault := GetFaultStatus()
spValid := !fault.Bus().ImpreciseDataBusError()

Expand Down
Loading