turn into a Cargo crate
This commit is contained in:
28
src/examples/_0_hello.rs
Normal file
28
src/examples/_0_hello.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
//! Prints "Hello, world!" on the OpenOCD console using semihosting
|
||||
//!
|
||||
//! ```
|
||||
//!
|
||||
//! #![feature(used)]
|
||||
//! #![no_std]
|
||||
//!
|
||||
//! #[macro_use]
|
||||
//! extern crate cortex_m;
|
||||
//! extern crate cortex_m_rt;
|
||||
//!
|
||||
//! use cortex_m::asm;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! hprintln!("Hello, world!");
|
||||
//! }
|
||||
//!
|
||||
//! // As we are not using interrupts, we just register a dummy catch all handler
|
||||
//! #[allow(dead_code)]
|
||||
//! #[used]
|
||||
//! #[link_section = ".rodata.interrupts"]
|
||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
||||
//!
|
||||
//! extern "C" fn default_handler() {
|
||||
//! asm::bkpt();
|
||||
//! }
|
||||
//! ```
|
||||
// Auto-generated. Do not modify.
|
||||
45
src/examples/_1_itm.rs
Normal file
45
src/examples/_1_itm.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
//! Sends "Hello, world!" through the ITM port 0
|
||||
//!
|
||||
//! **IMPORTANT** Not all Cortex-M chips 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.
|
||||
//!
|
||||
//! ITM is much faster than semihosting. Like 4 orders of magnitude or so.
|
||||
//!
|
||||
//! You'll need [`itmdump`] to receive the message on the host plus you'll need
|
||||
//! to uncomment OpenOCD's ITM support in `.gdbinit`.
|
||||
//!
|
||||
//! [`itmdump`]: https://docs.rs/itm/0.1.1/itm/
|
||||
//!
|
||||
//! ```
|
||||
//!
|
||||
//! #![feature(used)]
|
||||
//! #![no_std]
|
||||
//!
|
||||
//! #[macro_use]
|
||||
//! extern crate cortex_m;
|
||||
//! extern crate cortex_m_rt;
|
||||
//!
|
||||
//! use cortex_m::{asm, interrupt, peripheral};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! interrupt::free(
|
||||
//! |cs| {
|
||||
//! let itm = peripheral::ITM.borrow(&cs);
|
||||
//!
|
||||
//! iprintln!(&itm.stim[0], "Hello, world!");
|
||||
//! },
|
||||
//! );
|
||||
//! }
|
||||
//!
|
||||
//! // As we are not using interrupts, we just register a dummy catch all handler
|
||||
//! #[allow(dead_code)]
|
||||
//! #[used]
|
||||
//! #[link_section = ".rodata.interrupts"]
|
||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
||||
//!
|
||||
//! extern "C" fn default_handler() {
|
||||
//! asm::bkpt();
|
||||
//! }
|
||||
//! ```
|
||||
// Auto-generated. Do not modify.
|
||||
39
src/examples/_2_panic.rs
Normal file
39
src/examples/_2_panic.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
//! Redirecting `panic!` messages
|
||||
//!
|
||||
//! The `cortex-m-rt` crate provides two options to redirect `panic!` messages
|
||||
//! through these two Cargo features:
|
||||
//!
|
||||
//! - `panic-over-semihosting`. `panic!` messages will be printed to the OpenOCD
|
||||
//! console using semihosting. This is slow.
|
||||
//!
|
||||
//! - `panic-over-itm`. `panic!` messages will be send through the ITM port 0.
|
||||
//! This is much faster but requires ITM support on the device.
|
||||
//!
|
||||
//! If neither of these options is specified then the `panic!` message will be
|
||||
//! lost. Note that all `panic!`s will trigger a debugger breakpoint.
|
||||
//!
|
||||
//! ```
|
||||
//!
|
||||
//! #![feature(used)]
|
||||
//! #![no_std]
|
||||
//!
|
||||
//! extern crate cortex_m;
|
||||
//! extern crate cortex_m_rt;
|
||||
//!
|
||||
//! use cortex_m::asm;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! panic!("Oops");
|
||||
//! }
|
||||
//!
|
||||
//! // As we are not using interrupts, we just register a dummy catch all handler
|
||||
//! #[allow(dead_code)]
|
||||
//! #[used]
|
||||
//! #[link_section = ".rodata.interrupts"]
|
||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
||||
//!
|
||||
//! extern "C" fn default_handler() {
|
||||
//! asm::bkpt();
|
||||
//! }
|
||||
//! ```
|
||||
// Auto-generated. Do not modify.
|
||||
62
src/examples/_3_crash.rs
Normal file
62
src/examples/_3_crash.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
//! 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:
|
||||
//!
|
||||
//! ```
|
||||
//! (gdb) # Stacked registers = program state during the crash
|
||||
//! (gdb) print/x *_sr
|
||||
//! $1 = cortex_m::exception::StackedRegisters {
|
||||
//! r0 = 0x2fffffff,
|
||||
//! r1 = 0x2fffffff,
|
||||
//! r2 = 0x0,
|
||||
//! r3 = 0x0,
|
||||
//! r12 = 0x0,
|
||||
//! lr = 0x8000443,
|
||||
//! pc = 0x8000190,
|
||||
//! xpsr = 0x61000200,
|
||||
//! }
|
||||
//!
|
||||
//! (gdb) # What exception was triggered?
|
||||
//! (gdb) print _e
|
||||
//! $2 = cortex_m::exception::Exception::HardFault
|
||||
//!
|
||||
//! (gdb) # Where did we come from?
|
||||
//! (gdb) print _e
|
||||
//! ```
|
||||
//!
|
||||
//! ```
|
||||
//!
|
||||
//! #![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
|
||||
//! #[allow(dead_code)]
|
||||
//! #[used]
|
||||
//! #[link_section = ".rodata.interrupts"]
|
||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
||||
//!
|
||||
//! extern "C" fn default_handler() {
|
||||
//! asm::bkpt();
|
||||
//! }
|
||||
//! ```
|
||||
// Auto-generated. Do not modify.
|
||||
40
src/examples/_4_register_interrupt_handler.rs
Normal file
40
src/examples/_4_register_interrupt_handler.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
//! Register an interrupt handler
|
||||
//!
|
||||
//! NOTE Requires a device crate generated using `svd2rust`
|
||||
//!
|
||||
//! ```
|
||||
//!
|
||||
//! #![feature(used)]
|
||||
//! #![no_std]
|
||||
//!
|
||||
//! extern crate cortex_m;
|
||||
//! extern crate cortex_m_rt;
|
||||
//! // NOTE this is the device crate
|
||||
//! extern crate stm32f30x;
|
||||
//!
|
||||
//! use cortex_m::asm;
|
||||
//! use stm32f30x::interrupt;
|
||||
//!
|
||||
//! fn main() {}
|
||||
//!
|
||||
//! // NOTE each interrupt handler has a different signature
|
||||
//! extern "C" fn my_interrupt_handler(_ctxt: interrupt::Tim7) {
|
||||
//! asm::bkpt();
|
||||
//! }
|
||||
//!
|
||||
//! extern "C" fn another_interrupt_handler(_ctxt: interrupt::Exti0) {
|
||||
//! asm::bkpt();
|
||||
//! }
|
||||
//!
|
||||
//! // Here we override only two interrupt handlers, the rest of interrupt are
|
||||
//! // handled by the same interrupt handler
|
||||
//! #[allow(dead_code)]
|
||||
//! #[used]
|
||||
//! #[link_section = ".rodata.interrupts"]
|
||||
//! static INTERRUPTS: interrupt::Handlers = interrupt::Handlers {
|
||||
//! Tim7: my_interrupt_handler,
|
||||
//! Exti0: another_interrupt_handler,
|
||||
//! ..interrupt::DEFAULT_HANDLERS
|
||||
//! };
|
||||
//! ```
|
||||
// Auto-generated. Do not modify.
|
||||
50
src/examples/_5_override_exception_handler.rs
Normal file
50
src/examples/_5_override_exception_handler.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
//! Overriding an exception
|
||||
//!
|
||||
//! **NOTE** You have to disable the `cortex-m-rt` crate's "exceptions" feature
|
||||
//! to make this work.
|
||||
//!
|
||||
//! ```
|
||||
//!
|
||||
//! #![feature(used)]
|
||||
//! #![no_std]
|
||||
//!
|
||||
//! extern crate cortex_m;
|
||||
//! extern crate cortex_m_rt;
|
||||
//!
|
||||
//! use core::ptr;
|
||||
//!
|
||||
//! use cortex_m::{asm, exception};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! unsafe {
|
||||
//! // Invalid memory access
|
||||
//! ptr::read_volatile(0x2FFF_FFFF as *const u32);
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! extern "C" fn hard_fault(_: exception::HardFault) {
|
||||
//! // You'll hit this breakpoint rather than the one in cortex-m-rt
|
||||
//! asm::bkpt()
|
||||
//! }
|
||||
//!
|
||||
//! // When the "exceptions" feature is disabled, you'll have to provide this symbol
|
||||
//! #[allow(dead_code)]
|
||||
//! #[used]
|
||||
//! #[link_section = ".rodata.exceptions"]
|
||||
//! static EXCEPTIONS: exception::Handlers = exception::Handlers {
|
||||
//! // This is the exception handler override
|
||||
//! hard_fault: hard_fault,
|
||||
//! ..exception::DEFAULT_HANDLERS
|
||||
//! };
|
||||
//!
|
||||
//! // As we are not using interrupts, we just register a dummy catch all handler
|
||||
//! #[allow(dead_code)]
|
||||
//! #[used]
|
||||
//! #[link_section = ".rodata.interrupts"]
|
||||
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
|
||||
//!
|
||||
//! extern "C" fn default_handler() {
|
||||
//! asm::bkpt();
|
||||
//! }
|
||||
//! ```
|
||||
// Auto-generated. Do not modify.
|
||||
8
src/examples/mod.rs
Normal file
8
src/examples/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
//! Examples
|
||||
// Auto-generated. Do not modify.
|
||||
pub mod _0_hello;
|
||||
pub mod _1_itm;
|
||||
pub mod _2_panic;
|
||||
pub mod _3_crash;
|
||||
pub mod _4_register_interrupt_handler;
|
||||
pub mod _5_override_exception_handler;
|
||||
95
src/lib.rs
Normal file
95
src/lib.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
//! A template for building applications for ARM Cortex-M microcontrollers
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! - Clone this crate
|
||||
//!
|
||||
//! ``` text
|
||||
//! $ cargo clone cortex-m-quickstart && cd $_
|
||||
//! ```
|
||||
//!
|
||||
//! - Change the crate name, author and version
|
||||
//!
|
||||
//! ``` text
|
||||
//! $ edit Cargo.toml && head $_
|
||||
//! [package]
|
||||
//! authors = ["Jorge Aparicio <jorge@japaric.io>"]
|
||||
//! name = "demo"
|
||||
//! version = "0.1.0"
|
||||
//! ```
|
||||
//!
|
||||
//! - Specify the memory layout of the target device
|
||||
//!
|
||||
//! ``` text
|
||||
//! $ edit memory.x && cat $_
|
||||
//! MEMORY
|
||||
//! {
|
||||
//! /* NOTE K = KiBi = 1024 bytes */
|
||||
//! FLASH : ORIGIN = 0x08000000, LENGTH = 256K
|
||||
//! RAM : ORIGIN = 0x20000000, LENGTH = 40K
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! - Optionally, set a default build target
|
||||
//!
|
||||
//! ``` text
|
||||
//! $ cat >>.cargo/config <<'EOF'
|
||||
//! [build]
|
||||
//! target = "thumbv7em-none-eabihf"
|
||||
//! EOF
|
||||
//! ```
|
||||
//!
|
||||
//! - Very likely, depend on a device or a BSP (Board Support Package) crate.
|
||||
//!
|
||||
//! ``` text
|
||||
//! # add a device crate, or
|
||||
//! $ cargo add stm32f30x
|
||||
//!
|
||||
//! # add a BSP crate
|
||||
//! $ cargo add f3
|
||||
//! ```
|
||||
//!
|
||||
//! - Write the application or start from one of the examples
|
||||
//!
|
||||
//! ``` text
|
||||
//! $ rm -r src/* && cp examples/hello.rs src/main.rs
|
||||
//! ```
|
||||
//!
|
||||
//! - Build the application
|
||||
//!
|
||||
//! ``` text
|
||||
//! # if not installed
|
||||
//! $ cargo install xargo
|
||||
//!
|
||||
//! # NOTE this command requires `arm-none-eabi-ld` to be in $PATH
|
||||
//! $ xargo build --release
|
||||
//!
|
||||
//! $ arm-none-eabi-readelf -A target/thumbv7em-none-eabihf/release/demo
|
||||
//! Attribute Section: aeabi
|
||||
//! File Attributes
|
||||
//! Tag_conformance: "2.09"
|
||||
//! Tag_CPU_arch: v7E-M
|
||||
//! Tag_CPU_arch_profile: Microcontroller
|
||||
//! Tag_THUMB_ISA_use: Thumb-2
|
||||
//! Tag_FP_arch: VFPv4-D16
|
||||
//! Tag_ABI_PCS_GOT_use: direct
|
||||
//! Tag_ABI_FP_denormal: Needed
|
||||
//! Tag_ABI_FP_exceptions: Needed
|
||||
//! Tag_ABI_FP_number_model: IEEE 754
|
||||
//! Tag_ABI_align_needed: 8-byte
|
||||
//! Tag_ABI_align_preserved: 8-byte, except leaf SP
|
||||
//! Tag_ABI_HardFP_use: SP only
|
||||
//! Tag_ABI_VFP_args: VFP registers
|
||||
//! Tag_ABI_optimization_goals: Aggressive Speed
|
||||
//! Tag_CPU_unaligned_access: v6
|
||||
//! Tag_FP_HP_extension: Allowed
|
||||
//! Tag_ABI_FP_16bit_format: IEEE 754
|
||||
//! ```
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Check the [examples module](./examples/index.html)
|
||||
|
||||
#![no_std]
|
||||
|
||||
pub mod examples;
|
||||
Reference in New Issue
Block a user