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