From ca9b10dce8c062dc1798b944dee334c38f36e483 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 7 May 2019 00:32:45 +0200 Subject: [PATCH] refactor regs macros for RO/WO/RW access --- src/regs.rs | 89 +++++++++++++++++++++++++++++++++++++++--------- src/slcr.rs | 8 ++--- src/uart/mod.rs | 8 ++--- src/uart/regs.rs | 15 ++++---- 4 files changed, 88 insertions(+), 32 deletions(-) diff --git a/src/regs.rs b/src/regs.rs index e7ee651..f1c2292 100644 --- a/src/regs.rs +++ b/src/regs.rs @@ -1,24 +1,37 @@ //! Interface to peripheral registers akin to the code that svd2rust //! generates. +#![allow(unused)] use volatile_register::{RO, WO, RW}; use bit_field::BitField; -pub trait Register { +/// A readable register +pub trait RegisterR { + /// Type-safe reader for the register value type R; - type W; fn read(&self) -> Self::R; +} +/// A writable register +pub trait RegisterW { + /// Type-safe writer to the register value + type W; + + fn zeroed() -> Self::W; fn write(&self, w: Self::W); - fn modify Self::W>(&self, f: F); +} +/// A modifiable register +pub trait RegisterRW: RegisterR + RegisterW { + fn modify::R, ::W) -> ::W>(&self, f: F); } +#[doc(hidden)] #[macro_export] -macro_rules! register { - ($mod_name: ident, $struct_name: ident, $inner: ty) => ( +macro_rules! register_common { + ($mod_name: ident, $struct_name: ident, $access: ty, $inner: ty) => ( #[repr(C)] pub struct $struct_name { - inner: RW<$inner>, + inner: $access, } pub mod $mod_name { @@ -29,28 +42,46 @@ macro_rules! register { pub inner: $inner, } } - - impl $struct_name { - pub fn zeroed() -> $mod_name::Write { - $mod_name::Write { inner: 0 } - } - } - - impl crate::regs::Register for $struct_name { + ); +} +#[doc(hidden)] +#[macro_export] +macro_rules! register_r { + ($mod_name: ident, $struct_name: ident) => ( + impl crate::regs::RegisterR for $struct_name { type R = $mod_name::Read; - type W = $mod_name::Write; fn read(&self) -> Self::R { let inner = self.inner.read(); $mod_name::Read { inner } } + } + ); +} +#[doc(hidden)] +#[macro_export] +macro_rules! register_w { + ($mod_name: ident, $struct_name: ident) => ( + impl crate::regs::RegisterW for $struct_name { + type W = $mod_name::Write; + + fn zeroed() -> $mod_name::Write { + $mod_name::Write { inner: 0 } + } fn write(&self, w: Self::W) { unsafe { self.inner.write(w.inner); } } - + } + ); +} +#[doc(hidden)] +#[macro_export] +macro_rules! register_rw { + ($mod_name: ident, $struct_name: ident) => ( + impl crate::regs::RegisterRW for $struct_name { fn modify Self::W>(&self, f: F) { unsafe { self.inner.modify(|inner| { @@ -63,6 +94,31 @@ macro_rules! register { ); } +/// Main macro for register definition +#[macro_export] +macro_rules! register { + // Define read-only register + ($mod_name: ident, $struct_name: ident, RO, $inner: ty) => ( + crate::register_common!($mod_name, $struct_name, volatile_register::RO<$inner>, $inner); + crate::register_r!($mod_name, $struct_name); + ); + + // Define write-only register + ($mod_name: ident, $struct_name: ident, WO, $inner: ty) => ( + crate::register_common!($mod_name, $struct_name, volatile_register::WO<$inner>, $inner); + crate::register_w!($mod_name, $struct_name); + ); + + // Define read-write register + ($mod_name: ident, $struct_name: ident, RW, $inner: ty) => ( + crate::register_common!($mod_name, $struct_name, volatile_register::RW<$inner>, $inner); + crate::register_r!($mod_name, $struct_name); + crate::register_w!($mod_name, $struct_name); + crate::register_rw!($mod_name, $struct_name); + ); +} + +/// Define a 1-bit field of a register #[macro_export] macro_rules! register_bit { ($mod_name: ident, $name: ident, $bit: expr) => ( @@ -85,6 +141,7 @@ macro_rules! register_bit { ); } +/// Define a multi-bit field of a register #[macro_export] macro_rules! register_bits { ($mod_name: ident, $name: ident, $type: ty, $bit_begin: expr, $bit_end: expr) => ( diff --git a/src/slcr.rs b/src/slcr.rs index 7919998..4f25e43 100644 --- a/src/slcr.rs +++ b/src/slcr.rs @@ -1,6 +1,6 @@ -use volatile_register::{RO, WO, RW}; +#[allow(unused)] -use crate::{register, register_bit, register_bits, regs::Register}; +use crate::{register, register_bit, register_bits, regs::RegisterRW}; pub enum PllSource { IoPll = 0b00, @@ -8,7 +8,7 @@ pub enum PllSource { DdrPll = 0b11, } -register!(uart_clk_ctrl, UartClkCtrl, u32); +register!(uart_clk_ctrl, UartClkCtrl, RW, u32); register_bit!(uart_clk_ctrl, clkact0, 0); register_bit!(uart_clk_ctrl, clkact1, 1); register_bits!(uart_clk_ctrl, divisor, u8, 8, 13); @@ -32,7 +32,7 @@ impl UartClkCtrl { } } -register!(uart_rst_ctrl, UartRstCtrl, u32); +register!(uart_rst_ctrl, UartRstCtrl, RW, u32); register_bit!(uart_rst_ctrl, uart0_ref_rst, 3); register_bit!(uart_rst_ctrl, uart1_ref_rst, 2); register_bit!(uart_rst_ctrl, uart0_cpu1x_rst, 1); diff --git a/src/uart/mod.rs b/src/uart/mod.rs index 1221b4d..13c9eee 100644 --- a/src/uart/mod.rs +++ b/src/uart/mod.rs @@ -1,3 +1,5 @@ +#![allow(unused)] + mod regs; pub use regs::RegisterBlock; @@ -25,10 +27,8 @@ impl Uart { } pub fn write_byte(&self, v: u8) { - unsafe { - while self.regs.tx_fifo_full() {} + while self.regs.tx_fifo_full() {} - self.regs.write_byte(v); - } + self.regs.write_byte(v); } } diff --git a/src/uart/regs.rs b/src/uart/regs.rs index 09b2d36..ffda358 100644 --- a/src/uart/regs.rs +++ b/src/uart/regs.rs @@ -1,7 +1,6 @@ use volatile_register::{RO, WO, RW}; -use bit_field::BitField; -use crate::{register, register_bit, register_bits, regs::Register}; +use crate::{register, register_bit, register_bits, regs::*}; #[repr(u8)] pub enum ParityMode { @@ -33,7 +32,7 @@ pub struct RegisterBlock { tx_fifo_trigger_level: RW, } -register!(control, Control, u32); +register!(control, Control, RW, u32); register_bit!(control, rxrst, 0); register_bit!(control, txrst, 1); register_bit!(control, rxen, 2); @@ -41,19 +40,19 @@ register_bit!(control, rxdis, 3); register_bit!(control, txen, 4); register_bit!(control, txdis, 5); -register!(mode, Mode, u32); +register!(mode, Mode, RW, u32); register_bits!(mode, par, u8, 3, 5); -register!(baud_rate_gen, BaudRateGen, u32); +register!(baud_rate_gen, BaudRateGen, RW, u32); register_bits!(baud_rate_gen, cd, u16, 0, 15); -register!(channel_sts, ChannelSts, u32); +register!(channel_sts, ChannelSts, RO, u32); register_bit!(channel_sts, txfull, 4); -register!(tx_rx_fifo, TxRxFifo, u32); +register!(tx_rx_fifo, TxRxFifo, RW, u32); register_bits!(tx_rx_fifo, data, u32, 0, 31); -register!(baud_rate_div, BaudRateDiv, u32); +register!(baud_rate_div, BaudRateDiv, RW, u32); register_bits!(baud_rate_div, bdiv, u8, 0, 7); impl RegisterBlock {