kernel/utils/vcell.rs
1//! from `vcell` crate
2//! Copyright (c) 2017 Jorge Aparicio
3//!
4//! Permission is hereby granted, free of charge, to any
5//! person obtaining a copy of this software and associated
6//! documentation files (the "Software"), to deal in the
7//! Software without restriction, including without
8//! limitation the rights to use, copy, modify, merge,
9//! publish, distribute, sublicense, and/or sell copies of
10//! the Software, and to permit persons to whom the Software
11//! is furnished to do so, subject to the following
12//! conditions:
13//!
14//! The above copyright notice and this permission notice
15//! shall be included in all copies or substantial portions
16//! of the Software.
17//!
18//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
19//! ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
20//! TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
21//! PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
22//! SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23//! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24//! OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
25//! IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26//! DEALINGS IN THE SOFTWARE.
27//!
28//! ---
29//!
30//! AND from `volatile-register` crate
31//! Copyright (c) 2016 Jorge Aparicio
32//!
33//! Permission is hereby granted, free of charge, to any
34//! person obtaining a copy of this software and associated
35//! documentation files (the "Software"), to deal in the
36//! Software without restriction, including without
37//! limitation the rights to use, copy, modify, merge,
38//! publish, distribute, sublicense, and/or sell copies of
39//! the Software, and to permit persons to whom the Software
40//! is furnished to do so, subject to the following
41//! conditions:
42//!
43//! The above copyright notice and this permission notice
44//! shall be included in all copies or substantial portions
45//! of the Software.
46//!
47//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
48//! ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
49//! TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
50//! PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
51//! SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
52//! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
53//! OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
54//! IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
55//! DEALINGS IN THE SOFTWARE.
56
57#![allow(dead_code)]
58
59use core::cell::UnsafeCell;
60use core::ptr;
61
62/// Just like [`Cell`] but with [volatile] read / write operations
63///
64/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html
65/// [volatile]: https://doc.rust-lang.org/std/ptr/fn.read_volatile.html
66#[repr(transparent)]
67struct VCell<T> {
68 value: UnsafeCell<T>,
69}
70
71impl<T> VCell<T> {
72 /// Creates a new `VolatileCell` containing the given value
73 pub const fn new(value: T) -> Self {
74 VCell {
75 value: UnsafeCell::new(value),
76 }
77 }
78
79 /// Returns a copy of the contained value
80 #[inline(always)]
81 pub fn get(&self) -> T
82 where
83 T: Copy,
84 {
85 unsafe { ptr::read_volatile(self.value.get()) }
86 }
87
88 /// Sets the contained value
89 #[inline(always)]
90 pub fn set(&self, value: T)
91 where
92 T: Copy,
93 {
94 unsafe { ptr::write_volatile(self.value.get(), value) }
95 }
96
97 /// Returns a raw pointer to the underlying data in the cell
98 #[inline(always)]
99 pub fn as_ptr(&self) -> *mut T {
100 self.value.get()
101 }
102}
103
104// NOTE implicit because of `UnsafeCell`
105// unsafe impl<T> !Sync for VolatileCell<T> {}
106
107/// Read-Only register
108#[repr(transparent)]
109pub struct RO<T>
110where
111 T: Copy,
112{
113 register: VCell<T>,
114}
115
116impl<T> RO<T>
117where
118 T: Copy,
119{
120 /// Reads the value of the register
121 #[inline(always)]
122 pub fn read(&self) -> T {
123 self.register.get()
124 }
125}
126
127/// Read-Write register
128#[repr(transparent)]
129pub struct RW<T>
130where
131 T: Copy,
132{
133 register: VCell<T>,
134}
135
136impl<T> RW<T>
137where
138 T: Copy,
139{
140 /// Performs a read-modify-write operation
141 ///
142 /// NOTE: `unsafe` because writes to a register are side effectful
143 #[inline(always)]
144 pub unsafe fn modify<F>(&self, f: F)
145 where
146 F: FnOnce(T) -> T,
147 {
148 self.register.set(f(self.register.get()));
149 }
150
151 /// Reads the value of the register
152 #[inline(always)]
153 pub fn read(&self) -> T {
154 self.register.get()
155 }
156
157 /// Writes a `value` into the register
158 ///
159 /// NOTE: `unsafe` because writes to a register are side effectful
160 #[inline(always)]
161 pub unsafe fn write(&self, value: T) {
162 self.register.set(value)
163 }
164}
165
166/// Write-Only register
167#[repr(transparent)]
168pub struct WO<T>
169where
170 T: Copy,
171{
172 register: VCell<T>,
173}
174
175impl<T> WO<T>
176where
177 T: Copy,
178{
179 /// Writes `value` into the register
180 ///
181 /// NOTE: `unsafe` because writes to a register are side effectful
182 #[inline(always)]
183 pub unsafe fn write(&self, value: T) {
184 self.register.set(value)
185 }
186}