update examples and docs
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#![feature(alloc)]
|
#![feature(alloc)]
|
||||||
#![feature(global_allocator)]
|
#![feature(global_allocator)]
|
||||||
#![feature(used)]
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
// This is the allocator crate; you can use a different one
|
// This is the allocator crate; you can use a different one
|
||||||
@@ -19,42 +19,52 @@ extern crate alloc_cortex_m;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate cortex_m;
|
extern crate cortex_m;
|
||||||
extern crate cortex_m_rt;
|
#[macro_use]
|
||||||
extern crate cortex_m_semihosting;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate panic_abort; // panicking behavior
|
extern crate cortex_m_semihosting as sh;
|
||||||
|
extern crate panic_abort;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
use alloc_cortex_m::CortexMHeap;
|
use alloc_cortex_m::CortexMHeap;
|
||||||
use cortex_m::asm;
|
use cortex_m::asm;
|
||||||
use cortex_m_semihosting::hio;
|
use rt::ExceptionFrame;
|
||||||
|
use sh::hio;
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
|
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
static mut _sheap: u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
const HEAP_SIZE: usize = 1024; // in bytes
|
const HEAP_SIZE: usize = 1024; // in bytes
|
||||||
|
|
||||||
fn main() {
|
main!(main);
|
||||||
|
|
||||||
|
fn main() -> ! {
|
||||||
// Initialize the allocator
|
// Initialize the allocator
|
||||||
let start = unsafe { &mut _sheap as *mut u32 as usize };
|
unsafe { ALLOCATOR.init(rt::heap_start() as usize, HEAP_SIZE) }
|
||||||
unsafe { ALLOCATOR.init(start, HEAP_SIZE) }
|
|
||||||
|
|
||||||
// Growable array allocated on the heap
|
// Growable array allocated on the heap
|
||||||
let xs = vec![0, 1, 2];
|
let xs = vec![0, 1, 2];
|
||||||
|
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
writeln!(stdout, "{:?}", xs).unwrap();
|
writeln!(stdout, "{:?}", xs).unwrap();
|
||||||
|
|
||||||
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// As we are not using interrupts, we just register a dummy catch all handler
|
exception!(DefaultHandler, dh);
|
||||||
#[link_section = ".vector_table.interrupts"]
|
|
||||||
#[used]
|
|
||||||
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
|
||||||
|
|
||||||
extern "C" fn default_handler() {
|
#[inline(always)]
|
||||||
|
fn dh(_nr: u8) {
|
||||||
asm::bkpt();
|
asm::bkpt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exception!(HardFault, hf);
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
asm::bkpt();
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interrupts!(DefaultHandler);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
extern crate cortex_m;
|
extern crate cortex_m;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate panic_abort; // panicking behavior
|
extern crate panic_abort;
|
||||||
|
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
//! Using a device crate
|
//! Using a device crate
|
||||||
//!
|
//!
|
||||||
//! Crates generated using [`svd2rust`] are referred to as device crates. These crates provides an
|
//! Crates generated using [`svd2rust`] are referred to as device crates. These crates provides an
|
||||||
//! API to access the peripherals of a device. When you depend on one of these crates and the "rt"
|
//! API to access the peripherals of a device.
|
||||||
//! feature is enabled you don't need link to the cortex-m-rt crate.
|
|
||||||
//!
|
//!
|
||||||
//! [`svd2rust`]: https://crates.io/crates/svd2rust
|
//! [`svd2rust`]: https://crates.io/crates/svd2rust
|
||||||
//!
|
//!
|
||||||
//! Device crates also provide an `interrupt!` macro to register interrupt handlers.
|
//! Device crates also provide an `interrupt!` macro (behind the "rt" feature) to register interrupt
|
||||||
|
//! handlers.
|
||||||
//!
|
//!
|
||||||
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it to your Cargo.toml.
|
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it to your Cargo.toml.
|
||||||
//!
|
//!
|
||||||
@@ -16,80 +16,82 @@
|
|||||||
//! $ edit Cargo.toml && tail $_
|
//! $ edit Cargo.toml && tail $_
|
||||||
//! [dependencies.stm32f103xx]
|
//! [dependencies.stm32f103xx]
|
||||||
//! features = ["rt"]
|
//! features = ["rt"]
|
||||||
//! version = "0.9.0"
|
//! version = "0.10.0"
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! The `stm32f103xx` crate provides an `interrupts.x` file so you must remove the one in the root
|
||||||
|
//! of this crate.
|
||||||
|
//!
|
||||||
//! ---
|
//! ---
|
||||||
|
|
||||||
#![deny(warnings)]
|
#![no_main]
|
||||||
#![feature(const_fn)]
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate cortex_m;
|
extern crate cortex_m;
|
||||||
// extern crate cortex_m_rt; // included in the device crate
|
#[macro_use]
|
||||||
extern crate cortex_m_semihosting;
|
extern crate cortex_m_rt as rt;
|
||||||
#[macro_use(exception, interrupt)]
|
extern crate cortex_m_semihosting as sh;
|
||||||
|
#[macro_use]
|
||||||
extern crate stm32f103xx;
|
extern crate stm32f103xx;
|
||||||
extern crate panic_abort; // panicking behavior
|
extern crate panic_abort;
|
||||||
|
|
||||||
use core::cell::RefCell;
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
use cortex_m::interrupt::{self, Mutex};
|
use cortex_m::asm;
|
||||||
use cortex_m::peripheral::syst::SystClkSource;
|
use cortex_m::peripheral::syst::SystClkSource;
|
||||||
use cortex_m_semihosting::hio::{self, HStdout};
|
use rt::ExceptionFrame;
|
||||||
|
use sh::hio::{self, HStdout};
|
||||||
use stm32f103xx::Interrupt;
|
use stm32f103xx::Interrupt;
|
||||||
|
|
||||||
static HSTDOUT: Mutex<RefCell<Option<HStdout>>> = Mutex::new(RefCell::new(None));
|
main!(main);
|
||||||
|
|
||||||
static NVIC: Mutex<RefCell<Option<cortex_m::peripheral::NVIC>>> = Mutex::new(RefCell::new(None));
|
fn main() -> ! {
|
||||||
|
let p = cortex_m::Peripherals::take().unwrap();
|
||||||
|
|
||||||
fn main() {
|
let mut syst = p.SYST;
|
||||||
let global_p = cortex_m::Peripherals::take().unwrap();
|
let mut nvic = p.NVIC;
|
||||||
interrupt::free(|cs| {
|
|
||||||
let hstdout = HSTDOUT.borrow(cs);
|
|
||||||
if let Ok(fd) = hio::hstdout() {
|
|
||||||
*hstdout.borrow_mut() = Some(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut nvic = global_p.NVIC;
|
nvic.enable(Interrupt::EXTI0);
|
||||||
nvic.enable(Interrupt::TIM2);
|
|
||||||
*NVIC.borrow(cs).borrow_mut() = Some(nvic);
|
|
||||||
|
|
||||||
let mut syst = global_p.SYST;
|
|
||||||
syst.set_clock_source(SystClkSource::Core);
|
syst.set_clock_source(SystClkSource::Core);
|
||||||
syst.set_reload(8_000_000); // 1s
|
syst.set_reload(8_000_000); // 1s
|
||||||
syst.enable_counter();
|
syst.enable_counter();
|
||||||
syst.enable_interrupt();
|
|
||||||
});
|
loop {
|
||||||
|
// busy wait until the timer wraps around
|
||||||
|
while !syst.has_wrapped() {}
|
||||||
|
|
||||||
|
// trigger the `EXTI0` interrupt
|
||||||
|
nvic.set_pending(Interrupt::EXTI0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exception!(SYS_TICK, tick);
|
interrupt!(EXTI0, exti0, state: Option<HStdout> = None);
|
||||||
|
|
||||||
fn tick() {
|
fn exti0(state: &mut Option<HStdout>) {
|
||||||
interrupt::free(|cs| {
|
if state.is_none() {
|
||||||
let hstdout = HSTDOUT.borrow(cs);
|
*state = Some(hio::hstdout().unwrap());
|
||||||
if let Some(hstdout) = hstdout.borrow_mut().as_mut() {
|
|
||||||
writeln!(*hstdout, "Tick").ok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(nvic) = NVIC.borrow(cs).borrow_mut().as_mut() {
|
if let Some(hstdout) = state.as_mut() {
|
||||||
nvic.set_pending(Interrupt::TIM2);
|
hstdout.write_str(".").unwrap();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupt!(TIM2, tock, locals: {
|
exception!(DefaultHandler, deh);
|
||||||
tocks: u32 = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
fn tock(l: &mut TIM2::Locals) {
|
#[inline(always)]
|
||||||
l.tocks += 1;
|
fn deh(_nr: u8) {
|
||||||
|
asm::bkpt();
|
||||||
|
}
|
||||||
|
|
||||||
interrupt::free(|cs| {
|
exception!(HardFault, hf);
|
||||||
let hstdout = HSTDOUT.borrow(cs);
|
|
||||||
if let Some(hstdout) = hstdout.borrow_mut().as_mut() {
|
#[inline(always)]
|
||||||
writeln!(*hstdout, "Tock ({})", l.tocks).ok();
|
fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
}
|
asm::bkpt();
|
||||||
});
|
|
||||||
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interrupts!(DefaultHandler);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ extern crate cortex_m;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
extern crate panic_abort; // panicking behavior
|
extern crate panic_abort;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,40 @@
|
|||||||
|
//! Minimal Cortex-M program
|
||||||
|
//!
|
||||||
|
//! All Cortex-M programs need to:
|
||||||
|
//!
|
||||||
|
//! - Contain the `#![no_main]` and `#![no_std]` attributes. Embedded programs don't use the
|
||||||
|
//! standard Rust `main` interface or the Rust standard (`std`) library.
|
||||||
|
//!
|
||||||
|
//! - Define their entry point using `main!`. The entry point doesn't need to be called `main` and
|
||||||
|
//! it doesn't need to be in the root of the crate.
|
||||||
|
//!
|
||||||
|
//! - Define their panicking behavior, i.e. what happens when `panic!` is called. The easiest way to
|
||||||
|
//! define a panicking behavior is to link to a [panic implementation crate][0]
|
||||||
|
//!
|
||||||
|
//! [0]: https://crates.io/keywords/panic-impl
|
||||||
|
//!
|
||||||
|
//! - Define the `HardFault` handler. This function is called when a hard fault exception is raised
|
||||||
|
//! by the hardware.
|
||||||
|
//!
|
||||||
|
//! - Define a default handler. This function will be used to handle all interrupts and exceptions
|
||||||
|
//! which have not been assigned a specific handler.
|
||||||
|
//!
|
||||||
|
//! - Define the device specific interrupt handlers. `interrupts!` can be used to create a generic
|
||||||
|
//! program that works for all Cortex-M devices by binding all the possible interrupt handlers to
|
||||||
|
//! the `DefaultHandler`.
|
||||||
|
|
||||||
#![no_main] // <- IMPORTANT!
|
#![no_main] // <- IMPORTANT!
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate cortex_m;
|
extern crate cortex_m;
|
||||||
#[macro_use]
|
#[macro_use(main, exception, interrupts)]
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate panic_abort;
|
extern crate panic_abort; // panicking behavior
|
||||||
|
|
||||||
use cortex_m::asm;
|
use cortex_m::asm;
|
||||||
use rt::ExceptionFrame;
|
use rt::ExceptionFrame;
|
||||||
|
|
||||||
// user entry point
|
// the program entry point
|
||||||
main!(main);
|
main!(main);
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
//! Prints "Hello, world!" on the OpenOCD console using semihosting
|
|
||||||
//!
|
|
||||||
//! ---
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! #![feature(used)]
|
|
||||||
//! #![no_std]
|
|
||||||
//!
|
|
||||||
//! extern crate cortex_m;
|
|
||||||
//! extern crate cortex_m_rt;
|
|
||||||
//! extern crate cortex_m_semihosting;
|
|
||||||
//! extern crate panic_abort; // panicking behavior
|
|
||||||
//!
|
|
||||||
//! use core::fmt::Write;
|
|
||||||
//!
|
|
||||||
//! use cortex_m::asm;
|
|
||||||
//! use cortex_m_semihosting::hio;
|
|
||||||
//!
|
|
||||||
//! fn main() {
|
|
||||||
//! let mut stdout = hio::hstdout().unwrap();
|
|
||||||
//! writeln!(stdout, "Hello, world!").unwrap();
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! // 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.
|
|
||||||
70
src/examples/_0_minimal.rs
Normal file
70
src/examples/_0_minimal.rs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
//! Minimal Cortex-M program
|
||||||
|
//!
|
||||||
|
//! All Cortex-M programs need to:
|
||||||
|
//!
|
||||||
|
//! - Contain the `#![no_main]` and `#![no_std]` attributes. Embedded programs don't use the
|
||||||
|
//! standard Rust `main` interface or the Rust standard (`std`) library.
|
||||||
|
//!
|
||||||
|
//! - Define their entry point using `main!`. The entry point doesn't need to be called `main` and
|
||||||
|
//! it doesn't need to be in the root of the crate.
|
||||||
|
//!
|
||||||
|
//! - Define their panicking behavior, i.e. what happens when `panic!` is called. The easiest way to
|
||||||
|
//! define a panicking behavior is to link to a [panic implementation crate][0]
|
||||||
|
//!
|
||||||
|
//! [0]: https://crates.io/keywords/panic-impl
|
||||||
|
//!
|
||||||
|
//! - Define the `HardFault` handler. This function is called when a hard fault exception is raised
|
||||||
|
//! by the hardware.
|
||||||
|
//!
|
||||||
|
//! - Define a default handler. This function will be used to handle all interrupts and exceptions
|
||||||
|
//! which have not been assigned a specific handler.
|
||||||
|
//!
|
||||||
|
//! - Define the device specific interrupt handlers. `interrupts!` can be used to create a generic
|
||||||
|
//! program that works for all Cortex-M devices by binding all the possible interrupt handlers to
|
||||||
|
//! the `DefaultHandler`.
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! #![no_main] // <- IMPORTANT!
|
||||||
|
//! #![no_std]
|
||||||
|
//!
|
||||||
|
//! extern crate cortex_m;
|
||||||
|
//! #[macro_use(main, exception, interrupts)]
|
||||||
|
//! extern crate cortex_m_rt as rt;
|
||||||
|
//! extern crate panic_abort; // panicking behavior
|
||||||
|
//!
|
||||||
|
//! use cortex_m::asm;
|
||||||
|
//! use rt::ExceptionFrame;
|
||||||
|
//!
|
||||||
|
//! // the program entry point
|
||||||
|
//! main!(main);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn main() -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! // define the default exception handler
|
||||||
|
//! exception!(DefaultHandler, deh);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn deh(_nr: u8) {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! // define the hard fault handler
|
||||||
|
//! exception!(HardFault, hf);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! // bind all interrupts to the default exception handler
|
||||||
|
//! interrupts!(DefaultHandler);
|
||||||
|
//! ```
|
||||||
|
// Auto-generated. Do not modify.
|
||||||
50
src/examples/_1_hello.rs
Normal file
50
src/examples/_1_hello.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//! Prints "Hello, world!" on the OpenOCD console using semihosting
|
||||||
|
//!
|
||||||
|
//! ---
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! #![no_main]
|
||||||
|
//! #![no_std]
|
||||||
|
//!
|
||||||
|
//! extern crate cortex_m;
|
||||||
|
//! #[macro_use]
|
||||||
|
//! extern crate cortex_m_rt as rt;
|
||||||
|
//! extern crate cortex_m_semihosting as sh;
|
||||||
|
//! extern crate panic_abort;
|
||||||
|
//!
|
||||||
|
//! use core::fmt::Write;
|
||||||
|
//!
|
||||||
|
//! use cortex_m::asm;
|
||||||
|
//! use rt::ExceptionFrame;
|
||||||
|
//! use sh::hio;
|
||||||
|
//!
|
||||||
|
//! main!(main);
|
||||||
|
//!
|
||||||
|
//! fn main() -> ! {
|
||||||
|
//! let mut stdout = hio::hstdout().unwrap();
|
||||||
|
//! writeln!(stdout, "Hello, world!").unwrap();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(DefaultHandler, dh);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn dh(_nr: u8) {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(HardFault, hf);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! // As we are not using interrupts, we just bind them all to the `DefaultHandler` exception handler
|
||||||
|
//! interrupts!(DefaultHandler);
|
||||||
|
//! ```
|
||||||
|
// Auto-generated. Do not modify.
|
||||||
@@ -14,30 +14,46 @@
|
|||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! #![feature(used)]
|
//! #![no_main]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! #[macro_use]
|
//! #[macro_use]
|
||||||
//! extern crate cortex_m;
|
//! extern crate cortex_m;
|
||||||
//! extern crate cortex_m_rt;
|
//! #[macro_use]
|
||||||
|
//! extern crate cortex_m_rt as rt;
|
||||||
//! extern crate panic_abort; // panicking behavior
|
//! extern crate panic_abort; // panicking behavior
|
||||||
//!
|
//!
|
||||||
//! use cortex_m::{asm, Peripherals};
|
//! use cortex_m::{asm, Peripherals};
|
||||||
|
//! use rt::ExceptionFrame;
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! main!(main);
|
||||||
//! let p = Peripherals::take().unwrap();
|
|
||||||
//! let mut itm = p.ITM;
|
|
||||||
//!
|
//!
|
||||||
//! iprintln!(&mut itm.stim[0], "Hello, world!");
|
//! #[inline(always)]
|
||||||
|
//! fn main() -> ! {
|
||||||
|
//! let mut p = Peripherals::take().unwrap();
|
||||||
|
//! let stim = &mut p.ITM.stim[0];
|
||||||
|
//!
|
||||||
|
//! iprintln!(stim, "Hello, world!");
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // As we are not using interrupts, we just register a dummy catch all handler
|
//! exception!(DefaultHandler, dh);
|
||||||
//! #[link_section = ".vector_table.interrupts"]
|
|
||||||
//! #[used]
|
|
||||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
|
||||||
//!
|
//!
|
||||||
//! extern "C" fn default_handler() {
|
//! #[inline(always)]
|
||||||
|
//! fn dh(_nr: u8) {
|
||||||
//! asm::bkpt();
|
//! asm::bkpt();
|
||||||
//! }
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(HardFault, hf);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! interrupts!(DefaultHandler);
|
||||||
//! ```
|
//! ```
|
||||||
// Auto-generated. Do not modify.
|
// Auto-generated. Do not modify.
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
//! 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;
|
|
||||||
//! extern crate panic_abort; // panicking behavior
|
|
||||||
//!
|
|
||||||
//! 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.
|
|
||||||
@@ -9,27 +9,41 @@
|
|||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! #![feature(used)]
|
//! #![no_main]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! extern crate cortex_m;
|
//! extern crate cortex_m;
|
||||||
//! extern crate cortex_m_rt;
|
//! #[macro_use]
|
||||||
|
//! extern crate cortex_m_rt as rt;
|
||||||
//! // extern crate panic_abort;
|
//! // extern crate panic_abort;
|
||||||
//! extern crate panic_semihosting; // reports panic messages to the host stderr using semihosting
|
//! extern crate panic_semihosting; // reports panic messages to the host stderr using semihosting
|
||||||
//!
|
//!
|
||||||
//! use cortex_m::asm;
|
//! use cortex_m::asm;
|
||||||
|
//! use rt::ExceptionFrame;
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! main!(main);
|
||||||
//! panic!("Oops");
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn main() -> ! {
|
||||||
|
//! panic!("Oops")
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // As we are not using interrupts, we just register a dummy catch all handler
|
//! exception!(DefaultHandler, deh);
|
||||||
//! #[link_section = ".vector_table.interrupts"]
|
|
||||||
//! #[used]
|
|
||||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
|
||||||
//!
|
//!
|
||||||
//! extern "C" fn default_handler() {
|
//! #[inline(always)]
|
||||||
|
//! fn deh(_nr: u8) {
|
||||||
//! asm::bkpt();
|
//! asm::bkpt();
|
||||||
//! }
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(HardFault, hf);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! interrupts!(DefaultHandler);
|
||||||
//! ```
|
//! ```
|
||||||
// Auto-generated. Do not modify.
|
// Auto-generated. Do not modify.
|
||||||
115
src/examples/_4_crash.rs
Normal file
115
src/examples/_4_crash.rs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
//! 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) continue
|
||||||
|
//! Program received signal SIGTRAP, Trace/breakpoint trap.
|
||||||
|
//! __bkpt () at asm/bkpt.s:3
|
||||||
|
//! 3 bkpt
|
||||||
|
//!
|
||||||
|
//! (gdb) finish
|
||||||
|
//! Run till exit from #0 __bkpt () at asm/bkpt.s:3
|
||||||
|
//! Note: automatically using hardware breakpoints for read-only addresses.
|
||||||
|
//! crash::hf (_ef=0x20004fa0) at examples/crash.rs:102
|
||||||
|
//! 99 asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! (gdb) # Exception frame = program state during the crash
|
||||||
|
//! (gdb) print/x *_ef
|
||||||
|
//! $1 = cortex_m_rt::ExceptionFrame {
|
||||||
|
//! r0: 0x2fffffff,
|
||||||
|
//! r1: 0x2fffffff,
|
||||||
|
//! r2: 0x80006b0,
|
||||||
|
//! r3: 0x80006b0,
|
||||||
|
//! r12: 0x20000000,
|
||||||
|
//! lr: 0x800040f,
|
||||||
|
//! pc: 0x800066a,
|
||||||
|
//! xpsr: 0x61000000
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! (gdb) # Where did we come from?
|
||||||
|
//! (gdb) backtrace
|
||||||
|
//! #0 crash::hf (_ef=0x20004fa0) at examples/crash.rs:102
|
||||||
|
//! #1 0x080004ac in UserHardFault (ef=0x20004fa0) at <exception macros>:9
|
||||||
|
//! #2 <signal handler called>
|
||||||
|
//! #3 0x0800066a in core::ptr::read_volatile (src=0x2fffffff) at /checkout/src/libcore/ptr.rs:452
|
||||||
|
//! #4 0x0800040e in crash::main () at examples/crash.rs:85
|
||||||
|
//! #5 0x08000456 in main () at <main macros>:3
|
||||||
|
//!
|
||||||
|
//! (gdb) # Nail down the location of the crash
|
||||||
|
//! (gdb) disassemble/m _ef.pc
|
||||||
|
//! Dump of assembler code for function core::ptr::read_volatile:
|
||||||
|
//! 451 pub unsafe fn read_volatile<T>(src: *const T) -> T {}
|
||||||
|
//! 0x08000662 <+0>: sub sp, #16
|
||||||
|
//! 0x08000664 <+2>: mov r1, r0
|
||||||
|
//! 0x08000666 <+4>: str r0, [sp, #8]
|
||||||
|
//!
|
||||||
|
//! 452 intrinsics::volatile_load(src)
|
||||||
|
//! 0x08000668 <+6>: ldr r0, [sp, #8]
|
||||||
|
//! 0x0800066a <+8>: ldr r0, [r0, #0]
|
||||||
|
//! 0x0800066c <+10>: str r0, [sp, #12]
|
||||||
|
//! 0x0800066e <+12>: ldr r0, [sp, #12]
|
||||||
|
//! 0x08000670 <+14>: str r1, [sp, #4]
|
||||||
|
//! 0x08000672 <+16>: str r0, [sp, #0]
|
||||||
|
//! 0x08000674 <+18>: b.n 0x8000676 <core::ptr::read_volatile+20>
|
||||||
|
//!
|
||||||
|
//! 453 }
|
||||||
|
//! 0x08000676 <+20>: ldr r0, [sp, #0]
|
||||||
|
//! 0x08000678 <+22>: add sp, #16
|
||||||
|
//! 0x0800067a <+24>: bx lr
|
||||||
|
//!
|
||||||
|
//! End of assembler dump.
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ---
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! #![no_main]
|
||||||
|
//! #![no_std]
|
||||||
|
//!
|
||||||
|
//! extern crate cortex_m;
|
||||||
|
//! #[macro_use]
|
||||||
|
//! extern crate cortex_m_rt as rt;
|
||||||
|
//! extern crate panic_abort;
|
||||||
|
//!
|
||||||
|
//! use core::ptr;
|
||||||
|
//!
|
||||||
|
//! use cortex_m::asm;
|
||||||
|
//! use rt::ExceptionFrame;
|
||||||
|
//!
|
||||||
|
//! main!(main);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn main() -> ! {
|
||||||
|
//! unsafe {
|
||||||
|
//! ptr::read_volatile(0x2FFF_FFFF as *const u32);
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(DefaultHandler, dh);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn dh(_nr: u8) {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(HardFault, hf);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! interrupts!(DefaultHandler);
|
||||||
|
//! ```
|
||||||
|
// Auto-generated. Do not modify.
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
//! Overriding an exception handler
|
|
||||||
//!
|
|
||||||
//! You can override an exception handler using the [`exception!`][1] macro.
|
|
||||||
//!
|
|
||||||
//! [1]: https://docs.rs/cortex-m-rt/0.3.2/cortex_m_rt/macro.exception.html
|
|
||||||
//!
|
|
||||||
//! The default exception handler can be overridden using the [`default_handler!`][2] macro
|
|
||||||
//!
|
|
||||||
//! [2]: https://docs.rs/cortex-m-rt/0.3.2/cortex_m_rt/macro.default_handler.html
|
|
||||||
//!
|
|
||||||
//! ---
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! #![feature(used)]
|
|
||||||
//! #![no_std]
|
|
||||||
//!
|
|
||||||
//! extern crate cortex_m;
|
|
||||||
//! #[macro_use(exception)]
|
|
||||||
//! extern crate cortex_m_rt;
|
|
||||||
//! extern crate panic_abort; // panicking behavior
|
|
||||||
//!
|
|
||||||
//! use core::ptr;
|
|
||||||
//!
|
|
||||||
//! use cortex_m::asm;
|
|
||||||
//!
|
|
||||||
//! fn main() {
|
|
||||||
//! unsafe {
|
|
||||||
//! // Invalid memory access
|
|
||||||
//! ptr::read_volatile(0x2FFF_FFFF as *const u32);
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! exception!(HARD_FAULT, handler);
|
|
||||||
//!
|
|
||||||
//! fn handler() {
|
|
||||||
//! // You'll hit this breakpoint rather than the one in cortex-m-rt
|
|
||||||
//! asm::bkpt()
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! // As we are not using interrupts, we just register a dummy catch all handler
|
|
||||||
//! #[allow(dead_code)]
|
|
||||||
//! #[used]
|
|
||||||
//! #[link_section = ".vector_table.interrupts"]
|
|
||||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
|
||||||
//!
|
|
||||||
//! extern "C" fn default_handler() {
|
|
||||||
//! asm::bkpt();
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
// Auto-generated. Do not modify.
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
//! Using a device crate
|
|
||||||
//!
|
|
||||||
//! Crates generated using [`svd2rust`] are referred to as device crates. These crates provides an
|
|
||||||
//! API to access the peripherals of a device. When you depend on one of these crates and the "rt"
|
|
||||||
//! feature is enabled you don't need link to the cortex-m-rt crate.
|
|
||||||
//!
|
|
||||||
//! [`svd2rust`]: https://crates.io/crates/svd2rust
|
|
||||||
//!
|
|
||||||
//! Device crates also provide an `interrupt!` macro to register interrupt handlers.
|
|
||||||
//!
|
|
||||||
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it to your Cargo.toml.
|
|
||||||
//!
|
|
||||||
//! [`stm32f103xx`]: https://crates.io/crates/stm32f103xx
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//! $ edit Cargo.toml && tail $_
|
|
||||||
//! [dependencies.stm32f103xx]
|
|
||||||
//! features = ["rt"]
|
|
||||||
//! version = "0.9.0"
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! ---
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! #![deny(warnings)]
|
|
||||||
//! #![feature(const_fn)]
|
|
||||||
//! #![no_std]
|
|
||||||
//!
|
|
||||||
//! extern crate cortex_m;
|
|
||||||
//! // extern crate cortex_m_rt; // included in the device crate
|
|
||||||
//! extern crate cortex_m_semihosting;
|
|
||||||
//! #[macro_use(exception, interrupt)]
|
|
||||||
//! extern crate stm32f103xx;
|
|
||||||
//! extern crate panic_abort; // panicking behavior
|
|
||||||
//!
|
|
||||||
//! use core::cell::RefCell;
|
|
||||||
//! use core::fmt::Write;
|
|
||||||
//!
|
|
||||||
//! use cortex_m::interrupt::{self, Mutex};
|
|
||||||
//! use cortex_m::peripheral::syst::SystClkSource;
|
|
||||||
//! use cortex_m_semihosting::hio::{self, HStdout};
|
|
||||||
//! use stm32f103xx::Interrupt;
|
|
||||||
//!
|
|
||||||
//! static HSTDOUT: Mutex<RefCell<Option<HStdout>>> = Mutex::new(RefCell::new(None));
|
|
||||||
//!
|
|
||||||
//! static NVIC: Mutex<RefCell<Option<cortex_m::peripheral::NVIC>>> = Mutex::new(RefCell::new(None));
|
|
||||||
//!
|
|
||||||
//! fn main() {
|
|
||||||
//! let global_p = cortex_m::Peripherals::take().unwrap();
|
|
||||||
//! interrupt::free(|cs| {
|
|
||||||
//! let hstdout = HSTDOUT.borrow(cs);
|
|
||||||
//! if let Ok(fd) = hio::hstdout() {
|
|
||||||
//! *hstdout.borrow_mut() = Some(fd);
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! let mut nvic = global_p.NVIC;
|
|
||||||
//! nvic.enable(Interrupt::TIM2);
|
|
||||||
//! *NVIC.borrow(cs).borrow_mut() = Some(nvic);
|
|
||||||
//!
|
|
||||||
//! let mut syst = global_p.SYST;
|
|
||||||
//! syst.set_clock_source(SystClkSource::Core);
|
|
||||||
//! syst.set_reload(8_000_000); // 1s
|
|
||||||
//! syst.enable_counter();
|
|
||||||
//! syst.enable_interrupt();
|
|
||||||
//! });
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! exception!(SYS_TICK, tick);
|
|
||||||
//!
|
|
||||||
//! fn tick() {
|
|
||||||
//! interrupt::free(|cs| {
|
|
||||||
//! let hstdout = HSTDOUT.borrow(cs);
|
|
||||||
//! if let Some(hstdout) = hstdout.borrow_mut().as_mut() {
|
|
||||||
//! writeln!(*hstdout, "Tick").ok();
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! if let Some(nvic) = NVIC.borrow(cs).borrow_mut().as_mut() {
|
|
||||||
//! nvic.set_pending(Interrupt::TIM2);
|
|
||||||
//! }
|
|
||||||
//! });
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! interrupt!(TIM2, tock, locals: {
|
|
||||||
//! tocks: u32 = 0;
|
|
||||||
//! });
|
|
||||||
//!
|
|
||||||
//! fn tock(l: &mut TIM2::Locals) {
|
|
||||||
//! l.tocks += 1;
|
|
||||||
//!
|
|
||||||
//! interrupt::free(|cs| {
|
|
||||||
//! let hstdout = HSTDOUT.borrow(cs);
|
|
||||||
//! if let Some(hstdout) = hstdout.borrow_mut().as_mut() {
|
|
||||||
//! writeln!(*hstdout, "Tock ({})", l.tocks).ok();
|
|
||||||
//! }
|
|
||||||
//! });
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
// Auto-generated. Do not modify.
|
|
||||||
73
src/examples/_5_exception.rs
Normal file
73
src/examples/_5_exception.rs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
//! Overriding an exception handler
|
||||||
|
//!
|
||||||
|
//! You can override an exception handler using the [`exception!`][1] macro.
|
||||||
|
//!
|
||||||
|
//! [1]: https://docs.rs/cortex-m-rt/0.5.0/cortex_m_rt/macro.exception.html
|
||||||
|
//!
|
||||||
|
//! ---
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! #![deny(unsafe_code)]
|
||||||
|
//! #![no_main]
|
||||||
|
//! #![no_std]
|
||||||
|
//!
|
||||||
|
//! extern crate cortex_m;
|
||||||
|
//! #[macro_use]
|
||||||
|
//! extern crate cortex_m_rt as rt;
|
||||||
|
//! extern crate cortex_m_semihosting as sh;
|
||||||
|
//! extern crate panic_abort;
|
||||||
|
//!
|
||||||
|
//! use core::fmt::Write;
|
||||||
|
//!
|
||||||
|
//! use cortex_m::peripheral::syst::SystClkSource;
|
||||||
|
//! use cortex_m::{asm, Peripherals};
|
||||||
|
//! use rt::ExceptionFrame;
|
||||||
|
//! use sh::hio::{self, HStdout};
|
||||||
|
//!
|
||||||
|
//! main!(main);
|
||||||
|
//!
|
||||||
|
//! fn main() -> ! {
|
||||||
|
//! let p = Peripherals::take().unwrap();
|
||||||
|
//! let mut syst = p.SYST;
|
||||||
|
//!
|
||||||
|
//! syst.set_clock_source(SystClkSource::Core);
|
||||||
|
//! syst.set_reload(8_000_000); // 1s
|
||||||
|
//! syst.enable_counter();
|
||||||
|
//! syst.enable_interrupt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! // try commenting out this line: you'll end in `deh` instead of in `sys_tick`
|
||||||
|
//! exception!(SysTick, sys_tick, state: Option<HStdout> = None);
|
||||||
|
//!
|
||||||
|
//! fn sys_tick(state: &mut Option<HStdout>) {
|
||||||
|
//! if state.is_none() {
|
||||||
|
//! *state = Some(hio::hstdout().unwrap());
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! if let Some(hstdout) = state.as_mut() {
|
||||||
|
//! hstdout.write_str(".").unwrap();
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(DefaultHandler, deh);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn deh(_nr: u8) {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(HardFault, hf);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! interrupts!(DefaultHandler);
|
||||||
|
//! ```
|
||||||
|
// Auto-generated. Do not modify.
|
||||||
101
src/examples/_6_device.rs
Normal file
101
src/examples/_6_device.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
//! Using a device crate
|
||||||
|
//!
|
||||||
|
//! Crates generated using [`svd2rust`] are referred to as device crates. These crates provides an
|
||||||
|
//! API to access the peripherals of a device.
|
||||||
|
//!
|
||||||
|
//! [`svd2rust`]: https://crates.io/crates/svd2rust
|
||||||
|
//!
|
||||||
|
//! Device crates also provide an `interrupt!` macro (behind the "rt" feature) to register interrupt
|
||||||
|
//! handlers.
|
||||||
|
//!
|
||||||
|
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it to your Cargo.toml.
|
||||||
|
//!
|
||||||
|
//! [`stm32f103xx`]: https://crates.io/crates/stm32f103xx
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! $ edit Cargo.toml && tail $_
|
||||||
|
//! [dependencies.stm32f103xx]
|
||||||
|
//! features = ["rt"]
|
||||||
|
//! version = "0.10.0"
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! The `stm32f103xx` crate provides an `interrupts.x` file so you must remove the one in the root
|
||||||
|
//! of this crate.
|
||||||
|
//!
|
||||||
|
//! ---
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! #![no_main]
|
||||||
|
//! #![no_std]
|
||||||
|
//!
|
||||||
|
//! extern crate cortex_m;
|
||||||
|
//! #[macro_use]
|
||||||
|
//! extern crate cortex_m_rt as rt;
|
||||||
|
//! extern crate cortex_m_semihosting as sh;
|
||||||
|
//! #[macro_use]
|
||||||
|
//! extern crate stm32f103xx;
|
||||||
|
//! extern crate panic_abort;
|
||||||
|
//!
|
||||||
|
//! use core::fmt::Write;
|
||||||
|
//!
|
||||||
|
//! use cortex_m::asm;
|
||||||
|
//! use cortex_m::peripheral::syst::SystClkSource;
|
||||||
|
//! use rt::ExceptionFrame;
|
||||||
|
//! use sh::hio::{self, HStdout};
|
||||||
|
//! use stm32f103xx::Interrupt;
|
||||||
|
//!
|
||||||
|
//! main!(main);
|
||||||
|
//!
|
||||||
|
//! fn main() -> ! {
|
||||||
|
//! let p = cortex_m::Peripherals::take().unwrap();
|
||||||
|
//!
|
||||||
|
//! let mut syst = p.SYST;
|
||||||
|
//! let mut nvic = p.NVIC;
|
||||||
|
//!
|
||||||
|
//! nvic.enable(Interrupt::EXTI0);
|
||||||
|
//!
|
||||||
|
//! syst.set_clock_source(SystClkSource::Core);
|
||||||
|
//! syst.set_reload(8_000_000); // 1s
|
||||||
|
//! syst.enable_counter();
|
||||||
|
//!
|
||||||
|
//! loop {
|
||||||
|
//! // busy wait until the timer wraps around
|
||||||
|
//! while !syst.has_wrapped() {}
|
||||||
|
//!
|
||||||
|
//! // trigger the `EXTI0` interrupt
|
||||||
|
//! nvic.set_pending(Interrupt::EXTI0);
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! interrupt!(EXTI0, exti0, state: Option<HStdout> = None);
|
||||||
|
//!
|
||||||
|
//! fn exti0(state: &mut Option<HStdout>) {
|
||||||
|
//! if state.is_none() {
|
||||||
|
//! *state = Some(hio::hstdout().unwrap());
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! if let Some(hstdout) = state.as_mut() {
|
||||||
|
//! hstdout.write_str(".").unwrap();
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(DefaultHandler, deh);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn deh(_nr: u8) {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(HardFault, hf);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! interrupts!(DefaultHandler);
|
||||||
|
//! ```
|
||||||
|
// Auto-generated. Do not modify.
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
//!
|
//!
|
||||||
//! #![feature(alloc)]
|
//! #![feature(alloc)]
|
||||||
//! #![feature(global_allocator)]
|
//! #![feature(global_allocator)]
|
||||||
//! #![feature(used)]
|
//! #![no_main]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! // This is the allocator crate; you can use a different one
|
//! // This is the allocator crate; you can use a different one
|
||||||
@@ -21,44 +21,54 @@
|
|||||||
//! #[macro_use]
|
//! #[macro_use]
|
||||||
//! extern crate alloc;
|
//! extern crate alloc;
|
||||||
//! extern crate cortex_m;
|
//! extern crate cortex_m;
|
||||||
//! extern crate cortex_m_rt;
|
//! #[macro_use]
|
||||||
//! extern crate cortex_m_semihosting;
|
//! extern crate cortex_m_rt as rt;
|
||||||
//! extern crate panic_abort; // panicking behavior
|
//! extern crate cortex_m_semihosting as sh;
|
||||||
|
//! extern crate panic_abort;
|
||||||
//!
|
//!
|
||||||
//! use core::fmt::Write;
|
//! use core::fmt::Write;
|
||||||
//!
|
//!
|
||||||
//! use alloc_cortex_m::CortexMHeap;
|
//! use alloc_cortex_m::CortexMHeap;
|
||||||
//! use cortex_m::asm;
|
//! use cortex_m::asm;
|
||||||
//! use cortex_m_semihosting::hio;
|
//! use rt::ExceptionFrame;
|
||||||
|
//! use sh::hio;
|
||||||
//!
|
//!
|
||||||
//! #[global_allocator]
|
//! #[global_allocator]
|
||||||
//! static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
|
//! static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
|
||||||
//!
|
//!
|
||||||
//! extern "C" {
|
|
||||||
//! static mut _sheap: u32;
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! const HEAP_SIZE: usize = 1024; // in bytes
|
//! const HEAP_SIZE: usize = 1024; // in bytes
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! main!(main);
|
||||||
|
//!
|
||||||
|
//! fn main() -> ! {
|
||||||
//! // Initialize the allocator
|
//! // Initialize the allocator
|
||||||
//! let start = unsafe { &mut _sheap as *mut u32 as usize };
|
//! unsafe { ALLOCATOR.init(rt::heap_start() as usize, HEAP_SIZE) }
|
||||||
//! unsafe { ALLOCATOR.init(start, HEAP_SIZE) }
|
|
||||||
//!
|
//!
|
||||||
//! // Growable array allocated on the heap
|
//! // Growable array allocated on the heap
|
||||||
//! let xs = vec![0, 1, 2];
|
//! let xs = vec![0, 1, 2];
|
||||||
//!
|
//!
|
||||||
//! let mut stdout = hio::hstdout().unwrap();
|
//! let mut stdout = hio::hstdout().unwrap();
|
||||||
//! writeln!(stdout, "{:?}", xs).unwrap();
|
//! writeln!(stdout, "{:?}", xs).unwrap();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // As we are not using interrupts, we just register a dummy catch all handler
|
//! exception!(DefaultHandler, dh);
|
||||||
//! #[link_section = ".vector_table.interrupts"]
|
|
||||||
//! #[used]
|
|
||||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
|
||||||
//!
|
//!
|
||||||
//! extern "C" fn default_handler() {
|
//! #[inline(always)]
|
||||||
|
//! fn dh(_nr: u8) {
|
||||||
//! asm::bkpt();
|
//! asm::bkpt();
|
||||||
//! }
|
//! }
|
||||||
|
//!
|
||||||
|
//! exception!(HardFault, hf);
|
||||||
|
//!
|
||||||
|
//! #[inline(always)]
|
||||||
|
//! fn hf(_ef: &ExceptionFrame) -> ! {
|
||||||
|
//! asm::bkpt();
|
||||||
|
//!
|
||||||
|
//! loop {}
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! interrupts!(DefaultHandler);
|
||||||
//! ```
|
//! ```
|
||||||
// Auto-generated. Do not modify.
|
// Auto-generated. Do not modify.
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
//! Examples
|
//! Examples
|
||||||
// Auto-generated. Do not modify.
|
// Auto-generated. Do not modify.
|
||||||
pub mod _0_hello;
|
pub mod _0_minimal;
|
||||||
pub mod _1_itm;
|
pub mod _1_hello;
|
||||||
pub mod _2_panic;
|
pub mod _2_itm;
|
||||||
pub mod _3_crash;
|
pub mod _3_panic;
|
||||||
pub mod _4_override_exception_handler;
|
pub mod _4_crash;
|
||||||
pub mod _5_device;
|
pub mod _5_exception;
|
||||||
pub mod _6_allocator;
|
pub mod _6_device;
|
||||||
|
pub mod _7_allocator;
|
||||||
|
|||||||
54
src/lib.rs
54
src/lib.rs
@@ -4,9 +4,9 @@
|
|||||||
//!
|
//!
|
||||||
//! - Nightly Rust toolchain newer than `nightly-2018-04-08`: `rustup default nightly`
|
//! - Nightly Rust toolchain newer than `nightly-2018-04-08`: `rustup default nightly`
|
||||||
//! - Cargo `clone` subcommand: `cargo install cargo-clone`
|
//! - Cargo `clone` subcommand: `cargo install cargo-clone`
|
||||||
|
//! - ARM toolchain: `sudo apt-get install gcc-arm-none-eabi` (on Ubuntu)
|
||||||
//! - GDB: `sudo apt-get install gdb-arm-none-eabi` (on Ubuntu)
|
//! - GDB: `sudo apt-get install gdb-arm-none-eabi` (on Ubuntu)
|
||||||
//! - OpenOCD: `sudo apt-get install OpenOCD` (on Ubuntu)
|
//! - OpenOCD: `sudo apt-get install OpenOCD` (on Ubuntu)
|
||||||
//! - [Optional] ARM linker: `sudo apt-get install binutils-arm-none-eabi` (on Ubuntu)
|
|
||||||
//! - [Optional] Cargo `add` subcommand: `cargo install cargo-edit`
|
//! - [Optional] Cargo `add` subcommand: `cargo install cargo-edit`
|
||||||
//!
|
//!
|
||||||
//! # Usage
|
//! # Usage
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
//! 2) Clone this crate
|
//! 2) Clone this crate
|
||||||
//!
|
//!
|
||||||
//! ``` text
|
//! ``` text
|
||||||
//! $ cargo clone cortex-m-quickstart && cd $_
|
//! $ git clone https://github.com/japaric/cortex-m-quickstart --branch less-unstable
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! 3) Change the crate name, author and version
|
//! 3) Change the crate name, author and version
|
||||||
@@ -113,26 +113,6 @@
|
|||||||
//! Tag_ABI_FP_16bit_format: IEEE 754
|
//! Tag_ABI_FP_16bit_format: IEEE 754
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! **NOTE** By default Cargo will use the LLD linker shipped with the Rust toolchain. If you
|
|
||||||
//! encounter any linking error try to switch to the GNU linker by modifying the `.cargo/config`
|
|
||||||
//! file as shown below:
|
|
||||||
//!
|
|
||||||
//! ``` text
|
|
||||||
//! runner = 'arm-none-eabi-gdb'
|
|
||||||
//! rustflags = [
|
|
||||||
//! "-C", "link-arg=-Tlink.x",
|
|
||||||
//! - "-C", "linker=lld",
|
|
||||||
//! - "-Z", "linker-flavor=ld.lld",
|
|
||||||
//! - # "-C", "linker=arm-none-eabi-ld",
|
|
||||||
//! - # "-Z", "linker-flavor=ld",
|
|
||||||
//! + # "-C", "linker=lld",
|
|
||||||
//! + # "-Z", "linker-flavor=ld.lld",
|
|
||||||
//! + "-C", "linker=arm-none-eabi-ld",
|
|
||||||
//! + "-Z", "linker-flavor=ld",
|
|
||||||
//! "-Z", "thinlto=no",
|
|
||||||
//! ]
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! 9) Flash the program
|
//! 9) Flash the program
|
||||||
//!
|
//!
|
||||||
//! ``` text
|
//! ``` text
|
||||||
@@ -185,13 +165,7 @@
|
|||||||
//! Compiling demo v0.1.0 (file:///home/japaric/tmp/demo)
|
//! Compiling demo v0.1.0 (file:///home/japaric/tmp/demo)
|
||||||
//! error: linking with `arm-none-eabi-ld` failed: exit code: 1
|
//! error: linking with `arm-none-eabi-ld` failed: exit code: 1
|
||||||
//! |
|
//! |
|
||||||
//! = note: "lld" "-L" (..)
|
//! = note: "arm-none-eabi-gcc" "-L" (..)
|
||||||
//! = note: arm-none-eabi-ld: address 0xbaaab838 of hello section `.text' is ..
|
|
||||||
//! arm-none-eabi-ld: address 0xbaaab838 of hello section `.text' is ..
|
|
||||||
//! arm-none-eabi-ld:
|
|
||||||
//! Invalid '.rodata.exceptions' section.
|
|
||||||
//! Make sure to place a static with type `cortex_m::exception::Handlers`
|
|
||||||
//! in that section (cf. #[link_section]) ONLY ONCE.
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Solution: Specify your device memory layout in the `memory.x` linker script.
|
//! Solution: Specify your device memory layout in the `memory.x` linker script.
|
||||||
@@ -204,8 +178,7 @@
|
|||||||
//! ``` text
|
//! ``` text
|
||||||
//! $ cargo build
|
//! $ cargo build
|
||||||
//! (..)
|
//! (..)
|
||||||
//! Compiling cortex-m-semihosting v0.2.0
|
//! error: language item required, but not found: `eh_personality`
|
||||||
//! error[E0463]: can't find crate for `std`
|
|
||||||
//!
|
//!
|
||||||
//! error: aborting due to previous error
|
//! error: aborting due to previous error
|
||||||
//! ```
|
//! ```
|
||||||
@@ -259,6 +232,19 @@
|
|||||||
//! `/usr/share/openocd/scripts` directory (exact location varies per
|
//! `/usr/share/openocd/scripts` directory (exact location varies per
|
||||||
//! distribution / OS) for a list of scripts that can be used.
|
//! distribution / OS) for a list of scripts that can be used.
|
||||||
//!
|
//!
|
||||||
|
//! ## Forgot to install the `rust-std` component
|
||||||
|
//!
|
||||||
|
//! Error message:
|
||||||
|
//!
|
||||||
|
//! ``` text
|
||||||
|
//! $ cargo build
|
||||||
|
//! error[E0463]: can't find crate for `core`
|
||||||
|
//! |
|
||||||
|
//! = note: the `thumbv7m-none-eabi` target may not be installed
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Solution: call `rustup target add thumbv7m-none-eabi` but with the name of your target
|
||||||
|
//!
|
||||||
//! ## Used an old nightly
|
//! ## Used an old nightly
|
||||||
//!
|
//!
|
||||||
//! Error message:
|
//! Error message:
|
||||||
@@ -281,12 +267,10 @@
|
|||||||
//!
|
//!
|
||||||
//! ``` text
|
//! ``` text
|
||||||
//! $ cargo build
|
//! $ cargo build
|
||||||
//! error: failed to run `rustc` to learn about target-specific information
|
//! error[E0463]: can't find crate for `core`
|
||||||
//!
|
|
||||||
//! To learn more, run the command again with --verbose.
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Solution: Switch to the nightly toolchain with `rustup default nightly`.
|
//! Solution: We are not there yet! Switch to the nightly toolchain with `rustup default nightly`.
|
||||||
//!
|
//!
|
||||||
//! ## Used `gdb` instead of `arm-none-eabi-gdb`
|
//! ## Used `gdb` instead of `arm-none-eabi-gdb`
|
||||||
//!
|
//!
|
||||||
|
|||||||
Reference in New Issue
Block a user