Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

Commit

Permalink
Add method of passing peripherals from init_array to main
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Smith <[email protected]>
  • Loading branch information
yodaldevoid committed Feb 3, 2018
1 parent 62570c9 commit 5300fc5
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repository = "https://github.com/japaric/cortex-m-rt"
version = "0.3.12"

[dependencies]
cortex-m = "0.3.0"
cortex-m = "0.4.3"
r0 = "0.2.1"

[features]
Expand Down
10 changes: 10 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ fn main() {

has_fpu(&target);
is_armv6m(&target);
is_armv7m(&target);

// Put the linker script somewhere the linker can find it
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
Expand All @@ -48,3 +49,12 @@ fn is_armv6m(target: &str) {
println!("cargo:rustc-cfg=armv6m");
}
}

fn is_armv7m(target: &str) {
if target.starts_with("thumbv7m-") {
println!("cargo:rustc-cfg=armv7m");
} else if target.starts_with("thumbv7em-") {
println!("cargo:rustc-cfg=armv7m");
//println!("cargo:rustc-cfg=armv7em");
}
}
186 changes: 186 additions & 0 deletions src/init_array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
//! Core peripheral support when using `init_array`
//!
//! Allows passing on any subset of peripherals normally `take`n from
//! `cortex_m::peripheral::Peripherals`. Once in `main` `InitArrayPeripherals`
//! cannot be given back.
//!
//! ``` no_run
//! extern crate cortex_m;
//!
//! use cortex_m_rt::init_array::InitArrayPeripherals;
//!
//! init_array!(before_main, {
//! let mut peripherals = InitArrayPeripherals::take().unwrap();
//! peripherals.DWT.enable_cycle_counter();
//! InitArrayPeripherals::give(peripherals);
//! });
//!
//! fn main() {
//! let ok = InitArrayPeripherals::take().unwrap();
//! let panics = InitArrayPeripherals::take().unwrap();
//! }
//! ```
//!
//! Select peripherals can be dropped by creating a new `InitArrayPeripherals`
//! with `None` in place of the peripheral.
//!
//! ``` no_run
//! extern crate cortex_m;
//!
//! use cortex_m::peripheral::Peripherals;
//! use cortex_m_rt::init_array::InitArrayPeripherals;
//!
//! init_array!(before_main, {
//! let mut Peripherals {
//! CBP,
//! CPUID,
//! DCB,
//! DWT,
//! FPB,
//! FPU,
//! ITM,
//! MPU,
//! NVIC,
//! SCB,
//! SYST,
//! TPIU,
//! } = Peripherals::take().unwrap();
//! DWT.enable_cycle_counter();
//! let pass_on_peripherals = InitArrayPeripherals {
//! Some(CBP),
//! Some(CPUID),
//! Some(DCB),
//! None, // Don't pass on DWT
//! Some(FPB),
//! Some(FPU),
//! Some(ITM),
//! Some(MPU),
//! Some(NVIC),
//! Some(SCB),
//! Some(SYST),
//! Some(TPIU),
//! }
//! InitArrayPeripherals::give(pass_on_peripherals);
//! });
//!
//! fn main() {
//! let peripherals = InitArrayPeripherals::take().unwrap();
//! assert!(peripherals.DWT.is_none());
//! }
//! ```

#![allow(private_no_mangle_statics)]

use cortex_m::peripheral::{self, Peripherals};
use cortex_m::interrupt;

/// Core peripherals handed back from `init_array`
#[allow(non_snake_case)]
pub struct InitArrayPeripherals {
/// Cache and branch predictor maintenance operations
#[cfg(any(armv7m, target_arch = "x86_64"))]
pub CBP: Option<peripheral::CBP>,
/// CPUID
pub CPUID: Option<peripheral::CPUID>,
/// Debug Control Block
pub DCB: Option<peripheral::DCB>,
/// Data Watchpoint and Trace unit
pub DWT: Option<peripheral::DWT>,
/// Flash Patch and Breakpoint unit
#[cfg(any(armv7m, target_arch = "x86_64"))]
pub FPB: Option<peripheral::FPB>,
/// Floating Point Unit
#[cfg(any(has_fpu, target_arch = "x86_64"))]
pub FPU: Option<peripheral::FPU>,
/// Instrumentation Trace Macrocell
#[cfg(any(armv7m, target_arch = "x86_64"))]
pub ITM: Option<peripheral::ITM>,
/// Memory Protection Unit
pub MPU: Option<peripheral::MPU>,
/// Nested Vector Interrupt Controller
pub NVIC: Option<peripheral::NVIC>,
/// System Control Block
pub SCB: Option<peripheral::SCB>,
/// SysTick: System Timer
pub SYST: Option<peripheral::SYST>,
/// Trace Port Interface Unit;
#[cfg(any(armv7m, target_arch = "x86_64"))]
pub TPIU: Option<peripheral::TPIU>,
}

#[no_mangle]
static mut INIT_ARRAY_PERIPHERALS: Option<InitArrayPeripherals> = None;
#[no_mangle]
static mut INIT_ARRAY_DONE: bool = false;

impl InitArrayPeripherals {
/// Returns all the core peripherals. Can be given back in an `init_array`
/// function by calling `give`.
pub fn take() -> Option<Self> {
interrupt::free(|_| { unsafe { INIT_ARRAY_PERIPHERALS.take() } }).or_else(|| {
Peripherals::take().map(InitArrayPeripherals::from)
})
}

/// Give the peripherals back for use in `main` after using them in
/// `init_array`. Does nothing if called after `init_array`.
pub fn give<P: Into<InitArrayPeripherals>>(p: P) {
interrupt::free(|_| {
if unsafe { !INIT_ARRAY_DONE } {
unsafe { INIT_ARRAY_PERIPHERALS = Some(p.into()) }
}
})
}

pub(crate) fn done() {
interrupt::free(|_| {
unsafe { INIT_ARRAY_DONE = true };
})
}
}

#[allow(non_snake_case)]
impl From<Peripherals> for InitArrayPeripherals {
fn from(p: Peripherals) -> Self {
let Peripherals {
#[cfg(any(armv7m, target_arch = "x86_64"))]
CBP,
CPUID,
DCB,
DWT,
#[cfg(any(armv7m, target_arch = "x86_64"))]
FPB,
#[cfg(any(has_fpu, target_arch = "x86_64"))]
FPU,
#[cfg(any(armv7m, target_arch = "x86_64"))]
ITM,
MPU,
NVIC,
SCB,
SYST,
#[cfg(any(armv7m, target_arch = "x86_64"))]
TPIU,
..
} = p;

InitArrayPeripherals {
#[cfg(any(armv7m, target_arch = "x86_64"))]
CBP: Some(CBP),
CPUID: Some(CPUID),
DCB: Some(DCB),
DWT: Some(DWT),
#[cfg(any(armv7m, target_arch = "x86_64"))]
FPB: Some(FPB),
#[cfg(any(has_fpu, target_arch = "x86_64"))]
FPU: Some(FPU),
#[cfg(any(armv7m, target_arch = "x86_64"))]
ITM: Some(ITM),
MPU: Some(MPU),
NVIC: Some(NVIC),
SCB: Some(SCB),
SYST: Some(SYST),
#[cfg(any(armv7m, target_arch = "x86_64"))]
TPIU: Some(TPIU),
}
}
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ extern crate r0;

#[cfg(all(feature = "init_array", target_arch = "arm"))]
pub use r0::init_array;
#[cfg(all(feature = "init_array", target_arch = "arm"))]
pub mod init_array;

#[cfg(not(test))]
mod lang_items;
Expand Down Expand Up @@ -337,6 +339,8 @@ static RESET_VECTOR: unsafe extern "C" fn() -> ! = reset_handler;
unsafe extern "C" fn reset_handler() -> ! {
#[cfg(feature = "init_array")]
r0::run_init_array(&_init_array_start, &_init_array_end);
#[cfg(feature = "init_array")]
init_array::InitArrayPeripherals::done();
r0::zero_bss(&mut _sbss, &mut _ebss);
r0::init_data(&mut _sdata, &mut _edata, &_sidata);

Expand Down

0 comments on commit 5300fc5

Please sign in to comment.