Skip to content

Register trait improvements #463

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 101 additions & 98 deletions src/generate/generic.rs
Original file line number Diff line number Diff line change
@@ -1,60 +1,59 @@
use core::marker;

/// Raw register type
pub trait Register {
/// Raw register type (`u8`, `u16`, `u32`, ...).
type Ux: Copy;
}

/// Trait implemented by readable registers to enable the `read` method.
///
/// Registers marked with `Writable` can be also `modify`'ed.
pub trait Readable {}
pub trait Readable: Register {
/// Result from a call to `read` and argument to `modify`.
type Reader: core::convert::From<R<Self>> + core::ops::Deref<Target = R<Self>>;
}

/// Trait implemented by writeable registers.
///
/// This enables the `write`, `write_with_zero` and `reset` methods.
///
/// Registers marked with `Readable` can be also `modify`'ed.
pub trait Writable {}


/// Raw register type (autoimplemented for `Reg` type)
pub trait RawType {
/// Raw register type (`u8`, `u16`, `u32`, ...).
type Ux: Copy;
pub trait Writable: Register {
/// Writer type argument to `write`, et al.
type Writer: core::convert::From<W<Self>> + core::ops::Deref<Target = W<Self>>;
}

/// Reset value of the register.
///
/// This value is the initial value for the `write` method. It can also be directly written to the
/// register by using the `reset` method.
pub trait ResetValue: RawType {
pub trait Resettable: Register {
/// Reset value of the register.
fn reset_value() -> Self::Ux;
}

/// This structure provides volatile access to registers.
pub struct Reg<U, REG> {
register: vcell::VolatileCell<U>,
pub struct Reg<REG: Register> {
register: vcell::VolatileCell<REG::Ux>,
_marker: marker::PhantomData<REG>,
}

unsafe impl<U: Send, REG> Send for Reg<U, REG> {}
unsafe impl<REG: Register> Send for Reg<REG> where REG::Ux: Send {}

impl<U, REG> Reg<U, REG>
where
U: Copy,
{
impl<REG: Register> Reg<REG> {
/// Returns the underlying memory address of register.
///
/// ```ignore
/// let reg_ptr = periph.reg.as_ptr();
/// ```
#[inline(always)]
pub fn as_ptr(&self) -> *mut U {
pub fn as_ptr(&self) -> *mut REG::Ux {
self.register.as_ptr()
}
}

impl<U, REG> Reg<U, REG>
where
Self: Readable,
U: Copy,
{
impl<REG: Readable> Reg<REG> {
/// Reads the contents of a `Readable` register.
///
/// You can read the raw contents of a register by using `bits`:
Expand All @@ -68,40 +67,23 @@ where
/// let flag = reader.field2().bit_is_set();
/// ```
#[inline(always)]
pub fn read(&self) -> R<U, Self> {
R {
pub fn read(&self) -> REG::Reader {
REG::Reader::from(R {
bits: self.register.get(),
_reg: marker::PhantomData,
}
})
}
}

impl<U, REG> RawType for Reg<U, REG>
where
U: Copy,
{
type Ux = U;
}

impl<U, REG> Reg<U, REG>
where
Self: ResetValue + RawType<Ux = U> + Writable,
U: Copy,
{
impl<REG: Resettable + Writable> Reg<REG> {
/// Writes the reset value to `Writable` register.
///
/// Resets the register to its initial state.
#[inline(always)]
pub fn reset(&self) {
self.register.set(Self::reset_value())
self.register.set(REG::reset_value())
}
}

impl<U, REG> Reg<U, REG>
where
Self: ResetValue + RawType<Ux = U> + Writable,
U: Copy
{
/// Writes bits to a `Writable` register.
///
/// You can write raw bits into a register:
Expand All @@ -120,46 +102,41 @@ where
#[inline(always)]
pub fn write<F>(&self, f: F)
where
F: FnOnce(&mut W<U, Self>) -> &mut W<U, Self>,
F: FnOnce(&mut REG::Writer) -> &mut REG::Writer,
{
self.register.set(
f(&mut W {
bits: Self::reset_value(),
f(&mut REG::Writer::from(W {
bits: REG::reset_value(),
_reg: marker::PhantomData,
})
}))
.bits,
);
}
}

impl<U, REG> Reg<U, REG>
impl<REG: Writable> Reg<REG>
where
Self: Writable,
U: Copy + Default,
REG::Ux: Default,
{
/// Writes 0 to a `Writable` register.
///
/// Similar to `write`, but unused bits will contain 0.
#[inline(always)]
pub fn write_with_zero<F>(&self, f: F)
where
F: FnOnce(&mut W<U, Self>) -> &mut W<U, Self>,
F: FnOnce(&mut REG::Writer) -> &mut REG::Writer,
{
self.register.set(
f(&mut W {
bits: U::default(),
(*f(&mut REG::Writer::from(W {
bits: REG::Ux::default(),
_reg: marker::PhantomData,
})
})))
.bits,
);
}
}

impl<U, REG> Reg<U, REG>
where
Self: Readable + Writable,
U: Copy,
{
impl<REG: Readable + Writable> Reg<REG> {
/// Modifies the contents of the register by reading and then writing it.
///
/// E.g. to do a read-modify-write sequence to change parts of a register:
Expand All @@ -180,35 +157,88 @@ where
#[inline(always)]
pub fn modify<F>(&self, f: F)
where
for<'w> F: FnOnce(&R<U, Self>, &'w mut W<U, Self>) -> &'w mut W<U, Self>,
for<'w> F: FnOnce(&REG::Reader, &'w mut REG::Writer) -> &'w mut REG::Writer,
{
let bits = self.register.get();
self.register.set(
f(
&R {
&REG::Reader::from(R {
bits,
_reg: marker::PhantomData,
},
&mut W {
}),
&mut REG::Writer::from(W {
bits,
_reg: marker::PhantomData,
},
}),
)
.bits,
);
}
}

/// Register/field reader.
/// Register reader.
///
/// Result of the `read` methods of registers. Also used as a closure argument in the `modify`
/// method.
pub struct R<U, T> {
pub struct R<REG: Register + ?Sized> {
pub(crate) bits: REG::Ux,
_reg: marker::PhantomData<REG>,
}

impl<REG: Register> R<REG> {
/// Reads raw bits from register.
#[inline(always)]
pub fn bits(&self) -> REG::Ux {
self.bits
}
}

impl<REG: Register, FI> PartialEq<FI> for R<REG>
where
REG::Ux: PartialEq,
FI: Copy + Into<REG::Ux>,
{
#[inline(always)]
fn eq(&self, other: &FI) -> bool {
self.bits.eq(&(*other).into())
}
}

/// Register writer.
///
/// Used as an argument to the closures in the `write` and `modify` methods of the register.
pub struct W<REG: Register + ?Sized> {
///Writable bits
pub(crate) bits: REG::Ux,
_reg: marker::PhantomData<REG>,
}

impl<REG: Register> W<REG> {
/// Writes raw bits to the register.
#[inline(always)]
pub unsafe fn bits(&mut self, bits: REG::Ux) {
self.bits = bits;
}
}

/// Used if enumerated values cover not the whole range.
#[derive(Clone, Copy, PartialEq)]
pub enum Variant<U, T> {
/// Expected variant.
Val(T),
/// Raw bits.
Res(U),
}

/// Field reader.
///
/// Result of the `read` methods of fields.
pub struct FieldReader<U, T> {
pub(crate) bits: U,
_reg: marker::PhantomData<T>,
}

impl<U, T> R<U, T>
impl<U, T> FieldReader<U, T>
where
U: Copy,
{
Expand All @@ -221,14 +251,14 @@ where
}
}

/// Reads raw bits from register/field.
/// Reads raw bits from field.
#[inline(always)]
pub fn bits(&self) -> U {
self.bits
}
}

impl<U, T, FI> PartialEq<FI> for R<U, T>
impl<U, T, FI> PartialEq<FI> for FieldReader<U, T>
where
U: PartialEq,
FI: Copy + Into<U>,
Expand All @@ -239,7 +269,7 @@ where
}
}

impl<FI> R<bool, FI> {
impl<FI> FieldReader<bool, FI> {
/// Value of the field as raw bits.
#[inline(always)]
pub fn bit(&self) -> bool {
Expand All @@ -256,30 +286,3 @@ impl<FI> R<bool, FI> {
self.bit()
}
}

/// Register writer.
///
/// Used as an argument to the closures in the `write` and `modify` methods of the register.
pub struct W<U, REG> {
///Writable bits
pub(crate) bits: U,
_reg: marker::PhantomData<REG>,
}

impl<U, REG> W<U, REG> {
/// Writes raw bits to the register.
#[inline(always)]
pub unsafe fn bits(&mut self, bits: U) -> &mut Self {
self.bits = bits;
self
}
}

/// Used if enumerated values cover not the whole range.
#[derive(Clone, Copy, PartialEq)]
pub enum Variant<U, T> {
/// Expected variant.
Val(T),
/// Raw bits.
Res(U),
}
Loading