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
//! Debugging a crash (exception) //! //! The `cortex-m-rt` crate provides functionality for this through a default //! exception handler. When an exception is hit, the default handler will //! trigger a breakpoint and in this debugging context the stacked registers //! are accessible. //! //! In you run the example below, you'll be able to inspect the state of your //! program under the debugger using these commands: //! //! ``` text //! (gdb) # Exception frame = program state during the crash //! (gdb) print/x *ef //! $1 = cortex_m::exception::ExceptionFrame { //! r0 = 0x2fffffff, //! r1 = 0x2fffffff, //! r2 = 0x0, //! r3 = 0x0, //! r12 = 0x0, //! lr = 0x8000481, //! pc = 0x8000460, //! xpsr = 0x61000000, //! } //! //! (gdb) # Where did we come from? //! (gdb) backtrace //! #0 cortex_m_rt::default_handler (ef=0x20004f54) at (..) //! #1 <signal handler called> //! #2 0x08000460 in core::ptr::read_volatile<u32> (src=0x2fffffff) at (..) //! #3 0x08000480 in crash::main () at examples/crash.rs:68 //! //! (gdb) # Nail down the location of the crash //! (gdb) disassemble/m ef.pc //! Dump of assembler code for function core::ptr::read_volatile<u32>: //! 408 pub unsafe fn read_volatile<T>(src: *const T) -> T { //! 0x08000454 <+0>: sub sp, #20 //! 0x08000456 <+2>: mov r1, r0 //! 0x08000458 <+4>: str r0, [sp, #8] //! 0x0800045a <+6>: ldr r0, [sp, #8] //! 0x0800045c <+8>: str r0, [sp, #12] //! //! 409 intrinsics::volatile_load(src) //! 0x0800045e <+10>: ldr r0, [sp, #12] //! 0x08000460 <+12>: ldr r0, [r0, #0] //! 0x08000462 <+14>: str r0, [sp, #16] //! 0x08000464 <+16>: ldr r0, [sp, #16] //! 0x08000466 <+18>: str r1, [sp, #4] //! 0x08000468 <+20>: str r0, [sp, #0] //! 0x0800046a <+22>: b.n 0x800046c <core::ptr::read_volatile<u32>+24> //! //! 410 } //! 0x0800046c <+24>: ldr r0, [sp, #0] //! 0x0800046e <+26>: add sp, #20 //! 0x08000470 <+28>: bx lr //! //! End of assembler dump. //! ``` //! //! --- //! //! ``` //! //! #![feature(used)] //! #![no_std] //! //! extern crate cortex_m; //! extern crate cortex_m_rt; //! //! use core::ptr; //! //! use cortex_m::asm; //! //! fn main() { //! // Read an invalid memory address //! unsafe { //! ptr::read_volatile(0x2FFF_FFFF as *const u32); //! } //! } //! //! // As we are not using interrupts, we just register a dummy catch all handler //! #[link_section = ".vector_table.interrupts"] //! #[used] //! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; //! //! extern "C" fn default_handler() { //! asm::bkpt(); //! } //! ``` // Auto-generated. Do not modify.