2019-05-21 07:30:17 +08:00
|
|
|
//! Type-safe interface to peripheral registers akin to the code that
|
|
|
|
//! svd2rust generates.
|
2019-05-07 05:56:53 +08:00
|
|
|
|
2019-12-18 06:35:58 +08:00
|
|
|
#![no_std]
|
|
|
|
|
|
|
|
pub use vcell::VolatileCell;
|
|
|
|
pub use volatile_register::{RO, WO, RW};
|
|
|
|
pub use bit_field::BitField;
|
2019-05-07 05:56:53 +08:00
|
|
|
|
2019-05-07 06:32:45 +08:00
|
|
|
/// A readable register
|
|
|
|
pub trait RegisterR {
|
|
|
|
/// Type-safe reader for the register value
|
2019-05-07 05:56:53 +08:00
|
|
|
type R;
|
|
|
|
|
|
|
|
fn read(&self) -> Self::R;
|
2019-05-07 06:32:45 +08:00
|
|
|
}
|
|
|
|
/// A writable register
|
|
|
|
pub trait RegisterW {
|
|
|
|
/// Type-safe writer to the register value
|
|
|
|
type W;
|
|
|
|
|
|
|
|
fn zeroed() -> Self::W;
|
2019-05-24 00:01:18 +08:00
|
|
|
fn write(&mut self, w: Self::W);
|
2019-05-07 06:32:45 +08:00
|
|
|
}
|
|
|
|
/// A modifiable register
|
|
|
|
pub trait RegisterRW: RegisterR + RegisterW {
|
2019-05-24 00:01:18 +08:00
|
|
|
fn modify<F: FnOnce(<Self as RegisterR>::R, <Self as RegisterW>::W) -> <Self as RegisterW>::W>(&mut self, f: F);
|
2019-05-07 05:56:53 +08:00
|
|
|
}
|
|
|
|
|
2019-05-07 06:32:45 +08:00
|
|
|
#[doc(hidden)]
|
2019-05-07 05:56:53 +08:00
|
|
|
#[macro_export]
|
2019-05-07 06:32:45 +08:00
|
|
|
macro_rules! register_common {
|
2020-11-20 03:26:18 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, $access: ty, $inner: ty) => (
|
2019-05-07 06:05:38 +08:00
|
|
|
#[repr(C)]
|
2020-11-20 03:26:18 +08:00
|
|
|
$(#[$outer])*
|
2019-05-07 05:56:53 +08:00
|
|
|
pub struct $struct_name {
|
2019-05-07 06:32:45 +08:00
|
|
|
inner: $access,
|
2019-05-07 05:56:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub mod $mod_name {
|
2019-10-24 07:24:12 +08:00
|
|
|
#[derive(Clone)]
|
2019-05-07 05:56:53 +08:00
|
|
|
pub struct Read {
|
|
|
|
pub inner: $inner,
|
|
|
|
}
|
2019-10-24 07:24:12 +08:00
|
|
|
#[derive(Clone)]
|
2019-05-07 05:56:53 +08:00
|
|
|
pub struct Write {
|
|
|
|
pub inner: $inner,
|
|
|
|
}
|
|
|
|
}
|
2019-05-07 06:32:45 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register_r {
|
|
|
|
($mod_name: ident, $struct_name: ident) => (
|
2020-11-20 03:16:36 +08:00
|
|
|
impl $crate::RegisterR for $struct_name {
|
2019-05-07 05:56:53 +08:00
|
|
|
type R = $mod_name::Read;
|
|
|
|
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-07 05:56:53 +08:00
|
|
|
fn read(&self) -> Self::R {
|
|
|
|
let inner = self.inner.read();
|
|
|
|
$mod_name::Read { inner }
|
|
|
|
}
|
2019-05-07 06:32:45 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register_w {
|
|
|
|
($mod_name: ident, $struct_name: ident) => (
|
2020-11-20 03:16:36 +08:00
|
|
|
impl $crate::RegisterW for $struct_name {
|
2019-05-07 06:32:45 +08:00
|
|
|
type W = $mod_name::Write;
|
|
|
|
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-07 06:32:45 +08:00
|
|
|
fn zeroed() -> $mod_name::Write {
|
|
|
|
$mod_name::Write { inner: 0 }
|
|
|
|
}
|
2019-05-07 05:56:53 +08:00
|
|
|
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-24 00:01:18 +08:00
|
|
|
fn write(&mut self, w: Self::W) {
|
2019-05-07 05:56:53 +08:00
|
|
|
unsafe {
|
|
|
|
self.inner.write(w.inner);
|
|
|
|
}
|
|
|
|
}
|
2019-05-07 06:32:45 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register_rw {
|
|
|
|
($mod_name: ident, $struct_name: ident) => (
|
2020-11-20 03:16:36 +08:00
|
|
|
impl $crate::RegisterRW for $struct_name {
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-24 00:01:18 +08:00
|
|
|
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
2019-05-07 05:56:53 +08:00
|
|
|
unsafe {
|
|
|
|
self.inner.modify(|inner| {
|
|
|
|
f($mod_name::Read { inner }, $mod_name::Write { inner })
|
|
|
|
.inner
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2020-04-29 21:19:24 +08:00
|
|
|
($mod_name: ident, $struct_name: ident, $mask: expr) => (
|
2020-11-20 03:16:36 +08:00
|
|
|
impl $crate::RegisterRW for $struct_name {
|
2020-04-29 21:19:24 +08:00
|
|
|
#[inline]
|
|
|
|
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
|
|
|
unsafe {
|
|
|
|
self.inner.modify(|inner| {
|
|
|
|
f($mod_name::Read { inner }, $mod_name::Write { inner: inner & ($mask) })
|
|
|
|
.inner
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2019-05-07 05:56:53 +08:00
|
|
|
}
|
|
|
|
|
2019-10-31 10:15:13 +08:00
|
|
|
#[doc(hidden)]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register_vcell {
|
|
|
|
($mod_name: ident, $struct_name: ident) => (
|
2020-11-20 03:16:36 +08:00
|
|
|
impl $crate::RegisterR for $struct_name {
|
2019-10-31 10:15:13 +08:00
|
|
|
type R = $mod_name::Read;
|
|
|
|
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-10-31 10:15:13 +08:00
|
|
|
fn read(&self) -> Self::R {
|
|
|
|
let inner = self.inner.get();
|
|
|
|
$mod_name::Read { inner }
|
|
|
|
}
|
|
|
|
}
|
2020-11-20 03:16:36 +08:00
|
|
|
impl $crate::RegisterW for $struct_name {
|
2019-10-31 10:15:13 +08:00
|
|
|
type W = $mod_name::Write;
|
|
|
|
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-10-31 10:15:13 +08:00
|
|
|
fn zeroed() -> $mod_name::Write {
|
|
|
|
$mod_name::Write { inner: 0 }
|
|
|
|
}
|
|
|
|
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-10-31 10:15:13 +08:00
|
|
|
fn write(&mut self, w: Self::W) {
|
|
|
|
self.inner.set(w.inner);
|
|
|
|
}
|
|
|
|
}
|
2020-11-20 03:16:36 +08:00
|
|
|
impl $crate::RegisterRW for $struct_name {
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-10-31 10:15:13 +08:00
|
|
|
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
|
|
|
let r = self.read();
|
|
|
|
let w = $mod_name::Write { inner: r.inner };
|
|
|
|
let w = f(r, w);
|
|
|
|
self.write(w);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-05-07 06:32:45 +08:00
|
|
|
/// Main macro for register definition
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register {
|
|
|
|
// Define read-only register
|
2020-11-20 03:26:18 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, RO, $inner: ty) => (
|
|
|
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, $crate::RO<$inner>, $inner);
|
2020-11-20 03:16:36 +08:00
|
|
|
$crate::register_r!($mod_name, $struct_name);
|
2019-05-07 06:32:45 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
// Define write-only register
|
2020-11-20 03:26:18 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, WO, $inner: ty) => (
|
|
|
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, volatile_register::WO<$inner>, $inner);
|
2020-11-20 03:16:36 +08:00
|
|
|
$crate::register_w!($mod_name, $struct_name);
|
2019-05-07 06:32:45 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
// Define read-write register
|
2020-11-20 03:26:18 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, RW, $inner: ty) => (
|
|
|
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, volatile_register::RW<$inner>, $inner);
|
2020-11-20 03:16:36 +08:00
|
|
|
$crate::register_r!($mod_name, $struct_name);
|
|
|
|
$crate::register_w!($mod_name, $struct_name);
|
|
|
|
$crate::register_rw!($mod_name, $struct_name);
|
2019-05-07 06:32:45 +08:00
|
|
|
);
|
2019-10-31 10:15:13 +08:00
|
|
|
|
|
|
|
// Define read-write register
|
2020-11-20 03:26:18 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, VolatileCell, $inner: ty) => (
|
|
|
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, VolatileCell<$inner>, $inner);
|
2020-11-20 03:16:36 +08:00
|
|
|
$crate::register_vcell!($mod_name, $struct_name);
|
2019-10-31 10:15:13 +08:00
|
|
|
);
|
2020-04-29 21:19:24 +08:00
|
|
|
|
|
|
|
// Define read-write register with mask on write (for WTC mixed access.)
|
2020-11-20 03:26:18 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, RW, $inner: ty, $mask: expr) => (
|
|
|
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, volatile_register::RW<$inner>, $inner);
|
2020-11-20 03:16:36 +08:00
|
|
|
$crate::register_r!($mod_name, $struct_name);
|
|
|
|
$crate::register_w!($mod_name, $struct_name);
|
|
|
|
$crate::register_rw!($mod_name, $struct_name, $mask);
|
2020-04-29 21:19:24 +08:00
|
|
|
);
|
2019-05-07 06:32:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Define a 1-bit field of a register
|
2019-05-07 05:56:53 +08:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register_bit {
|
2019-05-25 05:49:49 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $name: ident, $bit: expr) => (
|
|
|
|
$(#[$outer])*
|
2019-05-07 05:56:53 +08:00
|
|
|
impl $mod_name::Read {
|
2019-05-25 05:49:49 +08:00
|
|
|
#[allow(unused)]
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-07 23:46:37 +08:00
|
|
|
pub fn $name(&self) -> bool {
|
2019-05-07 05:56:53 +08:00
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
self.inner.get_bit($bit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-25 05:49:49 +08:00
|
|
|
$(#[$outer])*
|
2019-05-07 05:56:53 +08:00
|
|
|
impl $mod_name::Write {
|
2019-05-25 05:49:49 +08:00
|
|
|
#[allow(unused)]
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-07 23:46:37 +08:00
|
|
|
pub fn $name(mut self, value: bool) -> Self {
|
2019-05-07 05:56:53 +08:00
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
self.inner.set_bit($bit, value);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2020-04-29 21:19:24 +08:00
|
|
|
|
|
|
|
// Single bit read-only
|
|
|
|
($mod_name: ident, $(#[$outer:meta])* $name: ident, $bit: expr, RO) => (
|
|
|
|
$(#[$outer])*
|
|
|
|
impl $mod_name::Read {
|
|
|
|
#[allow(unused)]
|
|
|
|
#[inline]
|
|
|
|
pub fn $name(&self) -> bool {
|
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
self.inner.get_bit($bit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
// Single bit write to clear. Note that this must be used with WTC register.
|
|
|
|
($mod_name: ident, $(#[$outer:meta])* $name: ident, $bit: expr, WTC) => (
|
|
|
|
$(#[$outer])*
|
|
|
|
impl $mod_name::Read {
|
|
|
|
#[allow(unused)]
|
|
|
|
#[inline]
|
|
|
|
pub fn $name(&self) -> bool {
|
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
self.inner.get_bit($bit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$(#[$outer])*
|
|
|
|
impl $mod_name::Write {
|
2020-05-01 15:38:07 +08:00
|
|
|
/// Clear bit field. (WTC)
|
2020-04-29 21:19:24 +08:00
|
|
|
#[allow(unused)]
|
|
|
|
#[inline]
|
|
|
|
pub fn $name(mut self) -> Self {
|
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
self.inner.set_bit($bit, true);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2019-05-07 05:56:53 +08:00
|
|
|
}
|
|
|
|
|
2019-05-07 06:32:45 +08:00
|
|
|
/// Define a multi-bit field of a register
|
2019-05-07 05:56:53 +08:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register_bits {
|
2019-05-25 05:49:49 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $name: ident, $type: ty, $bit_begin: expr, $bit_end: expr) => (
|
2019-05-07 05:56:53 +08:00
|
|
|
impl $mod_name::Read {
|
2019-05-25 05:49:49 +08:00
|
|
|
#[allow(unused)]
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-25 05:49:49 +08:00
|
|
|
$(#[$outer])*
|
2019-05-07 23:46:37 +08:00
|
|
|
pub fn $name(&self) -> $type {
|
2019-05-07 05:56:53 +08:00
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
self.inner.get_bits($bit_begin..=$bit_end) as $type
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-25 05:49:49 +08:00
|
|
|
#[allow(unused)]
|
|
|
|
$(#[$outer])*
|
2019-05-07 05:56:53 +08:00
|
|
|
impl $mod_name::Write {
|
2019-05-25 05:49:49 +08:00
|
|
|
#[allow(unused)]
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-07 23:46:37 +08:00
|
|
|
pub fn $name(mut self, value: $type) -> Self {
|
2019-05-07 05:56:53 +08:00
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
self.inner.set_bits($bit_begin..=$bit_end, value.into());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2019-05-21 05:01:50 +08:00
|
|
|
|
2019-05-24 00:23:51 +08:00
|
|
|
/// Define a multi-bit field of a register, coerced to a certain type
|
|
|
|
///
|
|
|
|
/// Because read bits are just transmuted to the `$type`, its
|
|
|
|
/// definition must be annotated with `#[repr($bit_type)]`!
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register_bits_typed {
|
2019-05-25 05:49:49 +08:00
|
|
|
($mod_name: ident, $(#[$outer:meta])* $name: ident, $bit_type: ty, $type: ty, $bit_begin: expr, $bit_end: expr) => (
|
2019-05-24 00:23:51 +08:00
|
|
|
impl $mod_name::Read {
|
2019-05-25 05:49:49 +08:00
|
|
|
#[allow(unused)]
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-25 05:49:49 +08:00
|
|
|
$(#[$outer])*
|
2019-05-24 00:23:51 +08:00
|
|
|
pub fn $name(&self) -> $type {
|
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
let bits = self.inner.get_bits($bit_begin..=$bit_end) as $bit_type;
|
|
|
|
unsafe { core::mem::transmute(bits) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl $mod_name::Write {
|
2019-05-25 05:49:49 +08:00
|
|
|
#[allow(unused)]
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-25 05:49:49 +08:00
|
|
|
$(#[$outer])*
|
2019-05-24 00:23:51 +08:00
|
|
|
pub fn $name(mut self, value: $type) -> Self {
|
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
|
|
let bits = (value as $bit_type).into();
|
|
|
|
self.inner.set_bits($bit_begin..=$bit_end, bits);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-05-21 05:01:50 +08:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! register_at {
|
|
|
|
($name: ident, $addr: expr, $ctor: ident) => (
|
|
|
|
impl $name {
|
2019-05-25 05:49:49 +08:00
|
|
|
#[allow(unused)]
|
2020-02-01 03:47:16 +08:00
|
|
|
#[inline]
|
2019-05-21 05:01:50 +08:00
|
|
|
pub fn $ctor() -> &'static mut Self {
|
|
|
|
let addr = $addr as *mut Self;
|
|
|
|
unsafe { &mut *addr }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|