From 8659ecea720193ab7e6d760f5948635be5b940d4 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 25 Apr 2017 14:13:46 -0500 Subject: [PATCH] add a `peripherals!` macro for safe declaration of `Peripheral`s closes #12 --- src/lib.rs | 18 ++++++++ tests/cfail/peripherals-alias-1.rs | 68 +++++++++++++++++++++++++++ tests/cfail/peripherals-alias-2.rs | 74 ++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 tests/cfail/peripherals-alias-1.rs create mode 100644 tests/cfail/peripherals-alias-2.rs diff --git a/src/lib.rs b/src/lib.rs index 1d883301d1..0b1c1fe9ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -705,6 +705,24 @@ pub unsafe trait GreaterThanOrEqual {} /// Do not implement this trait yourself. This is an implementation detail. pub unsafe trait LessThanOrEqual {} +/// Assigns ceilings to peripherals +#[macro_export] +macro_rules! peripherals { + ($device:ident, { + $($PERIPHERAL:ident: Peripheral { + register_block: $RegisterBlock:ident, + ceiling: $C:ident, + },)+ + }) => { + $( + #[no_mangle] + static $PERIPHERAL: + $crate::Peripheral<::$device::$RegisterBlock, $crate::$C> = + unsafe { $crate::Peripheral::new(::$device::$PERIPHERAL) }; + )+ + } +} + /// A macro to declare tasks /// /// **NOTE** This macro will expand to a `main` function. diff --git a/tests/cfail/peripherals-alias-1.rs b/tests/cfail/peripherals-alias-1.rs new file mode 100644 index 0000000000..0dfe8d102d --- /dev/null +++ b/tests/cfail/peripherals-alias-1.rs @@ -0,0 +1,68 @@ +// error-pattern: has already been defined + +#![feature(used)] + +#[macro_use] +extern crate cortex_m_rtfm as rtfm; + +use rtfm::{C16, P0, P1}; +use device::interrupt::Exti0; + +peripherals!(device, { + GPIOA: Peripheral { + register_block: Gpioa, + ceiling: C1, + }, + // WRONG: peripheral alias + GPIOA: Peripheral { + register_block: Gpioa, + ceiling: C2, + }, +}); + +tasks!(device, {}); + +fn init(_: P0, _: &C16) {} + +fn idle(_: P0) -> ! { + loop {} +} + +fn j1(_task: Exti0, _prio: P1) {} + +// fake device crate +extern crate core; +extern crate cortex_m; + +mod device { + use cortex_m::peripheral::Peripheral; + + pub const GPIOA: Peripheral = unsafe { Peripheral::new(0x0) }; + + pub struct Gpioa; + + pub mod interrupt { + use cortex_m::interrupt::Nr; + + extern "C" fn default_handler(_: T) {} + + pub struct Handlers { + pub Exti0: extern "C" fn(Exti0), + } + + pub struct Exti0; + + pub enum Interrupt { + Exti0, + } + + unsafe impl Nr for Interrupt { + fn nr(&self) -> u8 { + 0 + } + } + + pub const DEFAULT_HANDLERS: Handlers = + Handlers { Exti0: default_handler }; + } +} diff --git a/tests/cfail/peripherals-alias-2.rs b/tests/cfail/peripherals-alias-2.rs new file mode 100644 index 0000000000..e649459c63 --- /dev/null +++ b/tests/cfail/peripherals-alias-2.rs @@ -0,0 +1,74 @@ +// error-pattern: symbol `GPIOA` is already defined + +#![feature(const_fn)] +#![feature(used)] + +#[macro_use] +extern crate cortex_m_rtfm as rtfm; + +use rtfm::{C16, P0, P1}; +use device::interrupt::Exti0; + +peripherals!(device, { + GPIOA: Peripheral { + register_block: Gpioa, + ceiling: C1, + }, +}); + +mod foo { + // WRONG: peripheral alias + peripherals!(device, { + GPIOA: Peripheral { + register_block: Gpioa, + ceiling: C2, + }, + }); +} + +tasks!(device, {}); + +fn init(_: P0, _: &C16) {} + +fn idle(_: P0) -> ! { + loop {} +} + +fn j1(_task: Exti0, _prio: P1) {} + +// fake device crate +extern crate core; +extern crate cortex_m; + +mod device { + use cortex_m::peripheral::Peripheral; + + pub const GPIOA: Peripheral = unsafe { Peripheral::new(0x0) }; + + pub struct Gpioa; + + pub mod interrupt { + use cortex_m::interrupt::Nr; + + extern "C" fn default_handler(_: T) {} + + pub struct Handlers { + pub Exti0: extern "C" fn(Exti0), + } + + pub struct Exti0; + + pub enum Interrupt { + Exti0, + } + + unsafe impl Nr for Interrupt { + fn nr(&self) -> u8 { + 0 + } + } + + pub const DEFAULT_HANDLERS: Handlers = + Handlers { Exti0: default_handler }; + } +}