| 1 | //! Abstractions common to bare metal systems |
| 2 | |
| 3 | #![deny (missing_docs)] |
| 4 | #![deny (warnings)] |
| 5 | #![no_std ] |
| 6 | |
| 7 | use core::cell::UnsafeCell; |
| 8 | |
| 9 | /// A peripheral |
| 10 | #[derive (Debug)] |
| 11 | pub struct Peripheral<T> |
| 12 | where |
| 13 | T: 'static, |
| 14 | { |
| 15 | address: *mut T, |
| 16 | } |
| 17 | |
| 18 | impl<T> Peripheral<T> { |
| 19 | /// Creates a new peripheral |
| 20 | /// |
| 21 | /// `address` is the base address of the register block |
| 22 | pub const unsafe fn new(address: usize) -> Self { |
| 23 | Peripheral { |
| 24 | address: address as *mut T, |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | /// Borrows the peripheral for the duration of a critical section |
| 29 | pub fn borrow<'cs>(&self, _ctxt: &'cs CriticalSection) -> &'cs T { |
| 30 | unsafe { &*self.get() } |
| 31 | } |
| 32 | |
| 33 | /// Returns a pointer to the register block |
| 34 | pub fn get(&self) -> *mut T { |
| 35 | self.address as *mut T |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | /// Critical section token |
| 40 | /// |
| 41 | /// Indicates that you are executing code within a critical section |
| 42 | pub struct CriticalSection { |
| 43 | _0: (), |
| 44 | } |
| 45 | |
| 46 | impl CriticalSection { |
| 47 | /// Creates a critical section token |
| 48 | /// |
| 49 | /// This method is meant to be used to create safe abstractions rather than |
| 50 | /// meant to be directly used in applications. |
| 51 | pub unsafe fn new() -> Self { |
| 52 | CriticalSection { _0: () } |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | /// A "mutex" based on critical sections |
| 57 | /// |
| 58 | /// # Safety |
| 59 | /// |
| 60 | /// **This Mutex is only safe on single-core systems.** |
| 61 | /// |
| 62 | /// On multi-core systems, a `CriticalSection` **is not sufficient** to ensure exclusive access. |
| 63 | pub struct Mutex<T> { |
| 64 | inner: UnsafeCell<T>, |
| 65 | } |
| 66 | |
| 67 | impl<T> Mutex<T> { |
| 68 | /// Creates a new mutex |
| 69 | pub const fn new(value: T) -> Self { |
| 70 | Mutex { |
| 71 | inner: UnsafeCell::new(value), |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | impl<T> Mutex<T> { |
| 77 | /// Borrows the data for the duration of the critical section |
| 78 | pub fn borrow<'cs>(&'cs self, _cs: &'cs CriticalSection) -> &'cs T { |
| 79 | unsafe { &*self.inner.get() } |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | /// ``` compile_fail |
| 84 | /// fn bad(cs: &bare_metal::CriticalSection) -> &u32 { |
| 85 | /// let x = bare_metal::Mutex::new(42u32); |
| 86 | /// x.borrow(cs) |
| 87 | /// } |
| 88 | /// ``` |
| 89 | #[allow (dead_code)] |
| 90 | const GH_6: () = (); |
| 91 | |
| 92 | /// Interrupt number |
| 93 | pub unsafe trait Nr { |
| 94 | /// Returns the number associated with an interrupt |
| 95 | fn nr(&self) -> u8; |
| 96 | } |
| 97 | |
| 98 | // NOTE A `Mutex` can be used as a channel so the protected data must be `Send` |
| 99 | // to prevent sending non-Sendable stuff (e.g. access tokens) across different |
| 100 | // execution contexts (e.g. interrupts) |
| 101 | unsafe impl<T> Sync for Mutex<T> where T: Send {} |
| 102 | |