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() {
 | 
			
		||||
	// disable all interrupts
 | 
			
		||||
	arm.DisableInterrupts()
 | 
			
		||||
 | 
			
		||||
	// lock up forever
 | 
			
		||||
	for {
 | 
			
		||||
		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.
 | 
			
		||||
//go:export memset
 | 
			
		||||
func libc_memset(ptr unsafe.Pointer, c byte, size uintptr) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,5 +19,8 @@
 | 
			
		|||
	"ldflags": [
 | 
			
		||||
		"--gc-sections"
 | 
			
		||||
	],
 | 
			
		||||
	"extra-files": [
 | 
			
		||||
		"src/device/arm/cortexm.s"
 | 
			
		||||
	],
 | 
			
		||||
	"gdb": "arm-none-eabi-gdb"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче