bare_metal/
lib.rs

1//! Abstractions common to bare metal systems
2
3#![deny(missing_docs)]
4#![deny(warnings)]
5#![no_std]
6
7use core::cell::UnsafeCell;
8
9/// A peripheral
10#[derive(Debug)]
11pub struct Peripheral<T>
12where
13    T: 'static,
14{
15    address: *mut T,
16}
17
18impl<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
42pub struct CriticalSection {
43    _0: (),
44}
45
46impl 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.
63pub struct Mutex<T> {
64    inner: UnsafeCell<T>,
65}
66
67impl<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
76impl<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)]
90const GH_6: () = ();
91
92/// Interrupt number
93pub 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)
101unsafe impl<T> Sync for Mutex<T> where T: Send {}