1
1
#![ cfg_attr( feature = "const_fn" , feature( const_fn) ) ]
2
2
3
- //! Provides wrapper types `Volatile`, `ReadOnly`, `WriteOnly`, `ReadWrite`, which wrap any copy-able type and allows for
4
- //! volatile memory access to wrapped value. Volatile memory accesses are never optimized away by
5
- //! the compiler, and are useful in many low-level systems programming and concurrent contexts.
3
+ //! Provides the wrapper type `Volatile`, which wraps a reference to any copy-able type and allows
4
+ //! for volatile memory access to wrapped value. Volatile memory accesses are never optimized away
5
+ //! by the compiler, and are useful in many low-level systems programming and concurrent contexts.
6
6
//!
7
7
//! The wrapper types *do not* enforce any atomicity guarantees; to also get atomicity, consider
8
8
//! looking at the `Atomic` wrapper type found in `libcore` or `libstd`.
9
9
//!
10
10
//! These wrappers do not depend on the standard library and never panic.
11
- //!
12
- //! # Dealing with Volatile Pointers
13
- //!
14
- //! Frequently, one may have to deal with volatile pointers, eg, writes to specific memory
15
- //! locations. The canonical way to solve this is to cast the pointer to a volatile wrapper
16
- //! directly, eg:
17
- //!
18
- //! ```rust
19
- //! use volatile::Volatile;
20
- //!
21
- //! let mut_ptr = 0xFEE00000 as *mut u32;
22
- //!
23
- //! let volatile_ptr = mut_ptr as *mut Volatile<u32>;
24
- //! ```
25
- //!
26
- //! and then perform operations on the pointer as usual in a volatile way. This method works as all
27
- //! of the volatile wrapper types are the same size as their contained values.
11
+
28
12
#![ no_std]
29
13
30
14
pub use crate :: access:: { ReadWrite , Readable , Writable } ;
@@ -37,11 +21,14 @@ use core::{
37
21
38
22
mod access;
39
23
40
- /// A wrapper type around a volatile variable, which allows for volatile reads and writes
41
- /// to the contained value. The stored type needs to be `Copy`, as volatile reads and writes
42
- /// take and return copies of the value.
24
+ /// A wrapper type around a reference to a volatile variable.
25
+ ///
26
+ /// Allows volatile reads and writes on the referenced value. The referenced value needs to
27
+ /// be `Copy`, as volatile reads and writes take and return copies of the value.
43
28
///
44
29
/// The size of this struct is the same as the size of the contained type.
30
+ ///
31
+ /// TODO: read/write permissions
45
32
#[ derive( Debug , Default , Clone ) ]
46
33
#[ repr( transparent) ]
47
34
pub struct Volatile < T , A = ReadWrite > {
@@ -50,17 +37,18 @@ pub struct Volatile<T, A = ReadWrite> {
50
37
}
51
38
52
39
impl < T > Volatile < T > {
53
- /// Construct a new volatile instance wrapping the given value.
40
+ /// Construct a new volatile instance wrapping the given value reference.
41
+ ///
42
+ /// ## Example
54
43
///
55
44
/// ```rust
56
45
/// use volatile::Volatile;
57
46
///
58
- /// let value = Volatile::new(0u32);
59
- /// ```
60
- ///
61
- /// # Panics
47
+ /// let value = 0u32;
62
48
///
63
- /// This method never panics.
49
+ /// let volatile = Volatile::new(&value);
50
+ /// assert_eq!(volatile.read(), 0);
51
+ /// ```
64
52
pub const fn new ( value : T ) -> Volatile < T > {
65
53
Volatile {
66
54
value,
@@ -70,22 +58,22 @@ impl<T> Volatile<T> {
70
58
}
71
59
72
60
impl < T : Copy , A > Volatile < & T , A > {
73
- /// Performs a volatile read of the contained value, returning a copy
74
- /// of the read value. Volatile reads are guaranteed not to be optimized
61
+ /// Performs a volatile read of the contained value.
62
+ ///
63
+ /// Returns a copy of the read value. Volatile reads are guaranteed not to be optimized
75
64
/// away by the compiler, but by themselves do not have atomic ordering
76
65
/// guarantees. To also get atomicity, consider looking at the `Atomic` wrapper type.
77
66
///
67
+ /// ## Example
68
+ ///
78
69
/// ```rust
79
70
/// use volatile::Volatile;
80
71
///
81
- /// let value = Volatile::new(42u32);
72
+ /// let value = 42;
73
+ /// let volatile = Volatile::new(&value);
82
74
///
83
- /// assert_eq!(value .read(), 42u32 );
75
+ /// assert_eq!(volatile .read(), 42 );
84
76
/// ```
85
- ///
86
- /// # Panics
87
- ///
88
- /// This method never panics.
89
77
pub fn read ( & self ) -> T
90
78
where
91
79
A : Readable ,
@@ -96,22 +84,22 @@ impl<T: Copy, A> Volatile<&T, A> {
96
84
}
97
85
98
86
impl < T : Copy , A > Volatile < & mut T , A > {
99
- /// Performs a volatile read of the contained value, returning a copy
100
- /// of the read value. Volatile reads are guaranteed not to be optimized
87
+ /// Performs a volatile read of the contained value.
88
+ ///
89
+ /// Returns a copy of the read value. Volatile reads are guaranteed not to be optimized
101
90
/// away by the compiler, but by themselves do not have atomic ordering
102
91
/// guarantees. To also get atomicity, consider looking at the `Atomic` wrapper type.
103
92
///
93
+ /// ## Example
94
+ ///
104
95
/// ```rust
105
96
/// use volatile::Volatile;
106
97
///
107
- /// let value = Volatile::new(42u32);
98
+ /// let mut value = 42;
99
+ /// let volatile = Volatile::new(&mut value);
108
100
///
109
- /// assert_eq!(value .read(), 42u32 );
101
+ /// assert_eq!(volatile .read(), 42 );
110
102
/// ```
111
- ///
112
- /// # Panics
113
- ///
114
- /// This method never panics.
115
103
pub fn read ( & self ) -> T
116
104
where
117
105
A : Readable ,
@@ -120,24 +108,23 @@ impl<T: Copy, A> Volatile<&mut T, A> {
120
108
unsafe { ptr:: read_volatile ( self . value ) }
121
109
}
122
110
123
- /// Performs a volatile write, setting the contained value to the given value `value`. Volatile
124
- /// writes are guaranteed to not be optimized away by the compiler, but by themselves do not
125
- /// have atomic ordering guarantees. To also get atomicity, consider looking at the `Atomic`
126
- /// wrapper type.
111
+ /// Performs a volatile write, setting the contained value to the given `value`.
112
+ ///
113
+ /// Volatile writes are guaranteed to not be optimized away by the compiler, but by
114
+ /// themselves do not have atomic ordering guarantees. To also get atomicity, consider
115
+ /// looking at the `Atomic` wrapper type.
116
+ ///
117
+ /// ## Example
127
118
///
128
119
/// ```rust
129
120
/// use volatile::Volatile;
130
121
///
131
- /// let mut value = Volatile::new(0u32);
122
+ /// let mut value = 42;
123
+ /// let mut volatile = Volatile::new(&mut value);
124
+ /// volatile.write(50);
132
125
///
133
- /// value.write(42u32);
134
- ///
135
- /// assert_eq!(value.read(), 42u32);
126
+ /// assert_eq!(volatile.read(), 50);
136
127
/// ```
137
- ///
138
- /// # Panics
139
- ///
140
- /// This method never panics.
141
128
pub fn write ( & mut self , value : T )
142
129
where
143
130
A : Writable ,
@@ -146,23 +133,21 @@ impl<T: Copy, A> Volatile<&mut T, A> {
146
133
unsafe { ptr:: write_volatile ( self . value , value) } ;
147
134
}
148
135
136
+ /// Updates the contained value using the given closure and volatile instructions.
137
+ ///
149
138
/// Performs a volatile read of the contained value, passes a mutable reference to it to the
150
139
/// function `f`, and then performs a volatile write of the (potentially updated) value back to
151
140
/// the contained value.
152
141
///
153
142
/// ```rust
154
143
/// use volatile::Volatile;
155
144
///
156
- /// let mut value = Volatile::new(21u32);
145
+ /// let mut value = 42;
146
+ /// let mut volatile = Volatile::new(&mut value);
147
+ /// volatile.update(|val| *val += 1);
157
148
///
158
- /// value.update(|val_ref| *val_ref *= 2);
159
- ///
160
- /// assert_eq!(value.read(), 42u32);
149
+ /// assert_eq!(volatile.read(), 43);
161
150
/// ```
162
- ///
163
- /// # Panics
164
- ///
165
- /// Ths method never panics.
166
151
pub fn update < F > ( & mut self , f : F )
167
152
where
168
153
F : FnOnce ( & mut T ) ,
0 commit comments