Skip to content

Commit dbb4b83

Browse files
committed
tock-register-interface: move LocalRegisterCopy to own module
Move LocalRegisterCopy to its own module and rexport it through the top-level crate exports. LocalRegisterCopy is distinct from actual register types, as it only represents a copy of any other register type, whether implemented in this crate or outside of it. This is in contrast to an InMemoryRegister, which represents an actual register stored in memory. This is further emphasized by the fact that LocalRegisterCopy does not implement the tock-registers interface traits (e.g. Readable, Writeable) and uses different method signatures for manipulating the contained values, and implements the Copy trait. Hence, this moves it to its own module and reexports it with the top-level crate exports, as it is of importance regardless of whether the included register types are used. Signed-off-by: Leon Schuermann <leon@is.currently.online>
1 parent 12f4b79 commit dbb4b83

File tree

4 files changed

+135
-122
lines changed

4 files changed

+135
-122
lines changed

libraries/tock-register-interface/src/interfaces.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,7 @@
148148
//! ```
149149
150150
use crate::fields::{Field, FieldValue, TryFromValue};
151-
use crate::registers::LocalRegisterCopy;
152-
use crate::{IntLike, RegisterLongName};
151+
use crate::{IntLike, LocalRegisterCopy, RegisterLongName};
153152

154153
/// Readable register
155154
///

libraries/tock-register-interface/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ pub mod interfaces;
1010
pub mod macros;
1111
pub mod registers;
1212

13+
mod local_register;
14+
pub use local_register::LocalRegisterCopy;
15+
1316
use core::ops::{BitAnd, BitOr, BitOrAssign, Not, Shl, Shr};
1417

1518
/// Trait representing the base type of registers.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//! Module containing the [`LocalRegisterCopy`] type. Please refer to
2+
//! its documentation.
3+
4+
use core::fmt;
5+
use core::marker::PhantomData;
6+
7+
use crate::fields::{Field, FieldValue, TryFromValue};
8+
use crate::{IntLike, RegisterLongName};
9+
10+
/// A read-write copy of register contents.
11+
///
12+
/// This behaves very similarly to a read-write register, but instead of doing a
13+
/// volatile read to MMIO to get the value for each function call, a copy of the
14+
/// register contents are stored locally in memory. This allows a peripheral
15+
/// to do a single read on a register, and then check which bits are set without
16+
/// having to do a full MMIO read each time. It also allows the value of the
17+
/// register to be "cached" in case the peripheral driver needs to clear the
18+
/// register in hardware yet still be able to check the bits.
19+
/// You can write to a local register, which will modify the stored value, but
20+
/// will not modify any hardware because it operates only on local copy.
21+
///
22+
/// This type does not implement the
23+
/// [`Readable`](crate::interfaces::Readable) and
24+
/// [`Writeable`](crate::interfaces::Writeable) traits because it
25+
/// requires a mutable reference to modify the contained value. It
26+
/// still mirrors the interface which would be exposed by a type
27+
/// implementing [`Readable`](crate::interfaces::Readable),
28+
/// [`Writeable`](crate::interfaces::Writeable) and
29+
/// [`ReadWriteable`](crate::interfaces::ReadWriteable).
30+
#[derive(Copy, Clone)]
31+
pub struct LocalRegisterCopy<T: IntLike, R: RegisterLongName = ()> {
32+
value: T,
33+
associated_register: PhantomData<R>,
34+
}
35+
36+
impl<T: IntLike, R: RegisterLongName> LocalRegisterCopy<T, R> {
37+
pub const fn new(value: T) -> Self {
38+
LocalRegisterCopy {
39+
value: value,
40+
associated_register: PhantomData,
41+
}
42+
}
43+
44+
/// Get the raw register value
45+
#[inline]
46+
pub fn get(&self) -> T {
47+
self.value
48+
}
49+
50+
/// Set the raw register value
51+
#[inline]
52+
pub fn set(&mut self, value: T) {
53+
self.value = value;
54+
}
55+
56+
/// Read the value of the given field
57+
#[inline]
58+
pub fn read(&self, field: Field<T, R>) -> T {
59+
field.read(self.get())
60+
}
61+
62+
/// Read value of the given field as an enum member
63+
#[inline]
64+
pub fn read_as_enum<E: TryFromValue<T, EnumType = E>>(&self, field: Field<T, R>) -> Option<E> {
65+
field.read_as_enum(self.get())
66+
}
67+
68+
/// Write the value of one or more fields, overwriting the other fields with zero
69+
#[inline]
70+
pub fn write(&mut self, field: FieldValue<T, R>) {
71+
self.set(field.value);
72+
}
73+
74+
/// Write the value of one or more fields, leaving the other fields unchanged
75+
#[inline]
76+
pub fn modify(&mut self, field: FieldValue<T, R>) {
77+
self.set(field.modify(self.get()));
78+
}
79+
80+
/// Check if one or more bits in a field are set
81+
#[inline]
82+
pub fn is_set(&self, field: Field<T, R>) -> bool {
83+
field.is_set(self.get())
84+
}
85+
86+
/// Check if any specified parts of a field match
87+
#[inline]
88+
pub fn matches_any(&self, field: FieldValue<T, R>) -> bool {
89+
field.matches_any(self.get())
90+
}
91+
92+
/// Check if all specified parts of a field match
93+
#[inline]
94+
pub fn matches_all(&self, field: FieldValue<T, R>) -> bool {
95+
field.matches_all(self.get())
96+
}
97+
98+
/// Do a bitwise AND operation of the stored value and the passed in value
99+
/// and return a new LocalRegisterCopy.
100+
#[inline]
101+
pub fn bitand(&self, rhs: T) -> LocalRegisterCopy<T, R> {
102+
LocalRegisterCopy::new(self.value & rhs)
103+
}
104+
}
105+
106+
impl<T: IntLike + fmt::Debug, R: RegisterLongName> fmt::Debug for LocalRegisterCopy<T, R> {
107+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108+
write!(f, "{:?}", self.value)
109+
}
110+
}
111+
112+
// Helper macro to implement From<LocalRegisterCopy<T: IntLike>, R>>
113+
// for <T: IntLike>
114+
macro_rules! From_impl_for {
115+
($type:ty) => {
116+
impl<R: RegisterLongName> From<LocalRegisterCopy<$type, R>> for $type {
117+
fn from(r: LocalRegisterCopy<$type, R>) -> $type {
118+
r.value
119+
}
120+
}
121+
};
122+
}
123+
124+
From_impl_for!(u8);
125+
From_impl_for!(u16);
126+
From_impl_for!(u32);
127+
From_impl_for!(u64);
128+
From_impl_for!(u128);
129+
From_impl_for!(usize);

libraries/tock-register-interface/src/registers.rs

Lines changed: 2 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,8 @@
5454
//! - Shane Leonard <shanel@stanford.edu>
5555
5656
use core::cell::UnsafeCell;
57-
use core::fmt;
5857
use core::marker::PhantomData;
5958

60-
use crate::fields::{Field, FieldValue, TryFromValue};
6159
use crate::interfaces::{Readable, Writeable};
6260
use crate::{IntLike, RegisterLongName};
6361

@@ -219,122 +217,6 @@ impl<T: IntLike, R: RegisterLongName> Writeable for InMemoryRegister<T, R> {
219217
}
220218
}
221219

222-
/// A read-write copy of register contents.
223-
///
224-
/// This behaves very similarly to a read-write register, but instead of doing a
225-
/// volatile read to MMIO to get the value for each function call, a copy of the
226-
/// register contents are stored locally in memory. This allows a peripheral
227-
/// to do a single read on a register, and then check which bits are set without
228-
/// having to do a full MMIO read each time. It also allows the value of the
229-
/// register to be "cached" in case the peripheral driver needs to clear the
230-
/// register in hardware yet still be able to check the bits.
231-
/// You can write to a local register, which will modify the stored value, but
232-
/// will not modify any hardware because it operates only on local copy.
233-
///
234-
/// This type does not implement the [`Readable`] and [`Writeable`]
235-
/// traits because it requires a mutable reference to modify the
236-
/// contained value. It still mirrors the interface which would be
237-
/// exposed by a type implementing [`Readable`], [`Writeable`] and
238-
/// [`ReadWriteable`](crate::interfaces::ReadWriteable).
239-
#[derive(Copy, Clone)]
240-
pub struct LocalRegisterCopy<T: IntLike, R: RegisterLongName = ()> {
241-
value: T,
242-
associated_register: PhantomData<R>,
243-
}
244-
245-
impl<T: IntLike, R: RegisterLongName> LocalRegisterCopy<T, R> {
246-
pub const fn new(value: T) -> Self {
247-
LocalRegisterCopy {
248-
value: value,
249-
associated_register: PhantomData,
250-
}
251-
}
252-
253-
/// Get the raw register value
254-
#[inline]
255-
pub fn get(&self) -> T {
256-
self.value
257-
}
258-
259-
/// Set the raw register value
260-
#[inline]
261-
pub fn set(&mut self, value: T) {
262-
self.value = value;
263-
}
264-
265-
/// Read the value of the given field
266-
#[inline]
267-
pub fn read(&self, field: Field<T, R>) -> T {
268-
field.read(self.get())
269-
}
270-
271-
/// Read value of the given field as an enum member
272-
#[inline]
273-
pub fn read_as_enum<E: TryFromValue<T, EnumType = E>>(&self, field: Field<T, R>) -> Option<E> {
274-
field.read_as_enum(self.get())
275-
}
276-
277-
/// Write the value of one or more fields, overwriting the other fields with zero
278-
#[inline]
279-
pub fn write(&mut self, field: FieldValue<T, R>) {
280-
self.set(field.value);
281-
}
282-
283-
/// Write the value of one or more fields, leaving the other fields unchanged
284-
#[inline]
285-
pub fn modify(&mut self, field: FieldValue<T, R>) {
286-
self.set(field.modify(self.get()));
287-
}
288-
289-
/// Check if one or more bits in a field are set
290-
#[inline]
291-
pub fn is_set(&self, field: Field<T, R>) -> bool {
292-
field.is_set(self.get())
293-
}
294-
295-
/// Check if any specified parts of a field match
296-
#[inline]
297-
pub fn matches_any(&self, field: FieldValue<T, R>) -> bool {
298-
field.matches_any(self.get())
299-
}
300-
301-
/// Check if all specified parts of a field match
302-
#[inline]
303-
pub fn matches_all(&self, field: FieldValue<T, R>) -> bool {
304-
field.matches_all(self.get())
305-
}
306-
307-
/// Do a bitwise AND operation of the stored value and the passed in value
308-
/// and return a new LocalRegisterCopy.
309-
#[inline]
310-
pub fn bitand(&self, rhs: T) -> LocalRegisterCopy<T, R> {
311-
LocalRegisterCopy::new(self.value & rhs)
312-
}
313-
}
314-
315-
impl<T: IntLike + fmt::Debug, R: RegisterLongName> fmt::Debug for LocalRegisterCopy<T, R> {
316-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317-
write!(f, "{:?}", self.value)
318-
}
319-
}
320-
321-
macro_rules! From_impl_for {
322-
($type:ty) => {
323-
impl<R: RegisterLongName> From<LocalRegisterCopy<$type, R>> for $type {
324-
fn from(r: LocalRegisterCopy<$type, R>) -> $type {
325-
r.value
326-
}
327-
}
328-
};
329-
}
330-
331-
From_impl_for!(u8);
332-
From_impl_for!(u16);
333-
From_impl_for!(u32);
334-
From_impl_for!(u64);
335-
From_impl_for!(u128);
336-
From_impl_for!(usize);
337-
338220
#[cfg(not(feature = "no_std_unit_tests"))]
339221
#[cfg(test)]
340222
mod tests {
@@ -376,8 +258,8 @@ mod tests {
376258
}
377259

378260
mod field {
379-
use super::super::{Field, TryFromValue};
380261
use super::Foo;
262+
use crate::fields::{Field, TryFromValue};
381263

382264
#[test]
383265
fn test_new() {
@@ -446,7 +328,7 @@ mod tests {
446328
}
447329

448330
mod field_value {
449-
use super::super::Field;
331+
use crate::fields::Field;
450332

451333
#[test]
452334
fn test_from() {

0 commit comments

Comments
 (0)