Crate cortex_m_rt [−] [src]
Minimal startup / runtime for Cortex-M microcontrollers
Features
This crate provides
Before main initialization of the
.bss
and.data
sectionsAn overridable (*)
panic_fmt
implementation that prints to the ITM or to the host stdout (through semihosting) depending on which Cargo feature has been enabled:"panic-over-itm"
or"panic-over-semihosting"
.A minimal
start
lang item, to support vanillafn main()
. NOTE the processor goes into "reactive" mode (loop { asm!("wfi") }
) after returning frommain
.An opt-in linker script (
"linker-script"
Cargo feature) that encodes the memory layout of a generic Cortex-M microcontroller. This linker script is missing the definitions of the FLASH and RAM memory regions of the device and of the_stack_start
symbol (address where the call stack is allocated). This missing information must be supplied through amemory.x
file (see example below).A default exception handler tailored for debugging and that provides access to the stacked registers under the debugger. By default, all exceptions (**) are serviced by this handler but this can be overridden on a per exception basis by opting out of the "exceptions" Cargo feature and then defining the following
struct
A
_sheap
symbol at whose address you can locate the heap.
use cortex_m::exception; #[link_section = ".rodata.exceptions"] #[used] static EXCEPTIONS: exception::Handlers = exception::Handlers { hard_fault: my_override, nmi: another_handler, ..exception::DEFAULT_HANDLERS };
(*) To override the panic_fmt
implementation, simply create a new
rust_begin_unwind
symbol:
#[no_mangle] pub unsafe extern "C" fn rust_begin_unwind( _args: ::core::fmt::Arguments, _file: &'static str, _line: u32, ) -> ! { .. }
(**) All the device specific exceptions, i.e. the interrupts, are left unpopulated. You must fill that part of the vector table by defining the following static (with the right memory layout):
#[link_section = ".rodata.interrupts"] #[used] static INTERRUPTS: SomeStruct = SomeStruct { .. }
Example
$ cargo new --bin app && cd $_
$ cargo add cortex-m cortex-m-rt
$ edit Xargo.toml && cat $_
[dependencies.core]
[dependencies.compiler_builtins]
features = ["mem"]
git = "https://github.com/rust-lang-nursery/compiler-builtins"
stage = 1
$ edit memory.x && cat $_
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
FLASH : ORIGIN = 0x08000000, LENGTH = 128K
RAM : ORIGIN = 0x20000000, LENGTH = 8K
}
/* This is where the call stack will be allocated */
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
$ edit src/main.rs && cat $_
#![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)] #[link_section = ".rodata.interrupts"] #[used] static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; extern "C" fn default_handler() { asm::bkpt(); }
$ cargo install xargo
$ xargo rustc --target thumbv7m-none-eabi -- \
-C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld
$ arm-none-eabi-objdump -Cd $(find target -name app) | head
Disassembly of section .text:
08000400 <cortex_m_rt::reset_handler>:
8000400: b580 push {r7, lr}
8000402: 466f mov r7, sp
8000404: b084 sub sp, #16