1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
//! Debugging a crash (exception) //! //! Most crash conditions trigger a hard fault exception, whose handler is defined via //! `exception!(HardFault, ..)`. The `HardFault` handler has access to the exception frame, a //! snapshot of the CPU registers at the moment of the exception. //! //! This program crashes and the `HardFault` handler prints to the console the contents of the //! `ExceptionFrame` and then triggers a breakpoint. From that breakpoint one can see the backtrace //! that led to the exception. //! //! ``` text //! (gdb) continue //! Program received signal SIGTRAP, Trace/breakpoint trap. //! __bkpt () at asm/bkpt.s:3 //! 3 bkpt //! //! (gdb) backtrace //! #0 __bkpt () at asm/bkpt.s:3 //! #1 0x080030b4 in cortex_m::asm::bkpt () at $$/cortex-m-0.5.0/src/asm.rs:19 //! #2 rust_begin_unwind (args=..., file=..., line=99, col=5) at $$/panic-semihosting-0.2.0/src/lib.rs:87 //! #3 0x08001d06 in core::panicking::panic_fmt () at libcore/panicking.rs:71 //! #4 0x080004a6 in crash::hard_fault (ef=0x20004fa0) at examples/crash.rs:99 //! #5 0x08000548 in UserHardFault (ef=0x20004fa0) at <exception macros>:10 //! #6 0x0800093a in HardFault () at asm.s:5 //! Backtrace stopped: previous frame identical to this frame (corrupt stack?) //! ``` //! //! In the console output one will find the state of the Program Counter (PC) register at the time //! of the exception. //! //! ``` text //! panicked at 'HardFault at ExceptionFrame { //! r0: 0x2fffffff, //! r1: 0x2fffffff, //! r2: 0x080051d4, //! r3: 0x080051d4, //! r12: 0x20000000, //! lr: 0x08000435, //! pc: 0x08000ab6, //! xpsr: 0x61000000 //! }', examples/crash.rs:106:5 //! ``` //! //! This register contains the address of the instruction that caused the exception. In GDB one can //! disassemble the program around this address to observe the instruction that caused the //! exception. //! //! ``` text //! (gdb) disassemble/m 0x08000ab6 //! Dump of assembler code for function core::ptr::read_volatile: //! 451 pub unsafe fn read_volatile<T>(src: *const T) -> T { //! 0x08000aae <+0>: sub sp, #16 //! 0x08000ab0 <+2>: mov r1, r0 //! 0x08000ab2 <+4>: str r0, [sp, #8] //! //! 452 intrinsics::volatile_load(src) //! 0x08000ab4 <+6>: ldr r0, [sp, #8] //! -> 0x08000ab6 <+8>: ldr r0, [r0, #0] //! 0x08000ab8 <+10>: str r0, [sp, #12] //! 0x08000aba <+12>: ldr r0, [sp, #12] //! 0x08000abc <+14>: str r1, [sp, #4] //! 0x08000abe <+16>: str r0, [sp, #0] //! 0x08000ac0 <+18>: b.n 0x8000ac2 <core::ptr::read_volatile+20> //! //! 453 } //! 0x08000ac2 <+20>: ldr r0, [sp, #0] //! 0x08000ac4 <+22>: add sp, #16 //! 0x08000ac6 <+24>: bx lr //! //! End of assembler dump. //! ``` //! //! `ldr r0, [r0, #0]` caused the exception. This instruction tried to load (read) a 32-bit word //! from the address stored in the register `r0`. Looking again at the contents of `ExceptionFrame` //! we see that the `r0` contained the address `0x2FFF_FFFF` when this instruction was executed. //! //! --- //! //! ``` //! //! #![no_main] //! #![no_std] //! //! extern crate cortex_m; //! #[macro_use] //! extern crate cortex_m_rt as rt; //! extern crate panic_semihosting; //! //! use core::ptr; //! //! use rt::ExceptionFrame; //! //! entry!(main); //! //! fn main() -> ! { //! unsafe { //! // read an address outside of the RAM region; causes a HardFault exception //! ptr::read_volatile(0x2FFF_FFFF as *const u32); //! } //! //! loop {} //! } //! //! // define the hard fault handler //! exception!(HardFault, hard_fault); //! //! fn hard_fault(ef: &ExceptionFrame) -> ! { //! panic!("HardFault at {:#?}", ef); //! } //! //! // define the default exception handler //! exception!(*, default_handler); //! //! fn default_handler(irqn: i16) { //! panic!("Unhandled exception (IRQn = {})", irqn); //! } //! ``` // Auto-generated. Do not modify.