#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RO;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct WO;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RW;
pub trait Access: sealed::Access + Copy {}
impl Access for RO {}
impl Access for WO {}
impl Access for RW {}
pub trait Read: Access {}
impl Read for RO {}
impl Read for RW {}
pub trait Write: Access {}
impl Write for WO {}
impl Write for RW {}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct Reg<T: Copy, A: Access> {
ptr: *mut T,
phantom: core::marker::PhantomData<A>,
}
unsafe impl<T: Copy + Send, A: Access> Send for Reg<T, A> {}
unsafe impl<T: Copy + Sync, A: Access> Sync for Reg<T, A> {}
impl<T: Copy, A: Access> Reg<T, A> {
#[inline]
pub const unsafe fn new(ptr: *mut T) -> Self {
Self {
ptr,
phantom: core::marker::PhantomData,
}
}
#[inline]
pub const fn get_ptr(self) -> *mut T {
self.ptr
}
}
impl<T: Copy, A: Read> Reg<T, A> {
#[inline]
pub fn read(self) -> T {
unsafe { self.ptr.read_volatile() }
}
}
impl<T: Copy, A: Write> Reg<T, A> {
#[inline]
pub fn write(self, val: T) {
unsafe { self.ptr.write_volatile(val) }
}
}
impl<T: Copy, A: Read + Write> Reg<T, A> {
#[inline]
pub fn modify<R>(self, f: impl FnOnce(&mut T) -> R) -> R {
let mut val = self.read();
let res = f(&mut val);
self.write(val);
res
}
}
macro_rules! bitwise_reg {
($TYPE: ty) => {
impl<A: Read> Reg<$TYPE, A> {
#[inline]
pub fn read_bit(self, n: usize) -> bool {
let mask = 1 << n;
let val = self.read();
val & mask == mask
}
#[inline]
pub fn read_bits(self, start: usize, end: usize) -> $TYPE {
let n_bits = end - start + 1;
let mask = ((1 << n_bits) - 1) << start;
let val = self.read();
(val & mask) >> start
}
}
impl<A: Read + Write> Reg<$TYPE, A> {
#[inline]
pub fn clear_bit(self, n: usize) {
self.modify(|val| *val &= !(1 << n));
}
#[inline]
pub fn set_bit(self, n: usize) {
self.modify(|val| *val |= 1 << n);
}
#[inline]
pub fn write_bits(self, start: usize, end: usize, val: $TYPE) {
let n_bits = end - start + 1;
let mask = ((1 << n_bits) - 1) << start;
self.modify(|v| *v = (*v & !mask) | ((val << start) & mask));
}
}
};
}
bitwise_reg!(u8);
bitwise_reg!(u16);
bitwise_reg!(u32);
bitwise_reg!(u64);
bitwise_reg!(u128);
bitwise_reg!(usize);
bitwise_reg!(i8);
bitwise_reg!(i16);
bitwise_reg!(i32);
bitwise_reg!(i64);
bitwise_reg!(i128);
bitwise_reg!(isize);
#[cfg(any(
target_has_atomic = "8",
target_has_atomic = "16",
target_has_atomic = "32",
target_has_atomic = "64",
target_has_atomic = "ptr"
))]
macro_rules! bitwise_atomic_reg {
($TYPE: ty, $ATOMIC: ty) => {
impl<A: Read + Write> Reg<$TYPE, A> {
pub unsafe fn as_atomic<'a>(&self) -> &'a $ATOMIC {
unsafe { &*self.ptr.cast() }
}
#[inline]
pub unsafe fn atomic_clear_bit(&self, n: usize, order: core::sync::atomic::Ordering) {
unsafe { self.as_atomic() }.fetch_and(!(1 << n), order);
}
#[inline]
pub unsafe fn atomic_set_bit(&self, n: usize, order: core::sync::atomic::Ordering) {
unsafe { self.as_atomic() }.fetch_or(1 << n, order);
}
}
};
}
#[cfg(target_has_atomic = "8")]
bitwise_atomic_reg!(u8, core::sync::atomic::AtomicU8);
#[cfg(target_has_atomic = "16")]
bitwise_atomic_reg!(u16, core::sync::atomic::AtomicU16);
#[cfg(target_has_atomic = "32")]
bitwise_atomic_reg!(u32, core::sync::atomic::AtomicU32);
#[cfg(target_has_atomic = "64")]
bitwise_atomic_reg!(u64, core::sync::atomic::AtomicU64);
#[cfg(target_has_atomic = "ptr")]
bitwise_atomic_reg!(usize, core::sync::atomic::AtomicUsize);
#[cfg(target_has_atomic = "8")]
bitwise_atomic_reg!(i8, core::sync::atomic::AtomicI8);
#[cfg(target_has_atomic = "16")]
bitwise_atomic_reg!(i16, core::sync::atomic::AtomicI16);
#[cfg(target_has_atomic = "32")]
bitwise_atomic_reg!(i32, core::sync::atomic::AtomicI32);
#[cfg(target_has_atomic = "64")]
bitwise_atomic_reg!(i64, core::sync::atomic::AtomicI64);
#[cfg(target_has_atomic = "ptr")]
bitwise_atomic_reg!(isize, core::sync::atomic::AtomicIsize);
macro_rules! peripheral {
($REGISTER: ident, $TYPE: ty, $ACCESS: ident) => {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct $REGISTER {
register: $crate::common::Reg<$TYPE, $crate::common::$ACCESS>,
}
impl $REGISTER {
#[inline]
pub const unsafe fn new(address: usize) -> Self {
Self {
register: $crate::common::Reg::new(address as _),
}
}
}
};
($REGISTER: ident, $TYPE: ty, $ACCESS: ident, $GENERIC: ident) => {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct $REGISTER<$GENERIC> {
register: $crate::common::Reg<$TYPE, $crate::common::$ACCESS>,
_marker: core::marker::PhantomData<$GENERIC>,
}
impl<$GENERIC> $REGISTER<$GENERIC> {
#[inline]
pub const unsafe fn new(address: usize) -> Self {
Self {
register: $crate::common::Reg::new(address as _),
_marker: core::marker::PhantomData,
}
}
}
};
}
macro_rules! safe_peripheral {
($REGISTER: ident, $TYPE: ty, $ACCESS: ident) => {
$crate::common::peripheral!($REGISTER, $TYPE, $ACCESS);
impl $REGISTER {
#[inline]
pub const fn get_register(self) -> $crate::common::Reg<$TYPE, $crate::common::$ACCESS> {
self.register
}
}
impl core::ops::Deref for $REGISTER {
type Target = $crate::common::Reg<$TYPE, $crate::common::$ACCESS>;
fn deref(&self) -> &Self::Target {
&self.register
}
}
};
($REGISTER: ident, $TYPE: ty, $ACCESS: ident, $GENERIC: ident) => {
$crate::common::peripheral!($REGISTER, $TYPE, $ACCESS, $GENERIC);
impl $REGISTER {
#[inline]
pub const fn get_register(self) -> $crate::common::Reg<$TYPE, $crate::common::$ACCESS> {
self.register
}
}
impl<$GENERIC> core::ops::Deref for $REGISTER<$GENERIC> {
type Target = $crate::common::Reg<$TYPE, $crate::common::$ACCESS>;
fn deref(&self) -> &Self::Target {
&self.register
}
}
};
}
macro_rules! unsafe_peripheral {
($REGISTER: ident, $TYPE: ty, $ACCESS: ident) => {
$crate::common::peripheral!($REGISTER, $TYPE, $ACCESS);
impl $REGISTER {
#[inline]
pub const fn get_ptr(self) -> *mut $TYPE {
self.register.get_ptr()
}
#[inline]
pub const unsafe fn get_register(
self,
) -> $crate::common::Reg<$TYPE, $crate::common::$ACCESS> {
self.register
}
}
};
($REGISTER: ident, $TYPE: ty, $ACCESS: ident, $GENERIC: ident) => {
$crate::common::peripheral!($REGISTER, $TYPE, $ACCESS, $GENERIC);
impl<$GENERIC> $REGISTER<$GENERIC> {
#[inline]
pub const fn get_ptr(self) -> *mut $TYPE {
self.register.get_ptr()
}
#[inline]
pub const unsafe fn get_register(
self,
) -> $crate::common::Reg<$TYPE, $crate::common::$ACCESS> {
self.register
}
}
};
}
pub(crate) use {peripheral, safe_peripheral, unsafe_peripheral};
mod sealed {
use super::*;
pub trait Access {}
impl Access for RO {}
impl Access for WO {}
impl Access for RW {}
}