| 1 | //! Startup code and minimal runtime for Cortex-M microcontrollers |
| 2 | //! |
| 3 | //! This crate contains all the required parts to build a `no_std` application (binary crate) that |
| 4 | //! targets a Cortex-M microcontroller. |
| 5 | //! |
| 6 | //! # Features |
| 7 | //! |
| 8 | //! This crates takes care of: |
| 9 | //! |
| 10 | //! - The memory layout of the program. In particular, it populates the vector table so the device |
| 11 | //! can boot correctly, and properly dispatch exceptions and interrupts. |
| 12 | //! |
| 13 | //! - Initializing `static` variables before the program entry point. |
| 14 | //! |
| 15 | //! - Enabling the FPU before the program entry point if the target is `-eabihf`. |
| 16 | //! |
| 17 | //! This crate also provides the following attributes: |
| 18 | //! |
| 19 | //! - [`#[entry]`][attr-entry] to declare the entry point of the program |
| 20 | //! - [`#[exception]`][attr-exception] to override an exception handler. If not overridden all |
| 21 | //! exception handlers default to an infinite loop. |
| 22 | //! |
| 23 | //! This crate also implements a related attribute called `#[interrupt]`, which allows you |
| 24 | //! to define interrupt handlers. However, since which interrupts are available depends on the |
| 25 | //! microcontroller in use, this attribute should be re-exported and used from a peripheral |
| 26 | //! access crate (PAC). |
| 27 | //! |
| 28 | //! A [`#[pre_init]`][attr-pre_init] macro is also provided to run a function before RAM |
| 29 | //! initialisation, but its use is deprecated as it is not defined behaviour to execute Rust |
| 30 | //! code before initialisation. It is still possible to create a custom `pre_init` function |
| 31 | //! using assembly. |
| 32 | //! |
| 33 | //! The documentation for these attributes can be found in the [Attribute Macros](#attributes) |
| 34 | //! section. |
| 35 | //! |
| 36 | //! # Requirements |
| 37 | //! |
| 38 | //! ## `memory.x` |
| 39 | //! |
| 40 | //! This crate expects the user, or some other crate, to provide the memory layout of the target |
| 41 | //! device via a linker script named `memory.x`, described in this section. The `memory.x` file is |
| 42 | //! used during linking by the `link.x` script provided by this crate. If you are using a custom |
| 43 | //! linker script, you do not need a `memory.x` file. |
| 44 | //! |
| 45 | //! ### `MEMORY` |
| 46 | //! |
| 47 | //! The linker script must specify the memory available in the device as, at least, two `MEMORY` |
| 48 | //! regions: one named `FLASH` and one named `RAM`. The `.text` and `.rodata` sections of the |
| 49 | //! program will be placed in the `FLASH` region, whereas the `.bss` and `.data` sections, as well |
| 50 | //! as the heap, will be placed in the `RAM` region. |
| 51 | //! |
| 52 | //! ```text |
| 53 | //! /* Linker script for the STM32F103C8T6 */ |
| 54 | //! MEMORY |
| 55 | //! { |
| 56 | //! FLASH : ORIGIN = 0x08000000, LENGTH = 64K |
| 57 | //! RAM : ORIGIN = 0x20000000, LENGTH = 20K |
| 58 | //! } |
| 59 | //! ``` |
| 60 | //! |
| 61 | //! ### `_stack_start` / `_stack_end` |
| 62 | //! |
| 63 | //! The `_stack_start` optional symbol can be used to indicate where the call stack of the program |
| 64 | //! should be placed. If this symbol is not used then the stack will be placed at the *end* of the |
| 65 | //! `RAM` region -- the stack grows downwards towards smaller address. This is generally a sensible |
| 66 | //! default and most applications will not need to specify `_stack_start`. The same goes for |
| 67 | //! `_stack_end` which is automatically placed after the end of statically allocated RAM. |
| 68 | //! |
| 69 | //! **NOTE:** If you change `_stack_start`, make sure to also set `_stack_end` correctly to match |
| 70 | //! new stack area if you are using it, e.g for MSPLIM. The `_stack_end` is not used internally by |
| 71 | //! `cortex-m-rt` and is only for application use. |
| 72 | //! |
| 73 | //! For Cortex-M, the `_stack_start` must always be aligned to 8 bytes, which is enforced by |
| 74 | //! the linker script. If you override it, ensure that whatever value you set is a multiple |
| 75 | //! of 8 bytes. The `_stack_end` is aligned to 4 bytes. |
| 76 | //! |
| 77 | //! This symbol can be used to place the stack in a different memory region, for example: |
| 78 | //! |
| 79 | //! ```text |
| 80 | //! /* Linker script for the STM32F303VCT6 with stack in CCM */ |
| 81 | //! MEMORY |
| 82 | //! { |
| 83 | //! FLASH : ORIGIN = 0x08000000, LENGTH = 256K |
| 84 | //! |
| 85 | //! /* .bss, .data and the heap go in this region */ |
| 86 | //! RAM : ORIGIN = 0x20000000, LENGTH = 40K |
| 87 | //! |
| 88 | //! /* Core coupled (faster) RAM dedicated to hold the stack */ |
| 89 | //! CCRAM : ORIGIN = 0x10000000, LENGTH = 8K |
| 90 | //! } |
| 91 | //! |
| 92 | //! _stack_start = ORIGIN(CCRAM) + LENGTH(CCRAM); |
| 93 | //! _stack_end = ORIGIN(CCRAM); /* Optional, add if used by the application */ |
| 94 | //! ``` |
| 95 | //! |
| 96 | //! ### `_stext` |
| 97 | //! |
| 98 | //! This optional symbol can be used to control where the `.text` section is placed. If omitted the |
| 99 | //! `.text` section will be placed right after the vector table, which is placed at the beginning of |
| 100 | //! `FLASH`. Some devices store settings like Flash configuration right after the vector table; |
| 101 | //! for these devices one must place the `.text` section after this configuration section -- |
| 102 | //! `_stext` can be used for this purpose. |
| 103 | //! |
| 104 | //! ```text |
| 105 | //! MEMORY |
| 106 | //! { |
| 107 | //! /* .. */ |
| 108 | //! } |
| 109 | //! |
| 110 | //! /* The device stores Flash configuration in 0x400-0x40C so we place .text after that */ |
| 111 | //! _stext = ORIGIN(FLASH) + 0x40C |
| 112 | //! ``` |
| 113 | //! |
| 114 | //! # An example |
| 115 | //! |
| 116 | //! This section presents a minimal application built on top of `cortex-m-rt`. Apart from the |
| 117 | //! mandatory `memory.x` linker script describing the memory layout of the device, the hard fault |
| 118 | //! handler and the default exception handler must also be defined somewhere in the dependency |
| 119 | //! graph (see [`#[exception]`]). In this example we define them in the binary crate: |
| 120 | //! |
| 121 | //! ```no_run |
| 122 | //! #![no_main] |
| 123 | //! #![no_std] |
| 124 | //! |
| 125 | //! // Some panic handler needs to be included. This one halts the processor on panic. |
| 126 | //! use panic_halt as _; |
| 127 | //! |
| 128 | //! use cortex_m_rt::entry; |
| 129 | //! |
| 130 | //! // Use `main` as the entry point of this application, which may not return. |
| 131 | //! #[entry] |
| 132 | //! fn main() -> ! { |
| 133 | //! // initialization |
| 134 | //! |
| 135 | //! loop { |
| 136 | //! // application logic |
| 137 | //! } |
| 138 | //! } |
| 139 | //! ``` |
| 140 | //! |
| 141 | //! To actually build this program you need to place a `memory.x` linker script somewhere the linker |
| 142 | //! can find it, e.g. in the current directory; and then link the program using `cortex-m-rt`'s |
| 143 | //! linker script: `link.x`. The required steps are shown below: |
| 144 | //! |
| 145 | //! ```text |
| 146 | //! $ cat > memory.x <<EOF |
| 147 | //! MEMORY |
| 148 | //! { |
| 149 | //! FLASH : ORIGIN = 0x08000000, LENGTH = 64K |
| 150 | //! RAM : ORIGIN = 0x20000000, LENGTH = 20K |
| 151 | //! } |
| 152 | //! EOF |
| 153 | //! |
| 154 | //! $ cargo rustc --target thumbv7m-none-eabi -- -C link-arg=-nostartfiles -C link-arg=-Tlink.x |
| 155 | //! |
| 156 | //! $ file target/thumbv7m-none-eabi/debug/app |
| 157 | //! app: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, (..) |
| 158 | //! ``` |
| 159 | //! |
| 160 | //! # Optional features |
| 161 | //! |
| 162 | //! ## `device` |
| 163 | //! |
| 164 | //! If this feature is disabled then this crate populates the whole vector table. All the interrupts |
| 165 | //! in the vector table, even the ones unused by the target device, will be bound to the default |
| 166 | //! exception handler. This makes the final application device agnostic: you will be able to run it |
| 167 | //! on any Cortex-M device -- provided that you correctly specified its memory layout in `memory.x` |
| 168 | //! -- without hitting undefined behavior. |
| 169 | //! |
| 170 | //! If this feature is enabled then the interrupts section of the vector table is left unpopulated |
| 171 | //! and some other crate, or the user, will have to populate it. This mode is meant to be used in |
| 172 | //! conjunction with crates generated using `svd2rust`. Those peripheral access crates, or PACs, |
| 173 | //! will populate the missing part of the vector table when their `"rt"` feature is enabled. |
| 174 | //! |
| 175 | //! ## `set-sp` |
| 176 | //! |
| 177 | //! If this feature is enabled, the stack pointer (SP) is initialised in the reset handler to the |
| 178 | //! `_stack_start` value from the linker script. This is not usually required, but some debuggers |
| 179 | //! do not initialise SP when performing a soft reset, which can lead to stack corruption. |
| 180 | //! |
| 181 | //! ## `set-vtor` |
| 182 | //! |
| 183 | //! If this feature is enabled, the vector table offset register (VTOR) is initialised in the reset |
| 184 | //! handler to the start of the vector table defined in the linker script. This is not usually |
| 185 | //! required, but some bootloaders do not set VTOR before jumping to application code, leading to |
| 186 | //! your main function executing but interrupt handlers not being used. |
| 187 | //! |
| 188 | //! ## `zero-init-ram` |
| 189 | //! |
| 190 | //! If this feature is enabled, RAM is initialized with zeros during startup from the `_ram_start` |
| 191 | //! value to the `_ram_end` value from the linker script. This is not usually required, but might be |
| 192 | //! necessary to properly initialize memory integrity measures on some hardware. |
| 193 | //! |
| 194 | //! ## `paint-stack` |
| 195 | //! |
| 196 | //! Everywhere between `__sheap` and `_stack_start` is painted with the fixed value |
| 197 | //! `STACK_PAINT_VALUE`, which is `0xCCCC_CCCC`. |
| 198 | //! You can then inspect memory during debugging to determine how much of the stack has been used - |
| 199 | //! where the stack has been used the 'paint' will have been 'scrubbed off' and the memory will |
| 200 | //! have a value other than `STACK_PAINT_VALUE`. |
| 201 | //! |
| 202 | //! # Inspection |
| 203 | //! |
| 204 | //! This section covers how to inspect a binary that builds on top of `cortex-m-rt`. |
| 205 | //! |
| 206 | //! ## Sections (`size`) |
| 207 | //! |
| 208 | //! `cortex-m-rt` uses standard sections like `.text`, `.rodata`, `.bss` and `.data` as one would |
| 209 | //! expect. `cortex-m-rt` separates the vector table in its own section, named `.vector_table`. This |
| 210 | //! lets you distinguish how much space is taking the vector table in Flash vs how much is being |
| 211 | //! used by actual instructions (`.text`) and constants (`.rodata`). |
| 212 | //! |
| 213 | //! ```text |
| 214 | //! $ size -Ax target/thumbv7m-none-eabi/examples/app |
| 215 | //! target/thumbv7m-none-eabi/release/examples/app : |
| 216 | //! section size addr |
| 217 | //! .vector_table 0x400 0x8000000 |
| 218 | //! .text 0x88 0x8000400 |
| 219 | //! .rodata 0x0 0x8000488 |
| 220 | //! .data 0x0 0x20000000 |
| 221 | //! .bss 0x0 0x20000000 |
| 222 | //! ``` |
| 223 | //! |
| 224 | //! Without the `-A` argument `size` reports the sum of the sizes of `.text`, `.rodata` and |
| 225 | //! `.vector_table` under "text". |
| 226 | //! |
| 227 | //! ```text |
| 228 | //! $ size target/thumbv7m-none-eabi/examples/app |
| 229 | //! text data bss dec hex filename |
| 230 | //! 1160 0 0 1660 67c target/thumbv7m-none-eabi/release/app |
| 231 | //! ``` |
| 232 | //! |
| 233 | //! ## Symbols (`objdump`, `nm`) |
| 234 | //! |
| 235 | //! One will always find the following (unmangled) symbols in `cortex-m-rt` applications: |
| 236 | //! |
| 237 | //! - `Reset`. This is the reset handler. The microcontroller will execute this function upon |
| 238 | //! booting. This function will call the user program entry point (cf. [`#[entry]`][attr-entry]) |
| 239 | //! using the `main` symbol so you will also find that symbol in your program. |
| 240 | //! |
| 241 | //! - `DefaultHandler`. This is the default handler. If not overridden using `#[exception] fn |
| 242 | //! DefaultHandler(..` this will be an infinite loop. |
| 243 | //! |
| 244 | //! - `HardFault` and `_HardFault`. These function handle the hard fault handling and what they |
| 245 | //! do depends on whether the hard fault is overridden and whether the trampoline is enabled (which it is by default). |
| 246 | //! - No override: Both are the same function. The function is an infinite loop defined in the cortex-m-rt crate. |
| 247 | //! - Trampoline enabled: `HardFault` is the real hard fault handler defined in assembly. This function is simply a |
| 248 | //! trampoline that jumps into the rust defined `_HardFault` function. This second function jumps to the user-defined |
| 249 | //! handler with the exception frame as parameter. This second jump is usually optimised away with inlining. |
| 250 | //! - Trampoline disabled: `HardFault` is the user defined function. This means the user function is called directly |
| 251 | //! from the vector table. `_HardFault` still exists, but is an empty function that is purely there for compiler |
| 252 | //! diagnostics. |
| 253 | //! |
| 254 | //! - `__STACK_START`. This is the first entry in the `.vector_table` section. This symbol contains |
| 255 | //! the initial value of the stack pointer; this is where the stack will be located -- the stack |
| 256 | //! grows downwards towards smaller addresses. |
| 257 | //! |
| 258 | //! - `__RESET_VECTOR`. This is the reset vector, a pointer to the `Reset` function. This vector |
| 259 | //! is located in the `.vector_table` section after `__STACK_START`. |
| 260 | //! |
| 261 | //! - `__EXCEPTIONS`. This is the core exceptions portion of the vector table; it's an array of 14 |
| 262 | //! exception vectors, which includes exceptions like `HardFault` and `SysTick`. This array is |
| 263 | //! located after `__RESET_VECTOR` in the `.vector_table` section. |
| 264 | //! |
| 265 | //! - `__INTERRUPTS`. This is the device specific interrupt portion of the vector table; its exact |
| 266 | //! size depends on the target device but if the `"device"` feature has not been enabled it will |
| 267 | //! have a size of 32 vectors (on ARMv6-M), 240 vectors (on ARMv7-M) or 496 vectors (on ARMv8-M). |
| 268 | //! This array is located after `__EXCEPTIONS` in the `.vector_table` section. |
| 269 | //! |
| 270 | //! - `__pre_init`. This is a function to be run before RAM is initialized. It defaults to an empty |
| 271 | //! function. As this runs before RAM is initialised, it is not sound to use a Rust function for |
| 272 | //! `pre_init`, and instead it should typically be written in assembly using `global_asm` or an |
| 273 | //! external assembly file. |
| 274 | //! |
| 275 | //! If you override any exception handler you'll find it as an unmangled symbol, e.g. `SysTick` or |
| 276 | //! `SVCall`, in the output of `objdump`, |
| 277 | //! |
| 278 | //! # Advanced usage |
| 279 | //! |
| 280 | //! ## Custom linker script |
| 281 | //! |
| 282 | //! To use your own linker script, ensure it is placed in the linker search path (for example in |
| 283 | //! the crate root or in Cargo's `OUT_DIR`) and use it with `-C link-arg=-Tmy_script.ld` instead |
| 284 | //! of the normal `-C link-arg=-Tlink.x`. The provided `link.x` may be used as a starting point |
| 285 | //! for customisation. |
| 286 | //! |
| 287 | //! ## Setting the program entry point |
| 288 | //! |
| 289 | //! This section describes how [`#[entry]`][attr-entry] is implemented. This information is useful |
| 290 | //! to developers who want to provide an alternative to [`#[entry]`][attr-entry] that provides extra |
| 291 | //! guarantees. |
| 292 | //! |
| 293 | //! The `Reset` handler will call a symbol named `main` (unmangled) *after* initializing `.bss` and |
| 294 | //! `.data`, and enabling the FPU (if the target has an FPU). A function with the `entry` attribute |
| 295 | //! will be set to have the export name "`main`"; in addition, its mutable statics are turned into |
| 296 | //! safe mutable references (see [`#[entry]`][attr-entry] for details). |
| 297 | //! |
| 298 | //! The unmangled `main` symbol must have signature `extern "C" fn() -> !` or its invocation from |
| 299 | //! `Reset` will result in undefined behavior. |
| 300 | //! |
| 301 | //! ## Incorporating device specific interrupts |
| 302 | //! |
| 303 | //! This section covers how an external crate can insert device specific interrupt handlers into the |
| 304 | //! vector table. Most users don't need to concern themselves with these details, but if you are |
| 305 | //! interested in how PACs generated using `svd2rust` integrate with `cortex-m-rt` read on. |
| 306 | //! |
| 307 | //! The information in this section applies when the `"device"` feature has been enabled. |
| 308 | //! |
| 309 | //! ### `__INTERRUPTS` |
| 310 | //! |
| 311 | //! The external crate must provide the interrupts portion of the vector table via a `static` |
| 312 | //! variable named`__INTERRUPTS` (unmangled) that must be placed in the `.vector_table.interrupts` |
| 313 | //! section of its object file. |
| 314 | //! |
| 315 | //! This `static` variable will be placed at `ORIGIN(FLASH) + 0x40`. This address corresponds to the |
| 316 | //! spot where IRQ0 (IRQ number 0) is located. |
| 317 | //! |
| 318 | //! To conform to the Cortex-M ABI `__INTERRUPTS` must be an array of function pointers; some spots |
| 319 | //! in this array may need to be set to 0 if they are marked as *reserved* in the data sheet / |
| 320 | //! reference manual. We recommend using a `union` to set the reserved spots to `0`; `None` |
| 321 | //! (`Option<fn()>`) may also work but it's not guaranteed that the `None` variant will *always* be |
| 322 | //! represented by the value `0`. |
| 323 | //! |
| 324 | //! Let's illustrate with an artificial example where a device only has two interrupt: `Foo`, with |
| 325 | //! IRQ number = 2, and `Bar`, with IRQ number = 4. |
| 326 | //! |
| 327 | //! ```no_run |
| 328 | //! pub union Vector { |
| 329 | //! handler: unsafe extern "C" fn(), |
| 330 | //! reserved: usize, |
| 331 | //! } |
| 332 | //! |
| 333 | //! extern "C" { |
| 334 | //! fn Foo(); |
| 335 | //! fn Bar(); |
| 336 | //! } |
| 337 | //! |
| 338 | //! #[link_section = ".vector_table.interrupts" ] |
| 339 | //! #[no_mangle] |
| 340 | //! pub static __INTERRUPTS: [Vector; 5] = [ |
| 341 | //! // 0-1: Reserved |
| 342 | //! Vector { reserved: 0 }, |
| 343 | //! Vector { reserved: 0 }, |
| 344 | //! |
| 345 | //! // 2: Foo |
| 346 | //! Vector { handler: Foo }, |
| 347 | //! |
| 348 | //! // 3: Reserved |
| 349 | //! Vector { reserved: 0 }, |
| 350 | //! |
| 351 | //! // 4: Bar |
| 352 | //! Vector { handler: Bar }, |
| 353 | //! ]; |
| 354 | //! ``` |
| 355 | //! |
| 356 | //! ### `device.x` |
| 357 | //! |
| 358 | //! Linking in `__INTERRUPTS` creates a bunch of undefined references. If the user doesn't set a |
| 359 | //! handler for *all* the device specific interrupts then linking will fail with `"undefined |
| 360 | //! reference"` errors. |
| 361 | //! |
| 362 | //! We want to provide a default handler for all the interrupts while still letting the user |
| 363 | //! individually override each interrupt handler. In C projects, this is usually accomplished using |
| 364 | //! weak aliases declared in external assembly files. We use a similar solution via the `PROVIDE` |
| 365 | //! command in the linker script: when the `"device"` feature is enabled, `cortex-m-rt`'s linker |
| 366 | //! script (`link.x`) includes a linker script named `device.x`, which must be provided by |
| 367 | //! whichever crate provides `__INTERRUPTS`. |
| 368 | //! |
| 369 | //! For our running example the `device.x` linker script looks like this: |
| 370 | //! |
| 371 | //! ```text |
| 372 | //! /* device.x */ |
| 373 | //! PROVIDE(Foo = DefaultHandler); |
| 374 | //! PROVIDE(Bar = DefaultHandler); |
| 375 | //! ``` |
| 376 | //! |
| 377 | //! This weakly aliases both `Foo` and `Bar`. `DefaultHandler` is the default exception handler and |
| 378 | //! that the core exceptions use unless overridden. |
| 379 | //! |
| 380 | //! Because this linker script is provided by a dependency of the final application the dependency |
| 381 | //! must contain a build script that puts `device.x` somewhere the linker can find. An example of |
| 382 | //! such build script is shown below: |
| 383 | //! |
| 384 | //! ```ignore |
| 385 | //! use std::env; |
| 386 | //! use std::fs::File; |
| 387 | //! use std::io::Write; |
| 388 | //! use std::path::PathBuf; |
| 389 | //! |
| 390 | //! fn main() { |
| 391 | //! // Put the linker script somewhere the linker can find it |
| 392 | //! let out = &PathBuf::from(env::var_os("OUT_DIR" ).unwrap()); |
| 393 | //! File::create(out.join("device.x" )) |
| 394 | //! .unwrap() |
| 395 | //! .write_all(include_bytes!("device.x" )) |
| 396 | //! .unwrap(); |
| 397 | //! println!("cargo:rustc-link-search={}" , out.display()); |
| 398 | //! } |
| 399 | //! ``` |
| 400 | //! |
| 401 | //! ## Uninitialized static variables |
| 402 | //! |
| 403 | //! The `.uninit` linker section can be used to leave `static mut` variables uninitialized. One use |
| 404 | //! case of unitialized static variables is to avoid zeroing large statically allocated buffers (say |
| 405 | //! to be used as thread stacks) -- this can considerably reduce initialization time on devices that |
| 406 | //! operate at low frequencies. |
| 407 | //! |
| 408 | //! The only correct way to use this section is with [`MaybeUninit`] types. |
| 409 | //! |
| 410 | //! [`MaybeUninit`]: https://doc.rust-lang.org/core/mem/union.MaybeUninit.html |
| 411 | //! |
| 412 | //! ```no_run,edition2018 |
| 413 | //! # extern crate core; |
| 414 | //! use core::mem::MaybeUninit; |
| 415 | //! |
| 416 | //! const STACK_SIZE: usize = 8 * 1024; |
| 417 | //! const NTHREADS: usize = 4; |
| 418 | //! |
| 419 | //! #[link_section = ".uninit.STACKS" ] |
| 420 | //! static mut STACKS: MaybeUninit<[[u8; STACK_SIZE]; NTHREADS]> = MaybeUninit::uninit(); |
| 421 | //! ``` |
| 422 | //! |
| 423 | //! Be very careful with the `link_section` attribute because it's easy to misuse in ways that cause |
| 424 | //! undefined behavior. |
| 425 | //! |
| 426 | //! ## Extra Sections |
| 427 | //! |
| 428 | //! Some microcontrollers provide additional memory regions beyond RAM and FLASH. For example, |
| 429 | //! some STM32 devices provide "CCM" or core-coupled RAM that is only accessible from the core. In |
| 430 | //! order to place variables in these sections using [`link_section`] attributes from your code, |
| 431 | //! you need to modify `memory.x` to declare the additional sections: |
| 432 | //! |
| 433 | //! [`link_section`]: https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute |
| 434 | //! |
| 435 | //! ```text |
| 436 | //! MEMORY |
| 437 | //! { |
| 438 | //! FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K |
| 439 | //! RAM (rw) : ORIGIN = 0x20000000, LENGTH = 128K |
| 440 | //! CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K |
| 441 | //! } |
| 442 | //! |
| 443 | //! SECTIONS |
| 444 | //! { |
| 445 | //! .ccmram (NOLOAD) : ALIGN(4) |
| 446 | //! { |
| 447 | //! *(.ccmram .ccmram.*); |
| 448 | //! . = ALIGN(4); |
| 449 | //! } > CCMRAM |
| 450 | //! } |
| 451 | //! ``` |
| 452 | //! |
| 453 | //! You can then use something like this to place a variable into this specific section of memory: |
| 454 | //! |
| 455 | //! ```no_run,edition2018 |
| 456 | //! # extern crate core; |
| 457 | //! # use core::mem::MaybeUninit; |
| 458 | //! #[link_section=".ccmram.BUFFERS" ] |
| 459 | //! static mut BUF: MaybeUninit<[u8; 1024]> = MaybeUninit::uninit(); |
| 460 | //! ``` |
| 461 | //! |
| 462 | //! However, note that these sections are not initialised by cortex-m-rt, and so must be used |
| 463 | //! either with `MaybeUninit` types or you must otherwise arrange for them to be initialised |
| 464 | //! yourself, such as in `pre_init`. |
| 465 | //! |
| 466 | //! [attr-entry]: attr.entry.html |
| 467 | //! [attr-exception]: attr.exception.html |
| 468 | //! [attr-pre_init]: attr.pre_init.html |
| 469 | //! |
| 470 | //! # Minimum Supported Rust Version (MSRV) |
| 471 | //! |
| 472 | //! The MSRV of this release is Rust 1.61.0. |
| 473 | |
| 474 | // # Developer notes |
| 475 | // |
| 476 | // - `link_section` is used to place symbols in specific places of the final binary. The names used |
| 477 | // here will appear in the linker script (`link.x`) in conjunction with the `KEEP` command. |
| 478 | |
| 479 | #![deny (missing_docs)] |
| 480 | #![no_std ] |
| 481 | |
| 482 | extern crate cortex_m_rt_macros as macros; |
| 483 | |
| 484 | /// The 32-bit value the stack is painted with before the program runs. |
| 485 | // Note: keep this value in-sync with the start-up assembly code, as we can't |
| 486 | // use const values in `global_asm!` yet. |
| 487 | #[cfg (feature = "paint-stack" )] |
| 488 | pub const STACK_PAINT_VALUE: u32 = 0xcccc_cccc; |
| 489 | |
| 490 | #[cfg (cortex_m)] |
| 491 | use core::arch::global_asm; |
| 492 | use core::fmt; |
| 493 | |
| 494 | /// Parse cfg attributes inside a global_asm call. |
| 495 | #[cfg (cortex_m)] |
| 496 | macro_rules! cfg_global_asm { |
| 497 | {@inner, [$($x:tt)*], } => { |
| 498 | global_asm!{$($x)*} |
| 499 | }; |
| 500 | (@inner, [$($x:tt)*], #[cfg($meta:meta)] $asm:literal, $($rest:tt)*) => { |
| 501 | #[cfg($meta)] |
| 502 | cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*} |
| 503 | #[cfg(not($meta))] |
| 504 | cfg_global_asm!{@inner, [$($x)*], $($rest)*} |
| 505 | }; |
| 506 | {@inner, [$($x:tt)*], $asm:literal, $($rest:tt)*} => { |
| 507 | cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*} |
| 508 | }; |
| 509 | {$($asms:tt)*} => { |
| 510 | cfg_global_asm!{@inner, [], $($asms)*} |
| 511 | }; |
| 512 | } |
| 513 | |
| 514 | // This reset vector is the initial entry point after a system reset. |
| 515 | // Calls an optional user-provided __pre_init and then initialises RAM. |
| 516 | // If the target has an FPU, it is enabled. |
| 517 | // Finally jumps to the user main function. |
| 518 | #[cfg (cortex_m)] |
| 519 | cfg_global_asm! { |
| 520 | ".cfi_sections .debug_frame |
| 521 | .section .Reset, \"ax \" |
| 522 | .global Reset |
| 523 | .type Reset,%function |
| 524 | .thumb_func" , |
| 525 | ".cfi_startproc |
| 526 | Reset:" , |
| 527 | |
| 528 | // If enabled, initialise the SP. This is normally initialised by the CPU itself or by a |
| 529 | // bootloader, but some debuggers fail to set it when resetting the target, leading to |
| 530 | // stack corruptions. |
| 531 | #[cfg(feature = "set-sp" )] |
| 532 | "ldr r0, =_stack_start |
| 533 | msr msp, r0" , |
| 534 | |
| 535 | // If enabled, initialise VTOR to the start of the vector table. This is normally initialised |
| 536 | // by a bootloader when the non-reset value is required, but some bootloaders do not set it, |
| 537 | // leading to frustrating issues where everything seems to work but interrupts are never |
| 538 | // handled. The VTOR register is optional on ARMv6-M, but when not present is RAZ,WI and |
| 539 | // therefore safe to write to. |
| 540 | #[cfg(feature = "set-vtor" )] |
| 541 | "ldr r0, =0xe000ed08 |
| 542 | ldr r1, =__vector_table |
| 543 | str r1, [r0]" , |
| 544 | |
| 545 | // Run user pre-init code which must be executed immediately after startup, before the |
| 546 | // potentially time-consuming memory initialisation takes place. |
| 547 | // Example use cases include disabling default watchdogs or enabling RAM. |
| 548 | "bl __pre_init" , |
| 549 | |
| 550 | // If enabled, initialize RAM with zeros. This is not usually required, but might be necessary |
| 551 | // to properly initialize checksum-based memory integrity measures on safety-critical hardware. |
| 552 | #[cfg(feature = "zero-init-ram" )] |
| 553 | "ldr r0, =_ram_start |
| 554 | ldr r1, =_ram_end |
| 555 | movs r2, #0 |
| 556 | 0: |
| 557 | cmp r1, r0 |
| 558 | beq 1f |
| 559 | stm r0!, {{r2}} |
| 560 | b 0b |
| 561 | 1:" , |
| 562 | |
| 563 | // Initialise .bss memory. `__sbss` and `__ebss` come from the linker script. |
| 564 | #[cfg(not(feature = "zero-init-ram" ))] |
| 565 | "ldr r0, =__sbss |
| 566 | ldr r1, =__ebss |
| 567 | movs r2, #0 |
| 568 | 0: |
| 569 | cmp r1, r0 |
| 570 | beq 1f |
| 571 | stm r0!, {{r2}} |
| 572 | b 0b |
| 573 | 1:" , |
| 574 | |
| 575 | // If enabled, paint stack/heap RAM with 0xcccccccc. |
| 576 | // `__sheap` and `_stack_start` come from the linker script. |
| 577 | #[cfg(feature = "paint-stack" )] |
| 578 | "ldr r0, =__sheap |
| 579 | ldr r1, =_stack_start |
| 580 | ldr r2, =0xcccccccc // This must match STACK_PAINT_VALUE |
| 581 | 0: |
| 582 | cmp r1, r0 |
| 583 | beq 1f |
| 584 | stm r0!, {{r2}} |
| 585 | b 0b |
| 586 | 1:" , |
| 587 | |
| 588 | // Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the linker script. |
| 589 | "ldr r0, =__sdata |
| 590 | ldr r1, =__edata |
| 591 | ldr r2, =__sidata |
| 592 | 0: |
| 593 | cmp r1, r0 |
| 594 | beq 1f |
| 595 | ldm r2!, {{r3}} |
| 596 | stm r0!, {{r3}} |
| 597 | b 0b |
| 598 | 1:" , |
| 599 | |
| 600 | // Potentially enable an FPU. |
| 601 | // SCB.CPACR is 0xE000_ED88. |
| 602 | // We enable access to CP10 and CP11 from priviliged and unprivileged mode. |
| 603 | #[cfg(has_fpu)] |
| 604 | "ldr r0, =0xE000ED88 |
| 605 | ldr r1, =(0b1111 << 20) |
| 606 | ldr r2, [r0] |
| 607 | orr r2, r2, r1 |
| 608 | str r2, [r0] |
| 609 | dsb |
| 610 | isb" , |
| 611 | |
| 612 | // Jump to user main function. |
| 613 | // `bl` is used for the extended range, but the user main function should not return, |
| 614 | // so trap on any unexpected return. |
| 615 | "bl main |
| 616 | udf #0" , |
| 617 | |
| 618 | ".cfi_endproc |
| 619 | .size Reset, . - Reset" , |
| 620 | } |
| 621 | |
| 622 | /// Attribute to declare an interrupt (AKA device-specific exception) handler |
| 623 | /// |
| 624 | /// **NOTE**: This attribute is exposed by `cortex-m-rt` only when the `device` feature is enabled. |
| 625 | /// However, that export is not meant to be used directly -- using it will result in a compilation |
| 626 | /// error. You should instead use the PAC (usually generated using `svd2rust`) re-export of |
| 627 | /// that attribute. You need to use the re-export to have the compiler check that the interrupt |
| 628 | /// exists on the target device. |
| 629 | /// |
| 630 | /// # Syntax |
| 631 | /// |
| 632 | /// ``` ignore |
| 633 | /// extern crate device; |
| 634 | /// |
| 635 | /// // the attribute comes from the PAC not from cortex-m-rt |
| 636 | /// use device::interrupt; |
| 637 | /// |
| 638 | /// #[interrupt] |
| 639 | /// fn USART1() { |
| 640 | /// // .. |
| 641 | /// } |
| 642 | /// ``` |
| 643 | /// |
| 644 | /// where the name of the function must be one of the device interrupts. |
| 645 | /// |
| 646 | /// # Usage |
| 647 | /// |
| 648 | /// `#[interrupt] fn Name(..` overrides the default handler for the interrupt with the given `Name`. |
| 649 | /// These handlers must have signature `[unsafe] fn() [-> !]`. It's possible to add state to these |
| 650 | /// handlers by declaring `static mut` variables at the beginning of the body of the function. These |
| 651 | /// variables will be safe to access from the function body. |
| 652 | /// |
| 653 | /// If the interrupt handler has not been overridden it will be dispatched by the default exception |
| 654 | /// handler (`DefaultHandler`). |
| 655 | /// |
| 656 | /// # Properties |
| 657 | /// |
| 658 | /// Interrupts handlers can only be called by the hardware. Other parts of the program can't refer |
| 659 | /// to the interrupt handlers, much less invoke them as if they were functions. |
| 660 | /// |
| 661 | /// `static mut` variables declared within an interrupt handler are safe to access and can be used |
| 662 | /// to preserve state across invocations of the handler. The compiler can't prove this is safe so |
| 663 | /// the attribute will help by making a transformation to the source code: for this reason a |
| 664 | /// variable like `static mut FOO: u32` will become `let FOO: &mut u32;`. |
| 665 | /// |
| 666 | /// # Examples |
| 667 | /// |
| 668 | /// - Using state within an interrupt handler |
| 669 | /// |
| 670 | /// ``` ignore |
| 671 | /// extern crate device; |
| 672 | /// |
| 673 | /// use device::interrupt; |
| 674 | /// |
| 675 | /// #[interrupt] |
| 676 | /// fn TIM2() { |
| 677 | /// static mut COUNT: i32 = 0; |
| 678 | /// |
| 679 | /// // `COUNT` is safe to access and has type `&mut i32` |
| 680 | /// *COUNT += 1; |
| 681 | /// |
| 682 | /// println!("{}", COUNT); |
| 683 | /// } |
| 684 | /// ``` |
| 685 | #[cfg (feature = "device" )] |
| 686 | pub use macros::interrupt; |
| 687 | |
| 688 | /// Attribute to declare the entry point of the program |
| 689 | /// |
| 690 | /// The specified function will be called by the reset handler *after* RAM has been initialized. In |
| 691 | /// the case of the `thumbv7em-none-eabihf` target the FPU will also be enabled before the function |
| 692 | /// is called. |
| 693 | /// |
| 694 | /// The type of the specified function must be `[unsafe] fn() -> !` (never ending function) |
| 695 | /// |
| 696 | /// # Properties |
| 697 | /// |
| 698 | /// The entry point will be called by the reset handler. The program can't reference to the entry |
| 699 | /// point, much less invoke it. |
| 700 | /// |
| 701 | /// `static mut` variables declared within the entry point are safe to access. The compiler can't |
| 702 | /// prove this is safe so the attribute will help by making a transformation to the source code: for |
| 703 | /// this reason a variable like `static mut FOO: u32` will become `let FOO: &'static mut u32;`. Note |
| 704 | /// that `&'static mut` references have move semantics. |
| 705 | /// |
| 706 | /// # Examples |
| 707 | /// |
| 708 | /// - Simple entry point |
| 709 | /// |
| 710 | /// ``` no_run |
| 711 | /// # #![no_main] |
| 712 | /// # use cortex_m_rt::entry; |
| 713 | /// #[entry] |
| 714 | /// fn main() -> ! { |
| 715 | /// loop { |
| 716 | /// /* .. */ |
| 717 | /// } |
| 718 | /// } |
| 719 | /// ``` |
| 720 | /// |
| 721 | /// - `static mut` variables local to the entry point are safe to modify. |
| 722 | /// |
| 723 | /// ``` no_run |
| 724 | /// # #![no_main] |
| 725 | /// # use cortex_m_rt::entry; |
| 726 | /// #[entry] |
| 727 | /// fn main() -> ! { |
| 728 | /// static mut FOO: u32 = 0; |
| 729 | /// |
| 730 | /// let foo: &'static mut u32 = FOO; |
| 731 | /// assert_eq!(*foo, 0); |
| 732 | /// *foo = 1; |
| 733 | /// assert_eq!(*foo, 1); |
| 734 | /// |
| 735 | /// loop { |
| 736 | /// /* .. */ |
| 737 | /// } |
| 738 | /// } |
| 739 | /// ``` |
| 740 | pub use macros::entry; |
| 741 | |
| 742 | /// Attribute to declare an exception handler |
| 743 | /// |
| 744 | /// # Syntax |
| 745 | /// |
| 746 | /// ``` |
| 747 | /// # use cortex_m_rt::exception; |
| 748 | /// #[exception] |
| 749 | /// fn SysTick() { |
| 750 | /// // .. |
| 751 | /// } |
| 752 | /// |
| 753 | /// # fn main() {} |
| 754 | /// ``` |
| 755 | /// |
| 756 | /// where the name of the function must be one of: |
| 757 | /// |
| 758 | /// - `DefaultHandler` |
| 759 | /// - `NonMaskableInt` |
| 760 | /// - `HardFault` |
| 761 | /// - `MemoryManagement` (a) |
| 762 | /// - `BusFault` (a) |
| 763 | /// - `UsageFault` (a) |
| 764 | /// - `SecureFault` (b) |
| 765 | /// - `SVCall` |
| 766 | /// - `DebugMonitor` (a) |
| 767 | /// - `PendSV` |
| 768 | /// - `SysTick` |
| 769 | /// |
| 770 | /// (a) Not available on Cortex-M0 variants (`thumbv6m-none-eabi`) |
| 771 | /// |
| 772 | /// (b) Only available on ARMv8-M |
| 773 | /// |
| 774 | /// # Usage |
| 775 | /// |
| 776 | /// ## HardFault handler |
| 777 | /// |
| 778 | /// `#[exception(trampoline = true)] unsafe fn HardFault(..` sets the hard fault handler. |
| 779 | /// If the trampoline parameter is set to true, the handler must have signature `unsafe fn(&ExceptionFrame) -> !`. |
| 780 | /// If set to false, the handler must have signature `unsafe fn() -> !`. |
| 781 | /// |
| 782 | /// This handler is not allowed to return as that can cause undefined behavior. |
| 783 | /// |
| 784 | /// To maintain backwards compatibility the attribute can be used without trampoline parameter (`#[exception]`), |
| 785 | /// which sets the trampoline to true. |
| 786 | /// |
| 787 | /// ## Default handler |
| 788 | /// |
| 789 | /// `#[exception] unsafe fn DefaultHandler(..` sets the *default* handler. All exceptions which have |
| 790 | /// not been assigned a handler will be serviced by this handler. This handler must have signature |
| 791 | /// `unsafe fn(irqn: i16) [-> !]`. `irqn` is the IRQ number (See CMSIS); `irqn` will be a negative |
| 792 | /// number when the handler is servicing a core exception; `irqn` will be a positive number when the |
| 793 | /// handler is servicing a device specific exception (interrupt). |
| 794 | /// |
| 795 | /// ## Other handlers |
| 796 | /// |
| 797 | /// `#[exception] fn Name(..` overrides the default handler for the exception with the given `Name`. |
| 798 | /// These handlers must have signature `[unsafe] fn() [-> !]`. When overriding these other exception |
| 799 | /// it's possible to add state to them by declaring `static mut` variables at the beginning of the |
| 800 | /// body of the function. These variables will be safe to access from the function body. |
| 801 | /// |
| 802 | /// # Properties |
| 803 | /// |
| 804 | /// Exception handlers can only be called by the hardware. Other parts of the program can't refer to |
| 805 | /// the exception handlers, much less invoke them as if they were functions. |
| 806 | /// |
| 807 | /// `static mut` variables declared within an exception handler are safe to access and can be used |
| 808 | /// to preserve state across invocations of the handler. The compiler can't prove this is safe so |
| 809 | /// the attribute will help by making a transformation to the source code: for this reason a |
| 810 | /// variable like `static mut FOO: u32` will become `let FOO: &mut u32;`. |
| 811 | /// |
| 812 | /// # Safety |
| 813 | /// |
| 814 | /// It is not generally safe to register handlers for non-maskable interrupts. On Cortex-M, |
| 815 | /// `HardFault` is non-maskable (at least in general), and there is an explicitly non-maskable |
| 816 | /// interrupt `NonMaskableInt`. |
| 817 | /// |
| 818 | /// The reason for that is that non-maskable interrupts will preempt any currently running function, |
| 819 | /// even if that function executes within a critical section. Thus, if it was safe to define NMI |
| 820 | /// handlers, critical sections wouldn't work safely anymore. |
| 821 | /// |
| 822 | /// This also means that defining a `DefaultHandler` must be unsafe, as that will catch |
| 823 | /// `NonMaskableInt` and `HardFault` if no handlers for those are defined. |
| 824 | /// |
| 825 | /// The safety requirements on those handlers is as follows: The handler must not access any data |
| 826 | /// that is protected via a critical section and shared with other interrupts that may be preempted |
| 827 | /// by the NMI while holding the critical section. As long as this requirement is fulfilled, it is |
| 828 | /// safe to handle NMIs. |
| 829 | /// |
| 830 | /// # Examples |
| 831 | /// |
| 832 | /// - Setting the default handler |
| 833 | /// |
| 834 | /// ``` |
| 835 | /// use cortex_m_rt::exception; |
| 836 | /// |
| 837 | /// #[exception] |
| 838 | /// unsafe fn DefaultHandler(irqn: i16) { |
| 839 | /// println!("IRQn = {}", irqn); |
| 840 | /// } |
| 841 | /// |
| 842 | /// # fn main() {} |
| 843 | /// ``` |
| 844 | /// |
| 845 | /// - Overriding the `SysTick` handler |
| 846 | /// |
| 847 | /// ``` |
| 848 | /// use cortex_m_rt::exception; |
| 849 | /// |
| 850 | /// #[exception] |
| 851 | /// fn SysTick() { |
| 852 | /// static mut COUNT: i32 = 0; |
| 853 | /// |
| 854 | /// // `COUNT` is safe to access and has type `&mut i32` |
| 855 | /// *COUNT += 1; |
| 856 | /// |
| 857 | /// println!("{}", COUNT); |
| 858 | /// } |
| 859 | /// |
| 860 | /// # fn main() {} |
| 861 | /// ``` |
| 862 | pub use macros::exception; |
| 863 | |
| 864 | /// Attribute to mark which function will be called at the beginning of the reset handler. |
| 865 | /// |
| 866 | /// **IMPORTANT**: This attribute can appear at most *once* in the dependency graph. |
| 867 | /// |
| 868 | /// The function must have the signature of `unsafe fn()`. |
| 869 | /// |
| 870 | /// # Safety |
| 871 | /// |
| 872 | /// The function will be called before memory is initialized, as soon as possible after reset. Any |
| 873 | /// access of memory, including any static variables, will result in undefined behavior. |
| 874 | /// |
| 875 | /// **Warning**: Due to [rvalue static promotion][rfc1414] static variables may be accessed whenever |
| 876 | /// taking a reference to a constant. This means that even trivial expressions such as `&1` in the |
| 877 | /// `#[pre_init]` function *or any code called by it* will cause **immediate undefined behavior**. |
| 878 | /// |
| 879 | /// Users are advised to only use the `#[pre_init]` feature when absolutely necessary as these |
| 880 | /// constraints make safe usage difficult. |
| 881 | /// |
| 882 | /// # Examples |
| 883 | /// |
| 884 | /// ``` |
| 885 | /// # use cortex_m_rt::pre_init; |
| 886 | /// #[pre_init] |
| 887 | /// unsafe fn before_main() { |
| 888 | /// // do something here |
| 889 | /// } |
| 890 | /// |
| 891 | /// # fn main() {} |
| 892 | /// ``` |
| 893 | /// |
| 894 | /// [rfc1414]: https://github.com/rust-lang/rfcs/blob/master/text/1414-rvalue_static_promotion.md |
| 895 | pub use macros::pre_init; |
| 896 | |
| 897 | // We export this static with an informative name so that if an application attempts to link |
| 898 | // two copies of cortex-m-rt together, linking will fail. We also declare a links key in |
| 899 | // Cargo.toml which is the more modern way to solve the same problem, but we have to keep |
| 900 | // __ONCE__ around to prevent linking with versions before the links key was added. |
| 901 | #[export_name = "error: cortex-m-rt appears more than once in the dependency graph" ] |
| 902 | #[doc (hidden)] |
| 903 | pub static __ONCE__: () = (); |
| 904 | |
| 905 | /// Registers stacked (pushed onto the stack) during an exception. |
| 906 | #[derive (Clone, Copy)] |
| 907 | #[repr (C)] |
| 908 | #[allow (dead_code)] |
| 909 | pub struct ExceptionFrame { |
| 910 | r0: u32, |
| 911 | r1: u32, |
| 912 | r2: u32, |
| 913 | r3: u32, |
| 914 | r12: u32, |
| 915 | lr: u32, |
| 916 | pc: u32, |
| 917 | xpsr: u32, |
| 918 | } |
| 919 | |
| 920 | impl ExceptionFrame { |
| 921 | /// Returns the value of (general purpose) register 0. |
| 922 | #[inline (always)] |
| 923 | pub fn r0(&self) -> u32 { |
| 924 | self.r0 |
| 925 | } |
| 926 | |
| 927 | /// Returns the value of (general purpose) register 1. |
| 928 | #[inline (always)] |
| 929 | pub fn r1(&self) -> u32 { |
| 930 | self.r1 |
| 931 | } |
| 932 | |
| 933 | /// Returns the value of (general purpose) register 2. |
| 934 | #[inline (always)] |
| 935 | pub fn r2(&self) -> u32 { |
| 936 | self.r2 |
| 937 | } |
| 938 | |
| 939 | /// Returns the value of (general purpose) register 3. |
| 940 | #[inline (always)] |
| 941 | pub fn r3(&self) -> u32 { |
| 942 | self.r3 |
| 943 | } |
| 944 | |
| 945 | /// Returns the value of (general purpose) register 12. |
| 946 | #[inline (always)] |
| 947 | pub fn r12(&self) -> u32 { |
| 948 | self.r12 |
| 949 | } |
| 950 | |
| 951 | /// Returns the value of the Link Register. |
| 952 | #[inline (always)] |
| 953 | pub fn lr(&self) -> u32 { |
| 954 | self.lr |
| 955 | } |
| 956 | |
| 957 | /// Returns the value of the Program Counter. |
| 958 | #[inline (always)] |
| 959 | pub fn pc(&self) -> u32 { |
| 960 | self.pc |
| 961 | } |
| 962 | |
| 963 | /// Returns the value of the Program Status Register. |
| 964 | #[inline (always)] |
| 965 | pub fn xpsr(&self) -> u32 { |
| 966 | self.xpsr |
| 967 | } |
| 968 | |
| 969 | /// Sets the stacked value of (general purpose) register 0. |
| 970 | /// |
| 971 | /// # Safety |
| 972 | /// |
| 973 | /// This affects the `r0` register of the preempted code, which must not rely on it getting |
| 974 | /// restored to its previous value. |
| 975 | #[inline (always)] |
| 976 | pub unsafe fn set_r0(&mut self, value: u32) { |
| 977 | self.r0 = value; |
| 978 | } |
| 979 | |
| 980 | /// Sets the stacked value of (general purpose) register 1. |
| 981 | /// |
| 982 | /// # Safety |
| 983 | /// |
| 984 | /// This affects the `r1` register of the preempted code, which must not rely on it getting |
| 985 | /// restored to its previous value. |
| 986 | #[inline (always)] |
| 987 | pub unsafe fn set_r1(&mut self, value: u32) { |
| 988 | self.r1 = value; |
| 989 | } |
| 990 | |
| 991 | /// Sets the stacked value of (general purpose) register 2. |
| 992 | /// |
| 993 | /// # Safety |
| 994 | /// |
| 995 | /// This affects the `r2` register of the preempted code, which must not rely on it getting |
| 996 | /// restored to its previous value. |
| 997 | #[inline (always)] |
| 998 | pub unsafe fn set_r2(&mut self, value: u32) { |
| 999 | self.r2 = value; |
| 1000 | } |
| 1001 | |
| 1002 | /// Sets the stacked value of (general purpose) register 3. |
| 1003 | /// |
| 1004 | /// # Safety |
| 1005 | /// |
| 1006 | /// This affects the `r3` register of the preempted code, which must not rely on it getting |
| 1007 | /// restored to its previous value. |
| 1008 | #[inline (always)] |
| 1009 | pub unsafe fn set_r3(&mut self, value: u32) { |
| 1010 | self.r3 = value; |
| 1011 | } |
| 1012 | |
| 1013 | /// Sets the stacked value of (general purpose) register 12. |
| 1014 | /// |
| 1015 | /// # Safety |
| 1016 | /// |
| 1017 | /// This affects the `r12` register of the preempted code, which must not rely on it getting |
| 1018 | /// restored to its previous value. |
| 1019 | #[inline (always)] |
| 1020 | pub unsafe fn set_r12(&mut self, value: u32) { |
| 1021 | self.r12 = value; |
| 1022 | } |
| 1023 | |
| 1024 | /// Sets the stacked value of the Link Register. |
| 1025 | /// |
| 1026 | /// # Safety |
| 1027 | /// |
| 1028 | /// This affects the `lr` register of the preempted code, which must not rely on it getting |
| 1029 | /// restored to its previous value. |
| 1030 | #[inline (always)] |
| 1031 | pub unsafe fn set_lr(&mut self, value: u32) { |
| 1032 | self.lr = value; |
| 1033 | } |
| 1034 | |
| 1035 | /// Sets the stacked value of the Program Counter. |
| 1036 | /// |
| 1037 | /// # Safety |
| 1038 | /// |
| 1039 | /// This affects the `pc` register of the preempted code, which must not rely on it getting |
| 1040 | /// restored to its previous value. |
| 1041 | #[inline (always)] |
| 1042 | pub unsafe fn set_pc(&mut self, value: u32) { |
| 1043 | self.pc = value; |
| 1044 | } |
| 1045 | |
| 1046 | /// Sets the stacked value of the Program Status Register. |
| 1047 | /// |
| 1048 | /// # Safety |
| 1049 | /// |
| 1050 | /// This affects the `xPSR` registers (`IPSR`, `APSR`, and `EPSR`) of the preempted code, which |
| 1051 | /// must not rely on them getting restored to their previous value. |
| 1052 | #[inline (always)] |
| 1053 | pub unsafe fn set_xpsr(&mut self, value: u32) { |
| 1054 | self.xpsr = value; |
| 1055 | } |
| 1056 | } |
| 1057 | |
| 1058 | impl fmt::Debug for ExceptionFrame { |
| 1059 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 1060 | struct Hex(u32); |
| 1061 | impl fmt::Debug for Hex { |
| 1062 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 1063 | write!(f, "0x {:08x}" , self.0) |
| 1064 | } |
| 1065 | } |
| 1066 | f&mut DebugStruct<'_, '_>.debug_struct("ExceptionFrame" ) |
| 1067 | .field("r0" , &Hex(self.r0)) |
| 1068 | .field("r1" , &Hex(self.r1)) |
| 1069 | .field("r2" , &Hex(self.r2)) |
| 1070 | .field("r3" , &Hex(self.r3)) |
| 1071 | .field("r12" , &Hex(self.r12)) |
| 1072 | .field("lr" , &Hex(self.lr)) |
| 1073 | .field("pc" , &Hex(self.pc)) |
| 1074 | .field(name:"xpsr" , &Hex(self.xpsr)) |
| 1075 | .finish() |
| 1076 | } |
| 1077 | } |
| 1078 | |
| 1079 | /// Returns a pointer to the start of the heap |
| 1080 | /// |
| 1081 | /// The returned pointer is guaranteed to be 4-byte aligned. |
| 1082 | #[inline ] |
| 1083 | pub fn heap_start() -> *mut u32 { |
| 1084 | unsafeextern "C" { |
| 1085 | unsafestatic mut __sheap: u32; |
| 1086 | } |
| 1087 | |
| 1088 | #[allow (unused_unsafe)] // no longer unsafe since rust 1.82.0 |
| 1089 | unsafe { |
| 1090 | core::ptr::addr_of_mut!(__sheap) |
| 1091 | } |
| 1092 | } |
| 1093 | |
| 1094 | // Entry point is Reset. |
| 1095 | #[doc (hidden)] |
| 1096 | #[cfg_attr (cortex_m, link_section = ".vector_table.reset_vector" )] |
| 1097 | #[no_mangle ] |
| 1098 | pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; |
| 1099 | |
| 1100 | #[doc (hidden)] |
| 1101 | #[cfg_attr (cortex_m, link_section = ".HardFault.default" )] |
| 1102 | #[no_mangle ] |
| 1103 | pub unsafe extern "C" fn HardFault_() -> ! { |
| 1104 | #[allow (clippy::empty_loop)] |
| 1105 | loop {} |
| 1106 | } |
| 1107 | |
| 1108 | #[doc (hidden)] |
| 1109 | #[no_mangle ] |
| 1110 | pub unsafe extern "C" fn DefaultHandler_() -> ! { |
| 1111 | #[allow (clippy::empty_loop)] |
| 1112 | loop {} |
| 1113 | } |
| 1114 | |
| 1115 | #[doc (hidden)] |
| 1116 | #[no_mangle ] |
| 1117 | pub unsafe extern "C" fn DefaultPreInit() {} |
| 1118 | |
| 1119 | /* Exceptions */ |
| 1120 | #[doc (hidden)] |
| 1121 | pub enum Exception { |
| 1122 | NonMaskableInt, |
| 1123 | |
| 1124 | // Not overridable |
| 1125 | // HardFault, |
| 1126 | #[cfg (not(armv6m))] |
| 1127 | MemoryManagement, |
| 1128 | |
| 1129 | #[cfg (not(armv6m))] |
| 1130 | BusFault, |
| 1131 | |
| 1132 | #[cfg (not(armv6m))] |
| 1133 | UsageFault, |
| 1134 | |
| 1135 | #[cfg (armv8m)] |
| 1136 | SecureFault, |
| 1137 | |
| 1138 | SVCall, |
| 1139 | |
| 1140 | #[cfg (not(armv6m))] |
| 1141 | DebugMonitor, |
| 1142 | |
| 1143 | PendSV, |
| 1144 | |
| 1145 | SysTick, |
| 1146 | } |
| 1147 | |
| 1148 | #[doc (hidden)] |
| 1149 | pub use self::Exception as exception; |
| 1150 | |
| 1151 | unsafeextern "C" { |
| 1152 | unsafefn Reset() -> !; |
| 1153 | |
| 1154 | unsafefn NonMaskableInt(); |
| 1155 | |
| 1156 | unsafefn HardFault(); |
| 1157 | |
| 1158 | #[cfg (not(armv6m))] |
| 1159 | unsafefn MemoryManagement(); |
| 1160 | |
| 1161 | #[cfg (not(armv6m))] |
| 1162 | unsafefn BusFault(); |
| 1163 | |
| 1164 | #[cfg (not(armv6m))] |
| 1165 | unsafefn UsageFault(); |
| 1166 | |
| 1167 | #[cfg (armv8m)] |
| 1168 | fn SecureFault(); |
| 1169 | |
| 1170 | unsafefn SVCall(); |
| 1171 | |
| 1172 | #[cfg (not(armv6m))] |
| 1173 | unsafefn DebugMonitor(); |
| 1174 | |
| 1175 | unsafefn PendSV(); |
| 1176 | |
| 1177 | unsafefn SysTick(); |
| 1178 | } |
| 1179 | |
| 1180 | #[doc (hidden)] |
| 1181 | #[repr (C)] |
| 1182 | pub union Vector { |
| 1183 | handler: unsafe extern "C" fn(), |
| 1184 | reserved: usize, |
| 1185 | } |
| 1186 | |
| 1187 | #[doc (hidden)] |
| 1188 | #[cfg_attr (cortex_m, link_section = ".vector_table.exceptions" )] |
| 1189 | #[no_mangle ] |
| 1190 | pub static __EXCEPTIONS: [Vector; 14] = [ |
| 1191 | // Exception 2: Non Maskable Interrupt. |
| 1192 | Vector { |
| 1193 | handler: NonMaskableInt, |
| 1194 | }, |
| 1195 | // Exception 3: Hard Fault Interrupt. |
| 1196 | Vector { handler: HardFault }, |
| 1197 | // Exception 4: Memory Management Interrupt [not on Cortex-M0 variants]. |
| 1198 | #[cfg (not(armv6m))] |
| 1199 | Vector { |
| 1200 | handler: MemoryManagement, |
| 1201 | }, |
| 1202 | #[cfg (armv6m)] |
| 1203 | Vector { reserved: 0 }, |
| 1204 | // Exception 5: Bus Fault Interrupt [not on Cortex-M0 variants]. |
| 1205 | #[cfg (not(armv6m))] |
| 1206 | Vector { handler: BusFault }, |
| 1207 | #[cfg (armv6m)] |
| 1208 | Vector { reserved: 0 }, |
| 1209 | // Exception 6: Usage Fault Interrupt [not on Cortex-M0 variants]. |
| 1210 | #[cfg (not(armv6m))] |
| 1211 | Vector { |
| 1212 | handler: UsageFault, |
| 1213 | }, |
| 1214 | #[cfg (armv6m)] |
| 1215 | Vector { reserved: 0 }, |
| 1216 | // Exception 7: Secure Fault Interrupt [only on Armv8-M]. |
| 1217 | #[cfg (armv8m)] |
| 1218 | Vector { |
| 1219 | handler: SecureFault, |
| 1220 | }, |
| 1221 | #[cfg (not(armv8m))] |
| 1222 | Vector { reserved: 0 }, |
| 1223 | // 8-10: Reserved |
| 1224 | Vector { reserved: 0 }, |
| 1225 | Vector { reserved: 0 }, |
| 1226 | Vector { reserved: 0 }, |
| 1227 | // Exception 11: SV Call Interrupt. |
| 1228 | Vector { handler: SVCall }, |
| 1229 | // Exception 12: Debug Monitor Interrupt [not on Cortex-M0 variants]. |
| 1230 | #[cfg (not(armv6m))] |
| 1231 | Vector { |
| 1232 | handler: DebugMonitor, |
| 1233 | }, |
| 1234 | #[cfg (armv6m)] |
| 1235 | Vector { reserved: 0 }, |
| 1236 | // 13: Reserved |
| 1237 | Vector { reserved: 0 }, |
| 1238 | // Exception 14: Pend SV Interrupt [not on Cortex-M0 variants]. |
| 1239 | Vector { handler: PendSV }, |
| 1240 | // Exception 15: System Tick Interrupt. |
| 1241 | Vector { handler: SysTick }, |
| 1242 | ]; |
| 1243 | |
| 1244 | // If we are not targeting a specific device we bind all the potential device specific interrupts |
| 1245 | // to the default handler |
| 1246 | #[cfg (all(any(not(feature = "device" ), test), not(armv6m), not(armv8m)))] |
| 1247 | #[doc (hidden)] |
| 1248 | #[cfg_attr (cortex_m, link_section = ".vector_table.interrupts" )] |
| 1249 | #[no_mangle ] |
| 1250 | pub static __INTERRUPTS: [unsafe extern "C" fn(); 240] = [{ |
| 1251 | extern "C" { |
| 1252 | fn DefaultHandler(); |
| 1253 | } |
| 1254 | |
| 1255 | DefaultHandler |
| 1256 | }; 240]; |
| 1257 | |
| 1258 | // ARMv8-M can have up to 496 device specific interrupts |
| 1259 | #[cfg (all(not(feature = "device" ), armv8m))] |
| 1260 | #[doc (hidden)] |
| 1261 | #[cfg_attr (cortex_m, link_section = ".vector_table.interrupts" )] |
| 1262 | #[no_mangle ] |
| 1263 | pub static __INTERRUPTS: [unsafe extern "C" fn(); 496] = [{ |
| 1264 | extern "C" { |
| 1265 | fn DefaultHandler(); |
| 1266 | } |
| 1267 | |
| 1268 | DefaultHandler |
| 1269 | }; 496]; |
| 1270 | |
| 1271 | // ARMv6-M can only have a maximum of 32 device specific interrupts |
| 1272 | #[cfg (all(not(feature = "device" ), armv6m))] |
| 1273 | #[doc (hidden)] |
| 1274 | #[link_section = ".vector_table.interrupts" ] |
| 1275 | #[no_mangle ] |
| 1276 | pub static __INTERRUPTS: [unsafe extern "C" fn(); 32] = [{ |
| 1277 | extern "C" { |
| 1278 | fn DefaultHandler(); |
| 1279 | } |
| 1280 | |
| 1281 | DefaultHandler |
| 1282 | }; 32]; |
| 1283 | |