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.rs263
1 files changed, 13 insertions, 250 deletions
diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs
index 10f60f6..526b28b 100644
--- a/cortex-m-rt/src/lib.rs
+++ b/cortex-m-rt/src/lib.rs
@@ -94,18 +94,16 @@
//! #![no_main]
//! #![no_std]
//!
-//! #[macro_use(entry, exception)]
//! extern crate cortex_m_rt as rt;
//!
//! // makes `panic!` print messages to the host stderr using semihosting
//! extern crate panic_semihosting;
//!
-//! use rt::ExceptionFrame;
+//! use rt::entry;
//!
//! // use `main` as the entry point of this application
-//! entry!(main);
-//!
//! // `main` is not allowed to return
+//! #[entry]
//! fn main() -> ! {
//! // initialization
//!
@@ -113,20 +111,6 @@
//! // application logic
//! }
//! }
-//!
-//! // define the hard fault handler
-//! exception!(HardFault, hard_fault);
-//!
-//! fn hard_fault(ef: &ExceptionFrame) -> ! {
-//! panic!("{:#?}", ef);
-//! }
-//!
-//! // define the default exception handler
-//! exception!(*, default_handler);
-//!
-//! fn default_handler(irqn: i16) {
-//! panic!("unhandled exception (IRQn={})", irqn);
-//! }
//! ```
//!
//! To actually build this program you need to place a `memory.x` linker script somewhere the linker
@@ -397,11 +381,14 @@
#![deny(warnings)]
#![no_std]
+extern crate cortex_m_rt_macros as macros;
extern crate r0;
use core::fmt;
use core::sync::atomic::{self, Ordering};
+pub use macros::{entry, exception, pre_init};
+
/// Registers stacked (pushed into the stack) during an exception
#[derive(Clone, Copy)]
#[repr(C)]
@@ -474,8 +461,6 @@ pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset;
#[no_mangle]
pub unsafe extern "C" fn Reset() -> ! {
extern "C" {
- // This symbol will be provided by the user via the `entry!` macro
- fn main() -> !;
// These symbols come from `link.x`
static mut __sbss: u32;
@@ -485,11 +470,17 @@ pub unsafe extern "C" fn Reset() -> ! {
static mut __edata: u32;
static __sidata: u32;
+ }
+
+ extern "Rust" {
+ // This symbol will be provided by the user via `#[entry]`
+ fn main() -> !;
+
+ // This symbol will be provided by the user via `#[pre_init]`
fn __pre_init();
}
- let pre_init: unsafe extern "C" fn() = __pre_init;
- pre_init();
+ __pre_init();
// Initialize RAM
r0::zero_bss(&mut __sbss, &mut __ebss);
@@ -551,31 +542,6 @@ pub unsafe extern "C" fn DefaultHandler_() -> ! {
#[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
-/// from the root of the crate.
-///
-/// Usage: `entry!(path::to::entry::point)`
-///
-/// The specified function will be called by the reset handler *after* RAM has been initialized. In
-/// the case of the `thumbv7em-none-eabihf` target the FPU will also be enabled before the function
-/// is called.
-///
-/// The signature of the specified function must be `fn() -> !` (never ending function)
-#[macro_export]
-macro_rules! entry {
- ($path:expr) => {
- #[export_name = "main"]
- pub extern "C" fn __impl_main() -> ! {
- // validate the signature of the program entry point
- let f: fn() -> ! = $path;
-
- f()
- }
- };
-}
-
/* Exceptions */
#[doc(hidden)]
pub enum Exception {
@@ -721,206 +687,3 @@ pub static __INTERRUPTS: [unsafe extern "C" fn(); 32] = [{
DefaultHandler
}; 32];
-
-/// Macro to set or override a processor core exception handler
-///
-/// **NOTE** This macro must be invoked from an accessible module, ideally from the root of the
-/// crate.
-///
-/// # Syntax
-///
-/// ``` ignore
-/// exception!(
-/// // Name of the exception
-/// $Name:ident,
-///
-/// // Path to the exception handler (a function)
-/// $handler:expr,
-///
-/// // Optional, state preserved across invocations of the handler
-/// state: $State:ty = $initial_state:expr,
-/// );
-/// ```
-///
-/// where `$Name` can be one of:
-///
-/// - `*`
-/// - `NonMaskableInt`
-/// - `HardFault`
-/// - `MemoryManagement` (a)
-/// - `BusFault` (a)
-/// - `UsageFault` (a)
-/// - `SecureFault` (b)
-/// - `SVCall`
-/// - `DebugMonitor` (a)
-/// - `PendSV`
-/// - `SysTick`
-///
-/// (a) Not available on Cortex-M0 variants (`thumbv6m-none-eabi`)
-///
-/// (b) Only available on ARMv8-M
-///
-/// # Usage
-///
-/// `exception!(HardFault, ..)` sets the hard fault handler. The handler must have signature
-/// `fn(&ExceptionFrame) -> !`. This handler is not allowed to return as that can cause undefined
-/// behavior. It's mandatory to set the `HardFault` handler somewhere in the dependency graph of an
-/// application.
-///
-/// `exception!(*, ..)` sets the *default* handler. All exceptions which have not been assigned a
-/// handler will be serviced by this handler. This handler must have signature `fn(irqn: i16)`.
-/// `irqn` is the IRQ number (cf. CMSIS); `irqn` will be a negative number when the handler is
-/// servicing a core exception; `irqn` will be a positive number when the handler is servicing a
-/// device specific exception (interrupt). It's mandatory to set the default handler somewhere
-/// in the dependency graph of an application.
-///
-/// `exception!($Exception, ..)` overrides the default handler for `$Exception`. All exceptions,
-/// except for `HardFault`, can be assigned some `$State`.
-///
-/// # Examples
-///
-/// - Setting the `HardFault` handler
-///
-/// ```
-/// #[macro_use(exception)]
-/// extern crate cortex_m_rt as rt;
-///
-/// use rt::ExceptionFrame;
-///
-/// exception!(HardFault, hard_fault);
-///
-/// fn hard_fault(ef: &ExceptionFrame) -> ! {
-/// // prints the exception frame as a panic message
-/// panic!("{:#?}", ef);
-/// }
-///
-/// # fn main() {}
-/// ```
-///
-/// - Setting the default handler
-///
-/// ```
-/// #[macro_use(exception)]
-/// extern crate cortex_m_rt as rt;
-///
-/// exception!(*, default_handler);
-///
-/// fn default_handler(irqn: i16) {
-/// println!("IRQn = {}", irqn);
-/// }
-///
-/// # fn main() {}
-/// ```
-///
-/// - Overriding the `SysTick` handler
-///
-/// ```
-/// #[macro_use(exception)]
-/// extern crate cortex_m_rt as rt;
-///
-/// exception!(SysTick, sys_tick, state: u32 = 0);
-///
-/// fn sys_tick(count: &mut u32) {
-/// println!("count = {}", *count);
-///
-/// *count += 1;
-/// }
-///
-/// # fn main() {}
-/// ```
-#[macro_export]
-macro_rules! exception {
- (* , $handler:expr) => {
- #[allow(unsafe_code)]
- #[deny(private_no_mangle_fns)] // raise an error if this item is not accessible
- #[no_mangle]
- pub unsafe extern "C" fn DefaultHandler() {
- extern crate core;
-
- // validate the signature of the user provided handler
- let f: fn(i16) = $handler;
-
- const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
-
- // NOTE not volatile so the compiler can opt the load operation away if the value is
- // unused
- f(core::ptr::read(SCB_ICSR) as u8 as i16 - 16)
- }
- };
-
- (HardFault, $handler:expr) => {
- #[allow(unsafe_code)]
- #[deny(private_no_mangle_fns)] // raise an error if this item is not accessible
- #[no_mangle]
- pub unsafe extern "C" fn UserHardFault(ef: &$crate::ExceptionFrame) {
- // validate the signature of the user provided handler
- let f: fn(&$crate::ExceptionFrame) -> ! = $handler;
-
- f(ef)
- }
- };
-
- ($Name:ident, $handler:expr,state: $State:ty = $initial_state:expr) => {
- #[allow(unsafe_code)]
- #[deny(private_no_mangle_fns)] // raise an error if this item is not accessible
- #[no_mangle]
- pub unsafe extern "C" fn $Name() {
- static mut STATE: $State = $initial_state;
-
- // check that this exception exists
- let _ = $crate::Exception::$Name;
-
- // validate the signature of the user provided handler
- let f: fn(&mut $State) = $handler;
-
- f(&mut STATE)
- }
- };
-
- ($Name:ident, $handler:expr) => {
- #[allow(unsafe_code)]
- #[deny(private_no_mangle_fns)] // raise an error if this item is not accessible
- #[no_mangle]
- pub unsafe extern "C" fn $Name() {
- // check that this exception exists
- let _ = $crate::Exception::$Name;
-
- // validate the signature of the user provided handler
- let f: fn() = $handler;
-
- f()
- }
- };
-}
-
-/// 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();
- }
- };
-}