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}