Skip to content
Snippets Groups Projects
Commit dba88fca authored by Per Lindgren's avatar Per Lindgren
Browse files

polish

parent 6fbf672a
Branches
No related tags found
No related merge requests found
//! Debugging a crash (exception)
// #![deny(unsafe_code)] // this example is using unsafe
#![deny(warnings)]
#![no_main]
#![no_std]
extern crate panic_halt;
//use panic_halt as _;
use panic_semihosting as _;
use core::ptr;
use cortex_m_rt::{entry, exception};
......@@ -24,82 +28,5 @@ fn main() -> ! {
#[exception]
#[inline(never)]
fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
// to inline never and read_volatile required to
// avoid `ef` being optimized out in release mode
unsafe {
ptr::read_volatile(ef);
}
loop {
continue;
}
panic!("Exception frame {:?}", ef);
}
//
// Most crash conditions trigger a hard fault exception, whose handler is defined via
// ``` rust
// #[exception]
// fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
// ...
// ```
//
// `cortex-m-rt` generates a trampoline, that calls into your user defined `
// HardFault` handler. We look at the generated trampoline:
//
// ``` rust
// #[doc(hidden)]
// #[export_name = "HardFault"]
// #[link_section = ".HardFault.user"]
// pub unsafe extern "C" fn __cortex_m_rt_HardFault_trampoline(frame: &::cortex_m_rt::ExceptionFrame) {
// __cortex_m_rt_HardFault(frame)
// }
// ```
//
// The `HardFault` handler has access to the exception `frame`, a
// snapshot of the CPU registers at the moment of the exception.
//
// To better see what is happening we make a `--release` build
// (It reduces the amount of redundant code.)
//
// ``` text
// $ cargo run --example crash --release
// ...
// Breakpoint 1, main () at examples/crash.rs:69
// (gdb) continue
// Breakpoint 3, HardFault (frame=0x20007fe0) at examples/crash.rs:82
// 82 #[exception]
// (gdb) p/x *frame
// $1 = cortex_m_rt::ExceptionFrame {r0: 0x2fffffff, r1: 0xf00000, r2: 0x0, r3: 0x0, r12: 0x0, lr: 0x8000405, pc: 0x800040a, xpsr: 0x61000000}
// (gdb) disassemble frame.pc
// Dump of assembler code for function crash::__cortex_m_rt_main:
// 0x08000406 <+0>: mvn.w r0, #3489660928 ; 0xd0000000
// 0x0800040a <+4>: ldr r0, [r0, #0]
// 0x0800040c <+6>: b.n 0x800040c <crash::__cortex_m_rt_main+6>
// End of assembler dump.
// ```
//
// The program counter (frame.pc) 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. In our case its the `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 find that `r0` contained the address `0x2FFF_FFFF` when this instruction was executed.
//
// Looking at the assembly `mvn.w r0, #3489660928 ; 0xd0000000`.
// This is a *move* and *not*, so the resulting value here is actually
// 0x2fffffff. Why did it not do it straight up then as 0x2FFF_FFFF?
//
// Well a 32 bit constant cannot be stored in a 32 bit instruction.
// So under the hood it stores 0xd0, bit shifts it and bit wise inversion.
// This is the level of optimization Rust + LLVM is capable of.
//
// We can further backtrace the calls leading up to the fault.
// ``` text
// ((gdb) bt
// #0 HardFault (frame=0x20007fe0) at examples/crash.rs:79
// #1 <signal handler called>
// #2 core::ptr::read_volatile (src=0x2fffffff)
// at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libcore/ptr/mod.rs:948
// #3 crash::__cortex_m_rt_main () at examples/crash.rs:71
// #4 0x08000404 in main () at examples/crash.rs:66
// ```
// Here we see that on frame #2 we are doing the read causing havoc.
......@@ -5,7 +5,7 @@
#![no_std]
#[allow(unused_extern_crates)]
extern crate panic_halt;
use panic_halt as _;
use cortex_m::{iprint, peripheral::syst::SystClkSource};
use cortex_m_rt::entry;
......
......@@ -7,10 +7,11 @@
//! ---
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
extern crate panic_halt;
use panic_halt as _;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::Peripherals;
......
......@@ -4,13 +4,12 @@
//!
//! [1]: https://rust-embedded.github.io/cortex-m-rt/0.6.1/cortex_m_rt_macros/fn.exception.html
//!
//! Notice, steal will panic! in debug mode, due to a `debug_assert` (ignored in release).
//! ---
#![no_main]
#![no_std]
extern crate panic_halt;
use panic_halt as _;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::{iprint, iprintln, Peripherals};
......
......@@ -8,7 +8,7 @@
#![no_main]
#![no_std]
extern crate panic_halt;
use panic_halt as _;
use cortex_m::peripheral::{syst::SystClkSource, ITM};
use cortex_m::{iprint, iprintln, Peripherals};
......
//! Prints "Hello, world!" on the host console using semihosting
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
extern crate panic_halt;
use panic_halt as _;
use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
......
......@@ -7,11 +7,12 @@
//! [`itmdump`]: https://docs.rs/itm/0.3.1/itm/
//!
//! ---
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
extern crate panic_halt;
use panic_halt as _;
use cortex_m::{iprintln, Peripherals};
use cortex_m_rt::entry;
......
......@@ -4,21 +4,21 @@
//!
//! [0]: https://crates.io/keywords/panic-impl
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
// Pick one of these panic handlers:
// `panic!` halts execution; the panic message is ignored
extern crate panic_halt;
use panic_halt as _;
// Reports panic messages to the host stderr using semihosting
// NOTE to use this you need to uncomment the `panic-semihosting` dependency in Cargo.toml
// extern crate panic_semihosting;
//use panic_semihosting as _;
// Logs panic messages using the ITM (Instrumentation Trace Macrocell)
// NOTE to use this you need to uncomment the `panic-itm` dependency in Cargo.toml
//extern crate panic_itm;
//use panic_itm as _;
use cortex_m_rt::entry;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment