Skip to content

Commit e6a6769

Browse files
jcsooyodaldevoid
authored andcommitted
Add a __pre_init function to be called at the start of the reset handler
The call to the function and the macro to set it are both gated behind the `pre_init` feature flag. Signed-off-by: Gabriel Smith <[email protected]>
1 parent 96b76f9 commit e6a6769

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

cortex-m-rt/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ panic-abort = "0.2.0"
2121

2222
[features]
2323
device = []
24+
pre_init = []

cortex-m-rt/src/lib.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,13 @@
169169
//! conjunction with crates generated using `svd2rust`. Those *device crates* will populate the
170170
//! missing part of the vector table when their `"rt"` feature is enabled.
171171
//!
172+
//! ## `pre_init`
173+
//!
174+
//! If this feature is enabled then a user-defined function will be run at the start of the reset
175+
//! handler, before RAM is initialized. If this feature is enabled then the macro `pre_init!` needs
176+
//! to be called to set the function to be run. This feature is intended to perform actions that
177+
//! cannot wait the time it takes for RAM to be initialized, such as disabling a watchdog.
178+
//!
172179
//! # Inspection
173180
//!
174181
//! This section covers how to inspect a binary that builds on top of `cortex-m-rt`.
@@ -474,8 +481,14 @@ pub unsafe extern "C" fn Reset() -> ! {
474481
static mut __sdata: u32;
475482
static mut __edata: u32;
476483
static __sidata: u32;
484+
485+
#[cfg(feature = "pre_init")]
486+
fn _pre_init();
477487
}
478488

489+
#[cfg(feature = "pre_init")]
490+
_pre_init();
491+
479492
// Initialize RAM
480493
r0::zero_bss(&mut __sbss, &mut __ebss);
481494
r0::init_data(&mut __sdata, &mut __edata, &__sidata);
@@ -872,3 +885,36 @@ macro_rules! exception {
872885
}
873886
};
874887
}
888+
889+
/// Macro to set the function to be called at the beginning of the reset handler.
890+
///
891+
/// The function must have the signature of `unsafe fn()`.
892+
///
893+
/// The function passed will be called before static variables are initialized. Any access of static
894+
/// variables will result in undefined behavior.
895+
///
896+
/// # Examples
897+
///
898+
/// ``` ignore
899+
/// pre_init!(foo::bar);
900+
///
901+
/// mod foo {
902+
/// pub unsafe fn bar() {
903+
/// // do something here
904+
/// }
905+
/// }
906+
/// ```
907+
#[cfg(feature = "pre_init")]
908+
#[macro_export]
909+
macro_rules! pre_init {
910+
($handler:path) => {
911+
#[allow(unsafe_code)]
912+
#[deny(private_no_mangle_fns)] // raise an error if this item is not accessible
913+
#[no_mangle]
914+
pub unsafe extern "C" fn _pre_init() {
915+
// validate user handler
916+
let f: unsafe fn() = $handler;
917+
f();
918+
}
919+
}
920+
}

0 commit comments

Comments
 (0)