From 5781e9391fe3d7d3dabec620cb782d38f5f9cb9e Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Fri, 10 May 2019 11:50:53 -0400 Subject: Update to 0.2.0: Add HandlerArray type. * Create HandlerArray as a safe wrapper around Handler. * Add Cargo features for HandlerArray size. * Move Handler into sub-module. * Add CriticalSection sub-module for architecture dependent support of interrupt-free contexts. * Add build rules to pull in cortex-m support for CriticalSection automatically. --- src/cs/cortex.rs | 20 ++++++++++++++++++++ src/cs/dummy.rs | 18 ++++++++++++++++++ src/cs/mod.rs | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 src/cs/cortex.rs create mode 100644 src/cs/dummy.rs create mode 100644 src/cs/mod.rs (limited to 'src/cs') diff --git a/src/cs/cortex.rs b/src/cs/cortex.rs new file mode 100644 index 0000000..cc97a12 --- /dev/null +++ b/src/cs/cortex.rs @@ -0,0 +1,20 @@ +use super::CriticalSection; + +use cortex_m::interrupt; + +pub struct Locker {} + +impl Locker { + pub const fn new() -> Self { + Self {} + } +} + +impl CriticalSection for Locker { + fn with_lock(&self, f: F) -> R + where + F: FnOnce() -> R, + { + interrupt::free(|_cs| f()) + } +} diff --git a/src/cs/dummy.rs b/src/cs/dummy.rs new file mode 100644 index 0000000..86f4e90 --- /dev/null +++ b/src/cs/dummy.rs @@ -0,0 +1,18 @@ +use super::CriticalSection; + +pub struct Locker {} + +impl Locker { + pub const fn new() -> Self { + Self {} + } +} + +impl CriticalSection for Locker { + fn with_lock(&self, f: F) -> R + where + F: FnOnce() -> R, + { + f() + } +} diff --git a/src/cs/mod.rs b/src/cs/mod.rs new file mode 100644 index 0000000..8f97b6e --- /dev/null +++ b/src/cs/mod.rs @@ -0,0 +1,38 @@ +//! Critical Section support. +//! +//! Types that implement the `CriticalSection` trait can be used to +//! create critical sections to prevent data races between interrupt +//! and non-interrupt contexts. +//! +//! # Note +//! +//! Critical sections are only acquired for updating a +//! `HandlerTable`'s entries. They are *not* used when calling into a +//! closure. This is because the expected implementation of critical +//! sections turns off interrupts entirely. Given that interrupts are +//! off, it is impossible to call an ISR, and thus no data race can +//! occur. Additionally, because critcal sections are only enforced on +//! updates, deadlock is impossible between updating a `HandlerTable` +//! entry and calling into it. +//! +//! However, if you are going to implement your own `CriticalSection`, +//! you need to be aware of this limitation and its rationale to avoid +//! getting into trouble. + +/// Generic trait which supplies the ability to create a critical +/// section. +pub trait CriticalSection { + /// Execute `f` within a critical section. + fn with_lock(&self, f: F) -> R + where + F: FnOnce() -> R; +} + +#[cfg_attr(any(all(target_arch = "arm", target_os = "none")), path = "cortex.rs")] +#[cfg_attr( + not(any(all(target_arch = "arm", target_os = "none"))), + path = "dummy.rs" +)] +mod csimpl; + +pub use csimpl::Locker; -- cgit v1.2.3