zynq-rs/src/regs.rs

166 lines
4.5 KiB
Rust

//! Interface to peripheral registers akin to the code that svd2rust
//! generates.
#![allow(unused)]
use volatile_register::{RO, WO, RW};
use bit_field::BitField;
/// A readable register
pub trait RegisterR {
/// Type-safe reader for the register value
type R;
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);
}
/// 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_common {
($mod_name: ident, $struct_name: ident, $access: ty, $inner: ty) => (
#[repr(C)]
pub struct $struct_name {
inner: $access,
}
pub mod $mod_name {
pub struct Read {
pub inner: $inner,
}
pub struct Write {
pub inner: $inner,
}
}
);
}
#[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;
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| {
f($mod_name::Read { inner }, $mod_name::Write { inner })
.inner
});
}
}
}
);
}
/// 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) => (
impl $mod_name::Read {
pub fn $name(&self) -> bool {
use bit_field::BitField;
self.inner.get_bit($bit)
}
}
impl $mod_name::Write {
pub fn $name(mut self, value: bool) -> Self {
use bit_field::BitField;
self.inner.set_bit($bit, value);
self
}
}
);
}
/// 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) => (
impl $mod_name::Read {
pub fn $name(&self) -> $type {
use bit_field::BitField;
self.inner.get_bits($bit_begin..=$bit_end) as $type
}
}
impl $mod_name::Write {
pub fn $name(mut self, value: $type) -> Self {
use bit_field::BitField;
self.inner.set_bits($bit_begin..=$bit_end, value.into());
self
}
}
);
}