aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bors[bot] <bors[bot]@users.noreply.github.com> 2018-08-13 06:41:02 +0000
committerGravatar bors[bot] <bors[bot]@users.noreply.github.com> 2018-08-13 06:41:02 +0000
commit1089ef3423e60c6c9b186f77868ea1b16e153e01 (patch)
treed574ed4dee9ba3bc9ec195f6cb31b1c567226d83
parent96b76f974a7de4423f5bb0f529b399b0e310be2a (diff)
parent73e0b2a25d1766debe4f603dd13a732de2f1993d (diff)
downloadcortex-m-1089ef3423e60c6c9b186f77868ea1b16e153e01.tar.gz
cortex-m-1089ef3423e60c6c9b186f77868ea1b16e153e01.tar.zst
cortex-m-1089ef3423e60c6c9b186f77868ea1b16e153e01.zip
Merge #81
81: Add a __pre_init function to be called at the start of the reset handler r=korken89 a=yodaldevoid I needed this for a project so I went ahead and rebased and tweaked @jcsoo 's changes from #71. I will admit, I got a little impatient waiting and that also played into why I did this. If either @jcsoo or @japaric have an issue with this PR, please let me know and I will remove it. I apologize for toes that I have stepped on. Now onto the PR. This is possibly the simplest implementation that is possible. No nightly features were used in this implementation. Also, there is no hand-holding for the end user; if they want to mess with uninitialized statics, that is on them. If you would like me to add more documentation, please let me know what you would like to see. Fixes #17 Co-authored-by: Jonathan Soo <jcsoo@agora.com> Co-authored-by: Gabriel Smith <ga29smith@gmail.com>
-rw-r--r--cortex-m-rt/ci/script.sh1
-rw-r--r--cortex-m-rt/examples/pre_init.rs22
-rw-r--r--cortex-m-rt/link.x.in5
-rw-r--r--cortex-m-rt/src/lib.rs54
4 files changed, 82 insertions, 0 deletions
diff --git a/cortex-m-rt/ci/script.sh b/cortex-m-rt/ci/script.sh
index 2baec51..ac6df17 100644
--- a/cortex-m-rt/ci/script.sh
+++ b/cortex-m-rt/ci/script.sh
@@ -9,6 +9,7 @@ main() {
alignment
minimal
main
+ pre_init
state
)
local fail_examples=(
diff --git a/cortex-m-rt/examples/pre_init.rs b/cortex-m-rt/examples/pre_init.rs
new file mode 100644
index 0000000..7258936
--- /dev/null
+++ b/cortex-m-rt/examples/pre_init.rs
@@ -0,0 +1,22 @@
+//! `cortex-m-rt` based program with a function run before RAM is initialized.
+
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+#[macro_use(entry, pre_init)]
+extern crate cortex_m_rt as rt;
+extern crate panic_semihosting;
+
+pre_init!(disable_watchdog);
+
+unsafe fn disable_watchdog() {
+ // Do what you need to disable the watchdog.
+}
+
+// the program entry point
+entry!(main);
+
+fn main() -> ! {
+ loop {}
+}
diff --git a/cortex-m-rt/link.x.in b/cortex-m-rt/link.x.in
index dfcf262..23f406d 100644
--- a/cortex-m-rt/link.x.in
+++ b/cortex-m-rt/link.x.in
@@ -51,6 +51,11 @@ PROVIDE(UserHardFault = DefaultUserHardFault);
/* # Interrupt vectors */
EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */
+/* # Pre-initialization function */
+/* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function,
+ then the function this points to will be called before the RAM is initialized. */
+PROVIDE(__pre_init = DefaultPreInit);
+
/* # Sections */
SECTIONS
{
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();
+ }
+ }
+}