1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
//! 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: //! //! ``` text //! 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` //! //! ``` ignore,no_run //! 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): //! //! ``` ignore,no_run //! #[link_section = ".rodata.interrupts"] //! #[used] //! static INTERRUPTS: SomeStruct = SomeStruct { .. } //! ``` //! //! # Example //! //! ``` text //! $ cargo new --bin app && cd $_ //! //! $ cargo add cortex-m cortex-m-rt //! //! $ cat Xargo.toml //! ``` //! //! ``` text //! [dependencies.core] //! //! [dependencies.compiler_builtins] //! features = ["mem"] //! git = "https://github.com/rust-lang-nursery/compiler-builtins" //! stage = 1 //! ``` //! //! ``` text //! $ cat memory.x //! ``` //! //! ``` text //! MEMORY //! { //! FLASH : ORIGIN = 0x08000000, LENGTH = 128K //! RAM : ORIGIN = 0x20000000, LENGTH = 8K //! } //! ``` //! //! ``` text //! $ cat src/main.rs //! ``` //! //! ``` ignore,no_run //! #![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]; //! ``` //! //! ``` text //! $ 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... //! ``` #![deny(missing_docs)] #![deny(warnings)] #![feature(asm)] #![feature(compiler_builtins_lib)] #![feature(lang_items)] #![feature(linkage)] #![feature(used)] #![no_std] #[cfg(any(feature = "panic-over-itm", feature = "exceptions"))] #[cfg_attr(feature = "panic-over-itm", macro_use)] extern crate cortex_m; extern crate compiler_builtins; #[cfg(feature = "panic-over-semihosting")] #[macro_use] extern crate cortex_m_semihosting; extern crate r0; mod lang_items; #[cfg(feature = "exceptions")] use cortex_m::exception; /// The reset handler /// /// This is the entry point of all programs unsafe extern "C" fn reset_handler() -> ! { extern "C" { static mut _ebss: u32; static mut _sbss: u32; static mut _edata: u32; static mut _sdata: u32; static _sidata: u32; } ::r0::zero_bss(&mut _sbss, &mut _ebss); ::r0::init_data(&mut _sdata, &mut _edata, &_sidata); // NOTE `rustc` forces this signature on us. See `src/lang_items.rs` extern "C" { fn main(argc: isize, argv: *const *const u8) -> isize; } // Neither `argc` or `argv` make sense in bare metal contexts so we just // stub them main(0, ::core::ptr::null()); // If `main` returns, then we go into "reactive" mode and attend interrupts // as they occur. loop { #[cfg(target_arch = "arm")] asm!("wfi" :::: "volatile"); } } #[allow(dead_code)] #[used] #[link_section = ".rodata.reset_handler"] static RESET_HANDLER: unsafe extern "C" fn() -> ! = reset_handler; #[allow(dead_code)] #[cfg(feature = "exceptions")] #[link_section = ".rodata.exceptions"] #[used] static EXCEPTIONS: exception::Handlers = exception::Handlers { ..exception::DEFAULT_HANDLERS };