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.