1212//!
1313//! - Initializing `static` variables before the program entry point.
1414//!
15- //! - Enabling the FPU before the program entry point if the target is `thumbv7em-none -eabihf`.
15+ //! - Enabling the FPU before the program entry point if the target is `-eabihf`.
1616//!
1717//! This crate also provides the following attributes:
1818//!
1919//! - [`#[entry]`][attr-entry] to declare the entry point of the program
2020//! - [`#[exception]`][attr-exception] to override an exception handler. If not overridden all
2121//! exception handlers default to an infinite loop.
22- //! - [`#[pre_init]`][attr-pre_init] to run code *before* `static` variables are initialized
2322//!
2423//! This crate also implements a related attribute called `#[interrupt]`, which allows you
2524//! to define interrupt handlers. However, since which interrupts are available depends on the
26- //! microcontroller in use, this attribute should be re-exported and used from a device crate.
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.
2732//!
2833//! The documentation for these attributes can be found in the [Attribute Macros](#attributes)
2934//! section.
3338//! ## `memory.x`
3439//!
3540//! This crate expects the user, or some other crate, to provide the memory layout of the target
36- //! device via a linker script named `memory.x`. This section covers the contents of `memory.x`
37- //! The `memory.x` file is used during linking by the `link.x` script provided by this crate.
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.
3844//!
3945//! ### `MEMORY`
4046//!
4854//! MEMORY
4955//! {
5056//! FLASH : ORIGIN = 0x08000000, LENGTH = 64K
51- //! RAM : ORIGIN = 0x20000000, LENGTH = 20K
57+ //! RAM : ORIGIN = 0x20000000, LENGTH = 20K
5258//! }
5359//! ```
5460//!
5561//! ### `_stack_start`
5662//!
5763//! This optional symbol can be used to indicate where the call stack of the program should be
5864//! placed. If this symbol is not used then the stack will be placed at the *end* of the `RAM`
59- //! region -- the stack grows downwards towards smaller address.
65+ //! 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`.
6067//!
6168//! For Cortex-M, the `_stack_start` must always be aligned to 8 bytes, which is enforced by
6269//! the linker script. If you override it, ensure that whatever value you set is a multiple
6572//! This symbol can be used to place the stack in a different memory region, for example:
6673//!
6774//! ```text
68- //! /* Linker script for the STM32F303VCT6 */
75+ //! /* Linker script for the STM32F303VCT6 with stack in CCM */
6976//! MEMORY
7077//! {
7178//! FLASH : ORIGIN = 0x08000000, LENGTH = 256K
7279//!
7380//! /* .bss, .data and the heap go in this region */
74- //! RAM : ORIGIN = 0x20000000, LENGTH = 40K
81+ //! RAM : ORIGIN = 0x20000000, LENGTH = 40K
7582//!
7683//! /* Core coupled (faster) RAM dedicated to hold the stack */
7784//! CCRAM : ORIGIN = 0x10000000, LENGTH = 8K
106113//! graph (see [`#[exception]`]). In this example we define them in the binary crate:
107114//!
108115//! ```no_run
109- //! // IMPORTANT the standard `main` interface is not used because it requires nightly
110116//! #![no_main]
111117//! #![no_std]
112118//!
113119//! // Some panic handler needs to be included. This one halts the processor on panic.
114- //! extern crate panic_halt;
120+ //! use panic_halt as _ ;
115121//!
116122//! use cortex_m_rt::entry;
117123//!
118- //! // use `main` as the entry point of this application
119- //! // `main` is not allowed to return
124+ //! // Use `main` as the entry point of this application, which may not return.
120125//! #[entry]
121126//! fn main() -> ! {
122127//! // initialization
133138//!
134139//! ```text
135140//! $ cat > memory.x <<EOF
136- //! /* Linker script for the STM32F103C8T6 */
137141//! MEMORY
138142//! {
139143//! FLASH : ORIGIN = 0x08000000, LENGTH = 64K
140144//! RAM : ORIGIN = 0x20000000, LENGTH = 20K
141145//! }
142146//! EOF
143147//!
144- //! $ cargo rustc --target thumbv7m-none-eabi -- \
145- //! -C link-arg=-nostartfiles -C link-arg=-Tlink.x
148+ //! $ cargo rustc --target thumbv7m-none-eabi -- -C link-arg=-nostartfiles -C link-arg=-Tlink.x
146149//!
147150//! $ file target/thumbv7m-none-eabi/debug/app
148151//! app: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, (..)
160163//!
161164//! If this feature is enabled then the interrupts section of the vector table is left unpopulated
162165//! and some other crate, or the user, will have to populate it. This mode is meant to be used in
163- //! conjunction with crates generated using `svd2rust`. Those *device crates* will populate the
164- //! missing part of the vector table when their `"rt"` feature is enabled.
166+ //! conjunction with crates generated using `svd2rust`. Those peripheral access crates, or PACs,
167+ //! will populate the missing part of the vector table when their `"rt"` feature is enabled.
165168//!
166169//! ## `set-sp`
167170//!
168171//! If this feature is enabled, the stack pointer (SP) is initialised in the reset handler to the
169172//! `_stack_start` value from the linker script. This is not usually required, but some debuggers
170173//! do not initialise SP when performing a soft reset, which can lead to stack corruption.
171174//!
172- //! ## `zero-init-ram`
173- //!
174- //! If this feature is enabled, RAM is initialized with zeros during startup from the `_ram_start`
175- //! value to the `_ram_end` value from the linker script. This is not usually required, but might be
176- //! necessary to properly initialize checksum-based memory integrity measures on safety-critical
177- //! hardware.
178- //!
179175//! ## `set-vtor`
180176//!
181177//! If this feature is enabled, the vector table offset register (VTOR) is initialised in the reset
182178//! handler to the start of the vector table defined in the linker script. This is not usually
183179//! required, but some bootloaders do not set VTOR before jumping to application code, leading to
184180//! your main function executing but interrupt handlers not being used.
185181//!
182+ //! ## `zero-init-ram`
183+ //!
184+ //! If this feature is enabled, RAM is initialized with zeros during startup from the `_ram_start`
185+ //! value to the `_ram_end` value from the linker script. This is not usually required, but might be
186+ //! necessary to properly initialize memory integrity measures on some hardware.
187+ //!
186188//! # Inspection
187189//!
188190//! This section covers how to inspect a binary that builds on top of `cortex-m-rt`.
252254//! `__EXCEPTIONS` in the `.vector_table` section.
253255//!
254256//! - `__pre_init`. This is a function to be run before RAM is initialized. It defaults to an empty
255- //! function. The function called can be changed by applying the [`#[pre_init]`][attr-pre_init]
256- //! attribute to a function.
257+ //! function. As this runs before RAM is initialised, it is not sound to use a Rust function for
258+ //! `pre_init`, and instead it should typically be written in assembly using `global_asm` or an
259+ //! external assembly file.
257260//!
258261//! If you override any exception handler you'll find it as an unmangled symbol, e.g. `SysTick` or
259262//! `SVCall`, in the output of `objdump`,
260263//!
261264//! # Advanced usage
262265//!
266+ //! ## Custom linker script
267+ //!
268+ //! To use your own linker script, ensure it is placed in the linker search path (for example in
269+ //! the crate root or in Cargo's `OUT_DIR`) and use it with `-C link-arg=-Tmy_script.ld` instead
270+ //! of the normal `-C link-arg=-Tlink.x`. The provided `link.x` may be used as a starting point
271+ //! for customisation.
272+ //!
263273//! ## Setting the program entry point
264274//!
265275//! This section describes how [`#[entry]`][attr-entry] is implemented. This information is useful
278288//!
279289//! This section covers how an external crate can insert device specific interrupt handlers into the
280290//! vector table. Most users don't need to concern themselves with these details, but if you are
281- //! interested in how device crates generated using `svd2rust` integrate with `cortex-m-rt` read on.
291+ //! interested in how PACs generated using `svd2rust` integrate with `cortex-m-rt` read on.
282292//!
283293//! The information in this section applies when the `"device"` feature has been enabled.
284294//!
381391//! to be used as thread stacks) -- this can considerably reduce initialization time on devices that
382392//! operate at low frequencies.
383393//!
384- //! The only correct way to use this section is by placing `static mut` variables with type
385- //! [`MaybeUninit`] in it.
394+ //! The only correct way to use this section is with [`MaybeUninit`] types.
386395//!
387396//! [`MaybeUninit`]: https://doc.rust-lang.org/core/mem/union.MaybeUninit.html
388397//!
398407//! ```
399408//!
400409//! Be very careful with the `link_section` attribute because it's easy to misuse in ways that cause
401- //! undefined behavior. At some point in the future we may add an attribute to safely place static
402- //! variables in this section.
410+ //! undefined behavior.
403411//!
404412//! ## Extra Sections
405413//!
406- //! Some microcontrollers provide additional memory regions beyond RAM and FLASH.
407- //! For example, some STM32 devices provide "CCM" or core-coupled RAM that is
408- //! only accessible from the core. In order to access these using
409- //! [`link_section`] attributes from your code, you need to modify `memory.x`
410- //! to declare the additional sections:
414+ //! Some microcontrollers provide additional memory regions beyond RAM and FLASH. For example,
415+ //! some STM32 devices provide "CCM" or core-coupled RAM that is only accessible from the core. In
416+ //! order to place variables in these sections using [`link_section`] attributes from your code,
417+ //! you need to modify `memory.x` to declare the additional sections:
411418//!
412419//! [`link_section`]: https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute
413420//!
432439//! You can then use something like this to place a variable into this specific section of memory:
433440//!
434441//! ```no_run,edition2018
442+ //! # extern crate core;
443+ //! # use core::mem::MaybeUninit;
435444//! #[link_section=".ccmram.BUFFERS"]
436- //! static mut BUF: [u8; 1024] = [0u8; 1024] ;
445+ //! static mut BUF: MaybeUninit< [u8; 1024]> = MaybeUninit::uninit() ;
437446//! ```
438447//!
448+ //! However, note that these sections are not initialised by cortex-m-rt, and so must be used
449+ //! either with `MaybeUninit` types or you must otherwise arrange for them to be initialised
450+ //! yourself, such as in `pre_init`.
451+ //!
439452//! [attr-entry]: attr.entry.html
440453//! [attr-exception]: attr.exception.html
441454//! [attr-pre_init]: attr.pre_init.html
@@ -577,7 +590,7 @@ cfg_global_asm! {
577590///
578591/// **NOTE**: This attribute is exposed by `cortex-m-rt` only when the `device` feature is enabled.
579592/// However, that export is not meant to be used directly -- using it will result in a compilation
580- /// error. You should instead use the device crate (usually generated using `svd2rust`) re-export of
593+ /// error. You should instead use the PAC (usually generated using `svd2rust`) re-export of
581594/// that attribute. You need to use the re-export to have the compiler check that the interrupt
582595/// exists on the target device.
583596///
@@ -586,7 +599,7 @@ cfg_global_asm! {
586599/// ``` ignore
587600/// extern crate device;
588601///
589- /// // the attribute comes from the device crate not from cortex-m-rt
602+ /// // the attribute comes from the PAC not from cortex-m-rt
590603/// use device::interrupt;
591604///
592605/// #[interrupt]
0 commit comments