use super::*;
use core::ptr::{read_volatile, write_volatile};
pub trait Reg<T: RegTag>: Sized {
type Val: RegVal;
const ADDRESS: usize;
}
pub trait RegRef<'a, T: RegTag>: Reg<T> {
type Hold: RegHold<'a, T, Self>;
#[inline(always)]
fn hold(&'a self, val: Self::Val) -> Self::Hold {
unsafe { Self::Hold::new(self, val) }
}
#[inline(always)]
fn default(&'a self) -> Self::Hold {
self.hold(self.default_val())
}
#[inline(always)]
fn default_val(&self) -> Self::Val {
unsafe { Self::Val::default() }
}
}
pub trait RReg<T: RegTag>: Reg<T> {
#[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
#[inline(always)]
fn load<'a>(&'a self) -> <Self as RegRef<'a, T>>::Hold
where
Self: RegRef<'a, T>,
{
self.hold(self.load_val())
}
#[inline(always)]
fn load_val(&self) -> Self::Val {
unsafe { Self::Val::from_raw(read_volatile(self.to_ptr())) }
}
#[inline(always)]
fn to_ptr(&self) -> *const <Self::Val as RegVal>::Raw {
Self::ADDRESS as *const <Self::Val as RegVal>::Raw
}
}
pub trait WReg<T: RegTag>: Reg<T> {
#[inline(always)]
fn to_mut_ptr(&self) -> *mut <Self::Val as RegVal>::Raw {
Self::ADDRESS as *mut <Self::Val as RegVal>::Raw
}
}
pub trait RoReg<T: RegTag>: RReg<T> {}
pub trait WoReg<T: RegTag>: WReg<T> {}
pub trait WRegShared<'a, T: RegShared>: WReg<T> + RegRef<'a, T> {
fn reset<F>(&'a self, f: F)
where
F: for<'b> FnOnce(&'b mut <Self as RegRef<'a, T>>::Hold)
-> &'b mut <Self as RegRef<'a, T>>::Hold;
fn store_val(&self, val: Self::Val);
fn store_default(&'a self);
}
pub trait WRegUnique<'a>: WReg<Utt> + RegRef<'a, Utt> {
fn reset<F>(&'a mut self, f: F)
where
F: for<'b> FnOnce(&'b mut <Self as RegRef<'a, Utt>>::Hold)
-> &'b mut <Self as RegRef<'a, Utt>>::Hold;
fn store_val(&mut self, val: Self::Val);
fn store_default(&'a mut self);
}
pub trait RwRegUnique<'a>: RReg<Utt> + WRegUnique<'a> + RegRef<'a, Utt> {
fn modify<F>(&'a mut self, f: F)
where
F: for<'b> FnOnce(&'b mut <Self as RegRef<'a, Utt>>::Hold)
-> &'b mut <Self as RegRef<'a, Utt>>::Hold;
}
impl<'a, T, U> WRegShared<'a, T> for U
where
T: RegShared,
U: WReg<T> + RegRef<'a, T>,
U::Val: RegVal,
{
#[inline(always)]
fn reset<F>(&'a self, f: F)
where
F: for<'b> FnOnce(&'b mut <U as RegRef<'a, T>>::Hold)
-> &'b mut <U as RegRef<'a, T>>::Hold,
{
self.store_val(f(&mut self.default()).val());
}
#[inline(always)]
fn store_val(&self, val: U::Val) {
unsafe { write_volatile(self.to_mut_ptr(), val.raw()) };
}
#[inline(always)]
fn store_default(&'a self) {
self.store_val(self.default_val());
}
}
impl<'a, T> WRegUnique<'a> for T
where
T: WReg<Utt> + RegRef<'a, Utt>,
{
#[inline(always)]
fn reset<F>(&'a mut self, f: F)
where
F: for<'b> FnOnce(&'b mut <T as RegRef<'a, Utt>>::Hold)
-> &'b mut <T as RegRef<'a, Utt>>::Hold,
{
unsafe {
write_volatile(self.to_mut_ptr(), f(&mut self.default()).val().raw());
}
}
#[inline(always)]
fn store_val(&mut self, val: T::Val) {
unsafe { write_volatile(self.to_mut_ptr(), val.raw()) };
}
#[inline(always)]
fn store_default(&'a mut self) {
unsafe { write_volatile(self.to_mut_ptr(), self.default_val().raw()) };
}
}
impl<'a, T> RwRegUnique<'a> for T
where
T: RReg<Utt> + WRegUnique<'a> + RegRef<'a, Utt>,
{
#[inline(always)]
fn modify<F>(&'a mut self, f: F)
where
F: for<'b> FnOnce(&'b mut <T as RegRef<'a, Utt>>::Hold)
-> &'b mut <T as RegRef<'a, Utt>>::Hold,
{
unsafe {
write_volatile(self.to_mut_ptr(), f(&mut self.load()).val().raw());
}
}
}