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