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