Skip to content

Commit 607b583

Browse files
Merge #27
27: Some steps towards 1.0 r=therealprof a=jonas-schievink Closes rust-embedded/cortex-m#186 Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
2 parents 37bcf7b + 3002f98 commit 607b583

File tree

2 files changed

+86
-46
lines changed

2 files changed

+86
-46
lines changed

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,22 @@ This project adheres to [Semantic Versioning](http://semver.org/).
55

66
## [Unreleased]
77

8+
### Added
9+
10+
- Added the `StaticResource` trait.
11+
12+
### Breaking Changes
13+
14+
- Use `CriticalSection<'cs>` everywhere instead of `&'cs CriticalSection`
15+
(this makes it a zero-sized type).
16+
- Removed the `const-fn` feature.
17+
- Removed the `Peripheral` wrapper type.
18+
819
## [v0.2.5] - 2019-08-29
920

1021
### Changed
1122

12-
- The `const-fn` feature is now stable
23+
- The `const-fn` feature is now stable.
1324

1425
## [v0.2.4] - 2018-10-30
1526

src/lib.rs

Lines changed: 74 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Abstractions common to bare metal systems
1+
//! Abstractions common to bare metal systems.
22
33
#![deny(missing_docs)]
44
#![deny(warnings)]
@@ -7,56 +7,37 @@
77
use core::cell::UnsafeCell;
88
use 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)]
4416
pub struct CriticalSection<'cs> {
4517
_0: PhantomData<&'cs ()>,
4618
}
4719

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

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

7960
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.
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)]
9379
const GH_6: () = ();
9480

95-
/// Interrupt number
81+
/// Interrupt number.
9682
pub 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

Comments
 (0)