forked from M-Labs/zynq-rs
refactor regs macros for RO/WO/RW access
This commit is contained in:
parent
1e540a1175
commit
ca9b10dce8
87
src/regs.rs
87
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<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) => (
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {}
|
||||
|
||||
self.regs.write_byte(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue