From 840c32060bcf3127dab77c321c3c63ebffabcee9 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 25 Apr 2017 19:46:33 -0500 Subject: [PATCH] hide the unsafe Peripheral::new constructor `peripherals!` is the safe way to declare `Peripheral`s --- src/lib.rs | 103 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7edc89a57b..876b8dfb0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,8 +17,8 @@ //! - **Data race free memory sharing** through fine grained *non global* //! critical sections. //! - **Deadlock free execution** guaranteed at compile time. -//! - **Minimal overhead** as the scheduler has no software component / runtime; the -//! hardware does all the scheduling. +//! - **Minimal overhead** as the scheduler has no software component / runtime; +//! the hardware does all the scheduling. //! - Full support for all Cortex M3, M4 and M7 devices. M0(+) is also supported //! but the whole API is not available (due to missing hardware features). //! - The number of task priority levels is configurable at compile time through @@ -35,11 +35,11 @@ //! //! # Dependencies //! -//! - A device crate generated using [`svd2rust`] v0.6.x +//! - A device crate generated using [`svd2rust`] v0.7.x //! - A `start` lang time: Vanilla `main` must be supported in binary crates. //! You can use the [`cortex-m-rt`] crate to fulfill the requirement //! -//! [`svd2rust`]: https://docs.rs/svd2rust/0.6.1/svd2rust/ +//! [`svd2rust`]: https://docs.rs/svd2rust/0.7.0/svd2rust/ //! [`cortex-m-rt`]: https://docs.rs/cortex-m-rt/0.1.1/cortex_m_rt/ //! //! # Examples @@ -494,12 +494,15 @@ impl Resource> { unsafe impl Sync for Resource {} /// A hardware peripheral as a resource -pub struct Peripheral +/// +/// To assign a ceiling to a peripheral, use the +/// [`peripherals!`](./macro.peripherals.html) macro +pub struct Peripheral where P: 'static, { peripheral: cortex_m::peripheral::Peripheral

, - _ceiling: PhantomData, + _ceiling: PhantomData, } impl Peripheral> @@ -507,12 +510,8 @@ where CEILING: GreaterThanOrEqual, CEILING: LessThanOrEqual, { - /// Assigns a ceiling `C` to the `peripheral` - /// - /// # Safety - /// - /// You MUST not create two resources that point to the same peripheral - pub const unsafe fn new(peripheral: cortex_m::peripheral::Peripheral

,) + #[doc(hidden)] + pub const unsafe fn _new(peripheral: cortex_m::peripheral::Peripheral

,) -> Self { Peripheral { _ceiling: PhantomData, @@ -563,7 +562,7 @@ where /// /// The task won't run even if the underlying interrupt is raised pub fn disable(_task: fn(T, P)) - where +where T: Context + Nr, { // NOTE(safe) zero sized type @@ -705,7 +704,31 @@ pub unsafe trait GreaterThanOrEqual {} /// Do not implement this trait yourself. This is an implementation detail. pub unsafe trait LessThanOrEqual {} -/// Assigns ceilings to peripherals +/// A macro to assign ceilings to peripherals +/// +/// **NOTE** A peripheral instance, like RCC, can only be bound to a *single* +/// ceiling. Trying to use this macro to bind the same peripheral to several +/// ceiling will result in a compiler error. +/// +/// # Example +/// +/// ``` ignore +/// #[macro_use] +/// extern crate cortex_m_rtfm; +/// // device crate generated using `svd2rust` +/// extern crate stm32f30x; +/// +/// peripherals!(stm32f30x, { +/// GPIOA: Peripheral { +/// register_block: Gpioa, +/// ceiling: C1, +/// }, +/// RCC: Peripheral { +/// register_block: Rcc, +/// ceiling: C0, +/// }, +/// }); +/// ``` #[macro_export] macro_rules! peripherals { ($device:ident, { @@ -719,7 +742,7 @@ macro_rules! peripherals { #[no_mangle] static $PERIPHERAL: $crate::Peripheral<::$device::$RegisterBlock, $crate::$C> = - unsafe { $crate::Peripheral::new(::$device::$PERIPHERAL) }; + unsafe { $crate::Peripheral::_new(::$device::$PERIPHERAL) }; )+ } } @@ -729,13 +752,57 @@ macro_rules! peripherals { /// **NOTE** This macro will expand to a `main` function. /// /// Each `$task` is bound to an `$Interrupt` handler and has a priority `$P`. -/// `$enabled` indicates whether the task will be enabled before `idle` runs. +/// The minimum priority of a task is `P1`. `$enabled` indicates whether the +/// task will be enabled before `idle` runs. /// /// The `$Interrupt` handlers are defined in the `$device` crate. /// /// Apart from defining the listed `$tasks`, the `init` and `idle` functions -/// must be defined as well. `init` has type signature `fn(P0, &C16)`, and -/// `idle` has signature `fn(P0) -> !`. +/// must be defined as well. `init` has signature `fn(P0, &C16)`, and `idle` has +/// signature `fn(P0) -> !`. +/// +/// # Example +/// +/// ``` ignore +/// #[macro_use] +/// extern crate cortex_m_rtfm as rtfm; +/// // device crate generated using `svd2rust` +/// extern crate stm32f30x; +/// +/// use rtfm::{C16, P0, P1, P2}; +/// use stm32f30x::interrupt::{Exti0, Tim7}; +/// +/// tasks!(stm32f30x, { +/// periodic: Task { +/// interrupt: Tim7, +/// priority: P1, +/// enabled: true, +/// }, +/// button: Task { +/// interrupt: Exti0, +/// priority: P2, +/// enabled: true, +/// }, +/// }); +/// +/// fn init(priority: P0, ceiling: C16) { +/// // .. +/// } +/// +/// fn idle(priority: P0) -> ! { +/// // Sleep +/// loop { rtfm::wfi() } +/// } +/// +/// // NOTE signature must match the tasks! declaration +/// fn periodic(task: Tim7, priority: P1) { +/// // .. +/// } +/// +/// fn button(task: Exti0, priority: P2) { +/// // .. +/// } +/// ``` #[macro_export] macro_rules! tasks { ($device:ident, {