cortex_m_rt/
lib.rs

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
482extern 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")]
488pub const STACK_PAINT_VALUE: u32 = 0xcccc_cccc;
489
490#[cfg(cortex_m)]
491use core::arch::global_asm;
492use core::fmt;
493
494/// Parse cfg attributes inside a global_asm call.
495#[cfg(cortex_m)]
496macro_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)]
519cfg_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")]
686pub 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/// ```
740pub 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/// ```
862pub 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
895pub 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)]
903pub static __ONCE__: () = ();
904
905/// Registers stacked (pushed onto the stack) during an exception.
906#[derive(Clone, Copy)]
907#[repr(C)]
908#[allow(dead_code)]
909pub 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
920impl 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
1058impl 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.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("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]
1083pub fn heap_start() -> *mut u32 {
1084    extern "C" {
1085        static 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]
1098pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset;
1099
1100#[doc(hidden)]
1101#[cfg_attr(cortex_m, link_section = ".HardFault.default")]
1102#[no_mangle]
1103pub unsafe extern "C" fn HardFault_() -> ! {
1104    #[allow(clippy::empty_loop)]
1105    loop {}
1106}
1107
1108#[doc(hidden)]
1109#[no_mangle]
1110pub unsafe extern "C" fn DefaultHandler_() -> ! {
1111    #[allow(clippy::empty_loop)]
1112    loop {}
1113}
1114
1115#[doc(hidden)]
1116#[no_mangle]
1117pub unsafe extern "C" fn DefaultPreInit() {}
1118
1119/* Exceptions */
1120#[doc(hidden)]
1121pub 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)]
1149pub use self::Exception as exception;
1150
1151extern "C" {
1152    fn Reset() -> !;
1153
1154    fn NonMaskableInt();
1155
1156    fn HardFault();
1157
1158    #[cfg(not(armv6m))]
1159    fn MemoryManagement();
1160
1161    #[cfg(not(armv6m))]
1162    fn BusFault();
1163
1164    #[cfg(not(armv6m))]
1165    fn UsageFault();
1166
1167    #[cfg(armv8m)]
1168    fn SecureFault();
1169
1170    fn SVCall();
1171
1172    #[cfg(not(armv6m))]
1173    fn DebugMonitor();
1174
1175    fn PendSV();
1176
1177    fn SysTick();
1178}
1179
1180#[doc(hidden)]
1181#[repr(C)]
1182pub 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]
1190pub 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]
1250pub 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]
1263pub 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]
1276pub static __INTERRUPTS: [unsafe extern "C" fn(); 32] = [{
1277    extern "C" {
1278        fn DefaultHandler();
1279    }
1280
1281    DefaultHandler
1282}; 32];