diff options
Diffstat (limited to 'cortex-m-rt/src/lib.rs')
-rw-r--r-- | cortex-m-rt/src/lib.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 60c8034..cecb5f8 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -237,6 +237,11 @@ //! have a size of 32 vectors (on ARMv6-M) or 240 vectors (on ARMv7-M). This array is located after //! `__EXCEPTIONS` in the `.vector_table` section. //! +//! - `__pre_init`. This is a function to be run before RAM is initialized. It defaults to an empty +//! function. The function called can be changed by calling the `pre_init!` macro. The empty +//! function is not optimized out by default, but if an empty function is passed to `pre_init!` the +//! function call will be optimized out. +//! //! If you override any exception handler you'll find it as an unmangled symbol, e.g. `SysTick` or //! `SVCall`, in the output of `objdump`, //! @@ -378,6 +383,14 @@ //! println!("cargo:rustc-link-search={}", out.display()); //! } //! ``` +//! +//! ## `pre_init!` +//! +//! A user-defined function can be run at the start of the reset handler, before RAM is +//! initialized. The macro `pre_init!` can be called to set the function to be run. The function is +//! intended to perform actions that cannot wait the time it takes for RAM to be initialized, such +//! as disabling a watchdog. As the function is called before RAM is initialized, any access of +//! static variables will result in undefined behavior. // # Developer notes // @@ -474,8 +487,13 @@ pub unsafe extern "C" fn Reset() -> ! { static mut __sdata: u32; static mut __edata: u32; static __sidata: u32; + + fn __pre_init(); } + let pre_init: unsafe extern "C" fn() = __pre_init; + pre_init(); + // Initialize RAM r0::zero_bss(&mut __sbss, &mut __ebss); r0::init_data(&mut __sdata, &mut __edata, &__sidata); @@ -531,6 +549,10 @@ pub unsafe extern "C" fn DefaultUserHardFault() { } } +#[doc(hidden)] +#[no_mangle] +pub unsafe extern "C" fn DefaultPreInit() {} + /// Macro to define the entry point of the program /// /// **NOTE** This macro must be invoked once and must be invoked from an accessible module, ideally @@ -872,3 +894,35 @@ macro_rules! exception { } }; } + +/// Macro to set the function to be called at the beginning of the reset handler. +/// +/// The function must have the signature of `unsafe fn()`. +/// +/// The function passed will be called before static variables are initialized. Any access of static +/// variables will result in undefined behavior. +/// +/// # Examples +/// +/// ``` ignore +/// pre_init!(foo::bar); +/// +/// mod foo { +/// pub unsafe fn bar() { +/// // do something here +/// } +/// } +/// ``` +#[macro_export] +macro_rules! pre_init { + ($handler:path) => { + #[allow(unsafe_code)] + #[deny(private_no_mangle_fns)] // raise an error if this item is not accessible + #[no_mangle] + pub unsafe extern "C" fn __pre_init() { + // validate user handler + let f: unsafe fn() = $handler; + f(); + } + } +} |