|
237 | 237 | //! have a size of 32 vectors (on ARMv6-M) or 240 vectors (on ARMv7-M). This array is located after
|
238 | 238 | //! `__EXCEPTIONS` in the `.vector_table` section.
|
239 | 239 | //!
|
| 240 | +//! - `__pre_init`. This is a function to be run before RAM is initialized. It defaults to an empty |
| 241 | +//! function. The function called can be changed by calling the `pre_init!` macro. The empty |
| 242 | +//! function is not optimized out by default, but if an empty function is passed to `pre_init!` the |
| 243 | +//! function call will be optimized out. |
| 244 | +//! |
240 | 245 | //! If you override any exception handler you'll find it as an unmangled symbol, e.g. `SysTick` or
|
241 | 246 | //! `SVCall`, in the output of `objdump`,
|
242 | 247 | //!
|
|
378 | 383 | //! println!("cargo:rustc-link-search={}", out.display());
|
379 | 384 | //! }
|
380 | 385 | //! ```
|
| 386 | +//! |
| 387 | +//! ## `pre_init!` |
| 388 | +//! |
| 389 | +//! A user-defined function can be run at the start of the reset handler, before RAM is |
| 390 | +//! initialized. The macro `pre_init!` can be called to set the function to be run. The function is |
| 391 | +//! intended to perform actions that cannot wait the time it takes for RAM to be initialized, such |
| 392 | +//! as disabling a watchdog. As the function is called before RAM is initialized, any access of |
| 393 | +//! static variables will result in undefined behavior. |
381 | 394 |
|
382 | 395 | // # Developer notes
|
383 | 396 | //
|
@@ -474,8 +487,13 @@ pub unsafe extern "C" fn Reset() -> ! {
|
474 | 487 | static mut __sdata: u32;
|
475 | 488 | static mut __edata: u32;
|
476 | 489 | static __sidata: u32;
|
| 490 | + |
| 491 | + fn __pre_init(); |
477 | 492 | }
|
478 | 493 |
|
| 494 | + let pre_init: unsafe extern "C" fn() = __pre_init; |
| 495 | + pre_init(); |
| 496 | + |
479 | 497 | // Initialize RAM
|
480 | 498 | r0::zero_bss(&mut __sbss, &mut __ebss);
|
481 | 499 | r0::init_data(&mut __sdata, &mut __edata, &__sidata);
|
@@ -531,6 +549,10 @@ pub unsafe extern "C" fn DefaultUserHardFault() {
|
531 | 549 | }
|
532 | 550 | }
|
533 | 551 |
|
| 552 | +#[doc(hidden)] |
| 553 | +#[no_mangle] |
| 554 | +pub unsafe extern "C" fn DefaultPreInit() {} |
| 555 | + |
534 | 556 | /// Macro to define the entry point of the program
|
535 | 557 | ///
|
536 | 558 | /// **NOTE** This macro must be invoked once and must be invoked from an accessible module, ideally
|
@@ -872,3 +894,35 @@ macro_rules! exception {
|
872 | 894 | }
|
873 | 895 | };
|
874 | 896 | }
|
| 897 | + |
| 898 | +/// Macro to set the function to be called at the beginning of the reset handler. |
| 899 | +/// |
| 900 | +/// The function must have the signature of `unsafe fn()`. |
| 901 | +/// |
| 902 | +/// The function passed will be called before static variables are initialized. Any access of static |
| 903 | +/// variables will result in undefined behavior. |
| 904 | +/// |
| 905 | +/// # Examples |
| 906 | +/// |
| 907 | +/// ``` ignore |
| 908 | +/// pre_init!(foo::bar); |
| 909 | +/// |
| 910 | +/// mod foo { |
| 911 | +/// pub unsafe fn bar() { |
| 912 | +/// // do something here |
| 913 | +/// } |
| 914 | +/// } |
| 915 | +/// ``` |
| 916 | +#[macro_export] |
| 917 | +macro_rules! pre_init { |
| 918 | + ($handler:path) => { |
| 919 | + #[allow(unsafe_code)] |
| 920 | + #[deny(private_no_mangle_fns)] // raise an error if this item is not accessible |
| 921 | + #[no_mangle] |
| 922 | + pub unsafe extern "C" fn __pre_init() { |
| 923 | + // validate user handler |
| 924 | + let f: unsafe fn() = $handler; |
| 925 | + f(); |
| 926 | + } |
| 927 | + } |
| 928 | +} |
0 commit comments