1
- //! Abstractions common to bare metal systems
1
+ //! Abstractions common to bare metal systems.
2
2
3
3
#![ deny( missing_docs) ]
4
4
#![ deny( warnings) ]
7
7
use core:: cell:: UnsafeCell ;
8
8
use core:: marker:: PhantomData ;
9
9
10
- /// A peripheral
11
- #[ derive( Debug ) ]
12
- pub struct Peripheral < T >
13
- where
14
- T : ' static ,
15
- {
16
- address : * mut T ,
17
- }
18
-
19
- impl < T > Peripheral < T > {
20
- /// Creates a new peripheral
21
- ///
22
- /// `address` is the base address of the register block
23
- pub const unsafe fn new ( address : usize ) -> Self {
24
- Peripheral {
25
- address : address as * mut T ,
26
- }
27
- }
28
-
29
- /// Borrows the peripheral for the duration of a critical section
30
- pub fn borrow < ' cs > ( & self , _ctxt : CriticalSection < ' cs > ) -> & ' cs T {
31
- unsafe { & * self . get ( ) }
32
- }
33
-
34
- /// Returns a pointer to the register block
35
- pub fn get ( & self ) -> * mut T {
36
- self . address as * mut T
37
- }
38
- }
39
-
40
- /// Critical section token
10
+ /// Critical section token.
41
11
///
42
- /// Indicates that you are executing code within a critical section
12
+ /// An instance of this type indicates that the current core is executing code within a critical
13
+ /// section. This means that no interrupts must be enabled that could preempt the currently running
14
+ /// code.
43
15
#[ derive( Clone , Copy ) ]
44
16
pub struct CriticalSection < ' cs > {
45
17
_0 : PhantomData < & ' cs ( ) > ,
46
18
}
47
19
48
20
impl < ' cs > CriticalSection < ' cs > {
49
- /// Creates a critical section token
21
+ /// Creates a critical section token.
22
+ ///
23
+ /// This method is meant to be used to create safe abstractions rather than being directly used
24
+ /// in applications.
25
+ ///
26
+ /// # Safety
50
27
///
51
- /// This method is meant to be used to create safe abstractions rather than
52
- /// meant to be directly used in applications.
28
+ /// This must only be called when the current core is in a critical section. The caller must
29
+ /// ensure that the returned instance will not live beyond the end of the critical section.
30
+ ///
31
+ /// Note that the lifetime `'cs` of the returned instance is unconstrained. User code must not
32
+ /// be able to influence the lifetime picked for this type, since that might cause it to be
33
+ /// inferred to `'static`.
53
34
#[ inline( always) ]
54
35
pub unsafe fn new ( ) -> Self {
55
36
CriticalSection { _0 : PhantomData }
56
37
}
57
38
}
58
39
59
- /// A "mutex" based on critical sections
40
+ /// A "mutex" based on critical sections.
60
41
///
61
42
/// # Safety
62
43
///
@@ -68,7 +49,7 @@ pub struct Mutex<T> {
68
49
}
69
50
70
51
impl < T > Mutex < T > {
71
- /// Creates a new mutex
52
+ /// Creates a new mutex.
72
53
pub const fn new ( value : T ) -> Self {
73
54
Mutex {
74
55
inner : UnsafeCell :: new ( value) ,
@@ -77,12 +58,17 @@ impl<T> Mutex<T> {
77
58
}
78
59
79
60
impl < T > Mutex < T > {
80
- /// Borrows the data for the duration of the critical section
61
+ /// Borrows the data for the duration of the critical section.
81
62
pub fn borrow < ' cs > ( & ' cs self , _cs : CriticalSection < ' cs > ) -> & ' cs T {
82
63
unsafe { & * self . inner . get ( ) }
83
64
}
84
65
}
85
66
67
+ // NOTE A `Mutex` can be used as a channel so the protected data must be `Send`
68
+ // to prevent sending non-Sendable stuff (e.g. access tokens) across different
69
+ // execution contexts (e.g. interrupts)
70
+ unsafe impl < T > Sync for Mutex < T > where T : Send { }
71
+
86
72
/// ``` compile_fail
87
73
/// fn bad(cs: bare_metal::CriticalSection) -> &u32 {
88
74
/// let x = bare_metal::Mutex::new(42u32);
@@ -92,13 +78,56 @@ impl<T> Mutex<T> {
92
78
#[ allow( dead_code) ]
93
79
const GH_6 : ( ) = ( ) ;
94
80
95
- /// Interrupt number
81
+ /// Interrupt number.
96
82
pub unsafe trait Nr {
97
- /// Returns the number associated with an interrupt
83
+ /// Returns the number associated with an interrupt.
98
84
fn nr ( & self ) -> u8 ;
99
85
}
100
86
101
- // NOTE A `Mutex` can be used as a channel so the protected data must be `Send`
102
- // to prevent sending non-Sendable stuff (e.g. access tokens) across different
103
- // execution contexts (e.g. interrupts)
104
- unsafe impl < T > Sync for Mutex < T > where T : Send { }
87
+ /// Trait for static (singleton) resources with managed ownership.
88
+ ///
89
+ /// This trait allows application code and libraries to take ownership of resources that exist once
90
+ /// on every core, or once on the entire system.
91
+ ///
92
+ /// # Safety
93
+ ///
94
+ /// In order to safely implement this trait, the implementor must ensure that:
95
+ /// - A call to `take()` or `steal()` atomically ensures that no further call to `take()` will
96
+ /// succeed. This is commonly accomplished by using a static `AtomicBool` variable and a
97
+ /// compare-and-swap operation or a critical section.
98
+ /// - It is impossible to link multiple crates containing the synchronization state together. This
99
+ /// is usually accomplished by defining a well-known [`links = "..."`][links] key in the
100
+ /// `Cargo.toml`.
101
+ ///
102
+ /// [links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
103
+ pub unsafe trait StaticResource : Sized {
104
+ /// Obtains ownership of this resource singleton and makes it unavailable to future callers of
105
+ /// `take()`.
106
+ ///
107
+ /// If `take()` or `steal()` have been called before, this returns `None`.
108
+ fn take ( ) -> Option < Self > ;
109
+
110
+ /// Obtains an instance of this resource and makes all future calls to `take()` return `None`.
111
+ ///
112
+ /// This will not check if `take()` or `steal()` have already been called before. It is the
113
+ /// caller's responsibility to use the returned instance in a safe way that does not conflict
114
+ /// with other instances.
115
+ ///
116
+ /// This function is intended to be used when it is statically known that the resource is still
117
+ /// available (for example, in generated code that runs immediately after reset). It generally
118
+ /// has lower cost than `take().unwrap()`.
119
+ unsafe fn steal ( ) -> Self ;
120
+
121
+ /// Unsafely obtains an instance of this resource.
122
+ ///
123
+ /// This will not check if `take()` or `steal()` have already been called before. It is the
124
+ /// caller's responsibility to use the returned instance in a safe way that does not conflict
125
+ /// with other instances.
126
+ ///
127
+ /// Contrary to `steal()`, `conjure()` will *not* make future calls to `take()` return `None`.
128
+ ///
129
+ /// This function can be used to perform operations on a resource, ignoring any current
130
+ /// ownership of the resource. The safety of this depends on the specific resource, and on the
131
+ /// operations performed.
132
+ unsafe fn conjure ( ) -> Self ;
133
+ }
0 commit comments