Crate cortex_m_rt [] [src]

Minimal startup / runtime for Cortex-M microcontrollers

Features

This crate provides

  • Before main initialization of the .bss and .data sections

  • An 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 vanilla fn main(). NOTE the processor goes into "reactive" mode (loop { asm!("wfi") }) after returning from main.

  • 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 definition of the FLASH and RAM memory regions of the device. This missing information must be supplied through a memory.x linker script of the form:

MEMORY
{
  FLASH : ORIGIN = 0x08000000, LENGTH = 128K
  RAM : ORIGIN = 0x20000000, LENGTH = 8K
}
  • 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
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

$ cat Xargo.toml
[dependencies.core]

[dependencies.compiler_builtins]
features = ["mem"]
git = "https://github.com/rust-lang-nursery/compiler-builtins"
stage = 1
$ cat memory.x
MEMORY
{
  FLASH : ORIGIN = 0x08000000, LENGTH = 128K
  RAM : ORIGIN = 0x20000000, LENGTH = 8K
}
$ cat src/main.rs
#![feature(used)]
#![no_std]

#[macro_use]
extern crate cortex_m;
extern crate cortex_m_rt;

fn main() {
    hprintln!("Hello, world!");
}

#[allow(dead_code)]
#[link_section = ".rodata.interrupts"]
#[used]
static INTERRUPTS: [u32; 240] = [0; 240];
$ xargo rustc --target thumbv7m-none-eabi -- -C link-args='-Tlink.x -nostartfiles'

$ arm-none-eabi-objdump -Cd $(find target -name app) | less
08000000 <_VECTOR_TABLE>:
 8000000:       20002000        .word   0x20002000

08000004 <cortex_m_rt::RESET_HANDLER>:
 8000004:       08000671                                q...

08000008 <cortex_m_rt::EXCEPTIONS>:
 8000008:       080005a5 080005bd 08000569 08000599     ........i.......
 8000018:       08000581 00000000 00000000 00000000     ................
 8000028:       00000000 080005b1 00000000 00000000     ................
 8000038:       0800058d 08000575                       ....u...