-
Notifications
You must be signed in to change notification settings - Fork 156
Closed
Description
External traits crate:
pub trait ResetValue {
#[doc = r" Reset value of the register"]
const RESET_VALUE: Self;
}
pub trait BitOffset {
#[doc = r" Bit offset of the field"]
const OFFSET: u8;
}
pub trait WriteRegister<W>
where
W: ResetValue,
{
#[doc = r" Writes to the register"]
#[inline]
fn write<F>(&self, f: F)
// &self
where
F: FnOnce(&W) -> &mut W;
}
pub trait ReadRegister<R> {
#[doc = r" Reads the contents of the register"]
fn read(&self) -> R;
}
pub trait ResetRegister<W>: WriteRegister<W>
where
W: ResetValue,
{
#[doc = r" Writes the reset value to the register"]
fn reset(&self) {
// &self
self.write(|w| w)
}
}
pub trait ModifyRegister<R, W> {
#[doc = r" Modifies the contents of the register"]
#[inline]
fn modify<F>(&self, f: F)
// &self
where
for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W;
}
pub trait SingleBit<'a, W>
where
Self: core::marker::Sized + BitOffset,
{
#[doc = r" Sets the field bit"]
fn set_bit(self) -> &'a mut W {
self.bit(true)
}
#[doc = r" Clears the field bit"]
fn clear_bit(self) -> &'a mut W {
self.bit(false)
}
#[doc = r" Writes raw bits to the field"]
#[inline]
fn bit(self, value: bool) -> &'a mut W;
}
External macro crate:
extern crate proc_macro;
use crate::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(WriteRegister)]
pub fn write_register_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let regname = &input.ident;
let expanded = quote! {
impl crate::WriteRegister<W> for #regname {
#[inline]
fn write<F>(&self, f: F) // &self
where
F: FnOnce(&mut W) -> &mut W,
{
let mut w = W::RESET_VALUE;
f(&mut w);
self.register.set(w.bits);
}
}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(ResetRegister)]
pub fn reset_register_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let regname = &input.ident;
let expanded = quote! {
impl ResetRegister<W> for #regname {}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(ReadRegister)]
pub fn read_register_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let regname = &input.ident;
let expanded = quote! {
impl crate::ReadRegister<R> for #regname {
#[inline]
fn read(&self) -> R {
R {
bits: self.register.get(),
}
}
}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(ModifyRegister)]
pub fn modify_register_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let regname = &input.ident;
let expanded = quote! {
impl crate::ModifyRegister<R, W> for #regname {
#[inline]
fn modify<F>(&self, f: F) // &self
where
for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W,
{
let bits = self.register.get();
let r = R { bits };
let mut w = W { bits };
f(&r, &mut w);
self.register.set(w.bits);
}
}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(SingleBit)]
pub fn single_bit_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let regname = &input.ident;
let expanded = quote! {
impl<'a> SingleBit<'a, W> for #regname<'a> {
#[inline]
fn bit(self, value: bool) -> &'a mut W {
const MASK: bool = true;
self.w.bits &= !((MASK as u32) << Self::OFFSET);
self.w.bits |= ((value & MASK) as u32) << Self::OFFSET;
self.w
}
}
};
TokenStream::from(expanded)
}
Usage:
#[derive(ReadRegister, WriteRegister, ModifyRegister, ResetRegister)]
pub struct JDR {
register: ::vcell::VolatileCell<u32>,
}
#[doc = r" Value read from the register"]
struct R {
bits: u32,
}
#[doc = r" Value to write to the register"]
struct W {
bits: u32,
}
impl crate::ResetValue for W {
const RESET_VALUE: Self = Self { bits: 0 };
}
impl W {
#[doc = "Bit 9 - Enable the watchdog on a single channel in scan mode"]
#[inline]
pub fn awdsgl(&mut self) -> _AWDSGLW {
_AWDSGLW { w: self }
}
...
}
impl<'a> BitOffset for _AWDSGLW<'a> {
const OFFSET: u8 = 9;
}
#[doc = r" Proxy"]
#[derive(SingleBit)]
pub struct _AWDSGLW<'a> {
w: &'a mut W,
}
Activity
therealprof commentedon Feb 23, 2019
Interesting idea to reduce code size. I'm kind of wondering what this will do to our biggest pain point: compile time.
burrbull commentedon Feb 23, 2019
I don't have answer.