1- //! Abstractions common to bare metal systems
1+ //! Abstractions common to bare metal systems.
22
33#![ deny( missing_docs) ]
44#![ deny( warnings) ]
77use core:: cell:: UnsafeCell ;
88use core:: marker:: PhantomData ;
99
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.
4111///
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.
4315#[ derive( Clone , Copy ) ]
4416pub struct CriticalSection < ' cs > {
4517 _0 : PhantomData < & ' cs ( ) > ,
4618}
4719
4820impl < ' 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
5027 ///
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`.
5334 #[ inline( always) ]
5435 pub unsafe fn new ( ) -> Self {
5536 CriticalSection { _0 : PhantomData }
5637 }
5738}
5839
59- /// A "mutex" based on critical sections
40+ /// A "mutex" based on critical sections.
6041///
6142/// # Safety
6243///
@@ -68,7 +49,7 @@ pub struct Mutex<T> {
6849}
6950
7051impl < T > Mutex < T > {
71- /// Creates a new mutex
52+ /// Creates a new mutex.
7253 pub const fn new ( value : T ) -> Self {
7354 Mutex {
7455 inner : UnsafeCell :: new ( value) ,
@@ -77,12 +58,17 @@ impl<T> Mutex<T> {
7758}
7859
7960impl < 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.
8162 pub fn borrow < ' cs > ( & ' cs self , _cs : CriticalSection < ' cs > ) -> & ' cs T {
8263 unsafe { & * self . inner . get ( ) }
8364 }
8465}
8566
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+
8672/// ``` compile_fail
8773/// fn bad(cs: bare_metal::CriticalSection) -> &u32 {
8874/// let x = bare_metal::Mutex::new(42u32);
@@ -92,13 +78,56 @@ impl<T> Mutex<T> {
9278#[ allow( dead_code) ]
9379const GH_6 : ( ) = ( ) ;
9480
95- /// Interrupt number
81+ /// Interrupt number.
9682pub unsafe trait Nr {
97- /// Returns the number associated with an interrupt
83+ /// Returns the number associated with an interrupt.
9884 fn nr ( & self ) -> u8 ;
9985}
10086
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