aboutsummaryrefslogtreecommitdiff
path: root/cortex-m-rt/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cortex-m-rt/src/lib.rs')
-rw-r--r--cortex-m-rt/src/lib.rs54
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();
+ }
+ }
+}