12
12
//!
13
13
//! - Initializing `static` variables before the program entry point.
14
14
//!
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`.
16
16
//!
17
17
//! This crate also provides the following attributes:
18
18
//!
19
19
//! - [`#[entry]`][attr-entry] to declare the entry point of the program
20
20
//! - [`#[exception]`][attr-exception] to override an exception handler. If not overridden all
21
21
//! exception handlers default to an infinite loop.
22
- //! - [`#[pre_init]`][attr-pre_init] to run code *before* `static` variables are initialized
23
22
//!
24
23
//! This crate also implements a related attribute called `#[interrupt]`, which allows you
25
24
//! 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.
27
32
//!
28
33
//! The documentation for these attributes can be found in the [Attribute Macros](#attributes)
29
34
//! section.
33
38
//! ## `memory.x`
34
39
//!
35
40
//! 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.
38
44
//!
39
45
//! ### `MEMORY`
40
46
//!
48
54
//! MEMORY
49
55
//! {
50
56
//! FLASH : ORIGIN = 0x08000000, LENGTH = 64K
51
- //! RAM : ORIGIN = 0x20000000, LENGTH = 20K
57
+ //! RAM : ORIGIN = 0x20000000, LENGTH = 20K
52
58
//! }
53
59
//! ```
54
60
//!
55
61
//! ### `_stack_start`
56
62
//!
57
63
//! This optional symbol can be used to indicate where the call stack of the program should be
58
64
//! 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`.
60
67
//!
61
68
//! For Cortex-M, the `_stack_start` must always be aligned to 8 bytes, which is enforced by
62
69
//! the linker script. If you override it, ensure that whatever value you set is a multiple
65
72
//! This symbol can be used to place the stack in a different memory region, for example:
66
73
//!
67
74
//! ```text
68
- //! /* Linker script for the STM32F303VCT6 */
75
+ //! /* Linker script for the STM32F303VCT6 with stack in CCM */
69
76
//! MEMORY
70
77
//! {
71
78
//! FLASH : ORIGIN = 0x08000000, LENGTH = 256K
72
79
//!
73
80
//! /* .bss, .data and the heap go in this region */
74
- //! RAM : ORIGIN = 0x20000000, LENGTH = 40K
81
+ //! RAM : ORIGIN = 0x20000000, LENGTH = 40K
75
82
//!
76
83
//! /* Core coupled (faster) RAM dedicated to hold the stack */
77
84
//! CCRAM : ORIGIN = 0x10000000, LENGTH = 8K
106
113
//! graph (see [`#[exception]`]). In this example we define them in the binary crate:
107
114
//!
108
115
//! ```no_run
109
- //! // IMPORTANT the standard `main` interface is not used because it requires nightly
110
116
//! #![no_main]
111
117
//! #![no_std]
112
118
//!
113
119
//! // Some panic handler needs to be included. This one halts the processor on panic.
114
- //! extern crate panic_halt;
120
+ //! use panic_halt as _ ;
115
121
//!
116
122
//! use cortex_m_rt::entry;
117
123
//!
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.
120
125
//! #[entry]
121
126
//! fn main() -> ! {
122
127
//! // initialization
133
138
//!
134
139
//! ```text
135
140
//! $ cat > memory.x <<EOF
136
- //! /* Linker script for the STM32F103C8T6 */
137
141
//! MEMORY
138
142
//! {
139
143
//! FLASH : ORIGIN = 0x08000000, LENGTH = 64K
140
144
//! RAM : ORIGIN = 0x20000000, LENGTH = 20K
141
145
//! }
142
146
//! EOF
143
147
//!
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
146
149
//!
147
150
//! $ file target/thumbv7m-none-eabi/debug/app
148
151
//! app: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, (..)
160
163
//!
161
164
//! If this feature is enabled then the interrupts section of the vector table is left unpopulated
162
165
//! 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.
165
168
//!
166
169
//! ## `set-sp`
167
170
//!
168
171
//! If this feature is enabled, the stack pointer (SP) is initialised in the reset handler to the
169
172
//! `_stack_start` value from the linker script. This is not usually required, but some debuggers
170
173
//! do not initialise SP when performing a soft reset, which can lead to stack corruption.
171
174
//!
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
- //!
179
175
//! ## `set-vtor`
180
176
//!
181
177
//! If this feature is enabled, the vector table offset register (VTOR) is initialised in the reset
182
178
//! handler to the start of the vector table defined in the linker script. This is not usually
183
179
//! required, but some bootloaders do not set VTOR before jumping to application code, leading to
184
180
//! your main function executing but interrupt handlers not being used.
185
181
//!
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
+ //!
186
188
//! # Inspection
187
189
//!
188
190
//! This section covers how to inspect a binary that builds on top of `cortex-m-rt`.
252
254
//! `__EXCEPTIONS` in the `.vector_table` section.
253
255
//!
254
256
//! - `__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.
257
260
//!
258
261
//! If you override any exception handler you'll find it as an unmangled symbol, e.g. `SysTick` or
259
262
//! `SVCall`, in the output of `objdump`,
260
263
//!
261
264
//! # Advanced usage
262
265
//!
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
+ //!
263
273
//! ## Setting the program entry point
264
274
//!
265
275
//! This section describes how [`#[entry]`][attr-entry] is implemented. This information is useful
278
288
//!
279
289
//! This section covers how an external crate can insert device specific interrupt handlers into the
280
290
//! 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.
282
292
//!
283
293
//! The information in this section applies when the `"device"` feature has been enabled.
284
294
//!
381
391
//! to be used as thread stacks) -- this can considerably reduce initialization time on devices that
382
392
//! operate at low frequencies.
383
393
//!
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.
386
395
//!
387
396
//! [`MaybeUninit`]: https://doc.rust-lang.org/core/mem/union.MaybeUninit.html
388
397
//!
398
407
//! ```
399
408
//!
400
409
//! 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.
403
411
//!
404
412
//! ## Extra Sections
405
413
//!
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:
411
418
//!
412
419
//! [`link_section`]: https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute
413
420
//!
432
439
//! You can then use something like this to place a variable into this specific section of memory:
433
440
//!
434
441
//! ```no_run,edition2018
442
+ //! # extern crate core;
443
+ //! # use core::mem::MaybeUninit;
435
444
//! #[link_section=".ccmram.BUFFERS"]
436
- //! static mut BUF: [u8; 1024] = [0u8; 1024] ;
445
+ //! static mut BUF: MaybeUninit< [u8; 1024]> = MaybeUninit::uninit() ;
437
446
//! ```
438
447
//!
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
+ //!
439
452
//! [attr-entry]: attr.entry.html
440
453
//! [attr-exception]: attr.exception.html
441
454
//! [attr-pre_init]: attr.pre_init.html
@@ -577,7 +590,7 @@ cfg_global_asm! {
577
590
///
578
591
/// **NOTE**: This attribute is exposed by `cortex-m-rt` only when the `device` feature is enabled.
579
592
/// 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
581
594
/// that attribute. You need to use the re-export to have the compiler check that the interrupt
582
595
/// exists on the target device.
583
596
///
@@ -586,7 +599,7 @@ cfg_global_asm! {
586
599
/// ``` ignore
587
600
/// extern crate device;
588
601
///
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
590
603
/// use device::interrupt;
591
604
///
592
605
/// #[interrupt]
0 commit comments