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 | |