Talk as presented plus example source for MSP432 blinky light demo

This commit is contained in:
Levi Pearson
2019-03-18 11:18:16 -06:00
parent a7eedbbf68
commit 4499e75a92
605 changed files with 218085 additions and 13 deletions

View File

@@ -0,0 +1,96 @@
//! 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 panic_halt;
use core::ptr;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
unsafe {
// read an address outside of the RAM region; this causes a HardFault exception
ptr::read_volatile(0x2FFF_FFFF as *const u32);
}
loop {}
}

View File

@@ -0,0 +1,37 @@
//! Overriding an exception handler
//!
//! You can override an exception handler using the [`#[exception]`][1] attribute.
//!
//! [1]: https://rust-embedded.github.io/cortex-m-rt/0.6.1/cortex_m_rt_macros/fn.exception.html
//!
//! ---
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::Peripherals;
use cortex_m_rt::{entry, exception};
use cortex_m_semihosting::hprint;
#[entry]
fn main() -> ! {
let p = Peripherals::take().unwrap();
let mut syst = p.SYST;
// configures the system timer to trigger a SysTick exception every second
syst.set_clock_source(SystClkSource::Core);
syst.set_reload(8_000_000); // period = 1s
syst.enable_counter();
syst.enable_interrupt();
loop {}
}
#[exception]
fn SysTick() {
hprint!(".").unwrap();
}

View File

@@ -0,0 +1,20 @@
//! Prints "Hello, world!" on the host console using semihosting
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
#[entry]
fn main() -> ! {
hprintln!("Hello, world!").unwrap();
// exit QEMU
// NOTE do not run this on hardware; it can corrupt OpenOCD state
debug::exit(debug::EXIT_SUCCESS);
loop {}
}

View File

@@ -0,0 +1,33 @@
//! Sends "Hello, world!" through the ITM port 0
//!
//! ITM is much faster than semihosting. Like 4 orders of magnitude or so.
//!
//! **NOTE** Cortex-M0 chips don't support ITM.
//!
//! You'll have to connect the microcontroller's SWO pin to the SWD interface. Note that some
//! development boards don't provide this option.
//!
//! You'll need [`itmdump`] to receive the message on the host plus you'll need to uncomment two
//! `monitor` commands in the `.gdbinit` file.
//!
//! [`itmdump`]: https://docs.rs/itm/0.2.1/itm/
//!
//! ---
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m::{iprintln, Peripherals};
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
let mut p = Peripherals::take().unwrap();
let stim = &mut p.ITM.stim[0];
iprintln!(stim, "Hello, world!");
loop {}
}

View File

@@ -0,0 +1,28 @@
//! Changing the panicking behavior
//!
//! The easiest way to change the panicking behavior is to use a different [panic handler crate][0].
//!
//! [0]: https://crates.io/keywords/panic-impl
#![no_main]
#![no_std]
// Pick one of these panic handlers:
// `panic!` halts execution; the panic message is ignored
extern crate panic_halt;
// 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;
// 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 cortex_m_rt::entry;
#[entry]
fn main() -> ! {
panic!("Oops")
}

View File

@@ -0,0 +1,57 @@
//! Conditionally compiling tests with std and our executable with no_std.
//!
//! Rust's built in unit testing framework requires the standard library,
//! but we need to build our final executable with no_std.
//! The testing framework also generates a `main` method, so we need to only use the `#[entry]`
//! annotation when building our final image.
//! For more information on why this example works, see this excellent blog post.
//! https://os.phil-opp.com/unit-testing/
//!
//! Running this example:
//!
//! Ensure there are no targets specified under `[build]` in `.cargo/config`
//! In order to make this work, we lose the convenience of having a default target that isn't the
//! host.
//!
//! cargo build --example test_on_host --target thumbv7m-none-eabi
//! cargo test --example test_on_host
#![cfg_attr(test, allow(unused_imports))]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(not(test), no_main)]
// pick a panicking behavior
#[cfg(not(test))]
extern crate panic_halt; // you can put a breakpoint on `rust_begin_unwind` to catch panics
// extern crate panic_abort; // requires nightly
// extern crate panic_itm; // logs messages over ITM; requires ITM support
// extern crate panic_semihosting; // logs messages to the host stderr; requires a debugger
use cortex_m::asm;
use cortex_m_rt::entry;
#[cfg(not(test))]
#[entry]
fn main() -> ! {
asm::nop(); // To not have main optimize to abort in release mode, remove when you add code
loop {
// your code goes here
}
}
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn foo() {
println!("tests work!");
assert!(2 == add(1,1));
}
}