1
0
Fork 0

refactor regs macros for RO/WO/RW access

This commit is contained in:
Astro 2019-05-07 00:32:45 +02:00
parent 1e540a1175
commit ca9b10dce8
4 changed files with 88 additions and 32 deletions

View File

@ -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<F: FnOnce(Self::R, Self::W) -> Self::W>(&self, f: F);
}
/// A modifiable register
pub trait RegisterRW: RegisterR + RegisterW {
fn modify<F: FnOnce(<Self as RegisterR>::R, <Self as RegisterW>::W) -> <Self as RegisterW>::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<F: FnOnce(Self::R, Self::W) -> 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) => (

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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<u32>,
}
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 {