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 | |