diff --git a/src/lib/ioreg.rs b/src/lib/ioreg.rs
index 3f99731..bf010f2 100644
--- a/src/lib/ioreg.rs
+++ b/src/lib/ioreg.rs
@@ -15,6 +15,40 @@
#![macro_escape]
+/**
+ * I wish this would work
+ */
+/*
+pub macro_rules! ioregion(
+ ($link:ident $s:ident:$width:ty -> $($reg:ident:$ty:ty),+) => (
+ extern {
+ #[link_name=(stringify!($link))] pub static $s : $link;
+ }
+ struct $link {
+ $(
+ pub $reg : VolatileCellRestricted<$ty,$width>,
+ )+
+ }
+ );
+)*/
+/**
+ * TODO:
+ * * wish: remove $st by making struct type name anonymous/generated
+ * * is order guaranteed? Reference Manual says something about #[repr(...)] attribute
+ */
+pub macro_rules! ioregion(
+ ($link:meta $st:ident,$s:ident:$width:ty -> $($reg:ident:$ty:ty),+) => (
+ extern {
+ #[$link] pub static $s : $st;
+ }
+ struct $st {
+ $(
+ pub $reg : VolatileCellRestricted<$ty,$width>,
+ )+
+ }
+ );
+)
+
macro_rules! ioreg(
($io:ident: $ty:ty, $($reg:ident),+) => (
#[allow(uppercase_variables)]
diff --git a/src/lib/volatile_cell.rs b/src/lib/volatile_cell.rs
index df64a57..12181a4 100644
--- a/src/lib/volatile_cell.rs
+++ b/src/lib/volatile_cell.rs
@@ -52,3 +52,43 @@ impl<T> VolatileCell<T> {
}
}
}
+
+pub struct VolatileCellRestricted<REST,T> {
+ cell : VolatileCell<T>
+}
+
+pub struct R;
+pub struct W;
+pub struct RW;
+
+pub trait VolatileCellReadable<T> {
+ fn get(&self) -> T;
+}
+
+pub trait VolatileCellWritable<T> {
+ fn set(&self, value: T);
+}
+
+impl<T> VolatileCellReadable<T> for VolatileCellRestricted<R,T> {
+ fn get(&self) -> T {
+ self.cell.get()
+ }
+}
+
+impl<T> VolatileCellWritable<T> for VolatileCellRestricted<W,T> {
+ fn set(&self, value: T) {
+ self.cell.set(value)
+ }
+}
+
+impl<T> VolatileCellReadable<T> for VolatileCellRestricted<RW,T> {
+ fn get(&self) -> T {
+ self.cell.get()
+ }
+}
+
+impl<T> VolatileCellWritable<T> for VolatileCellRestricted<RW,T> {
+ fn set(&self, value: T) {
+ self.cell.set(value)
+ }
+}
# So with this in zinc code one can define IO registers like this:
use lib::volatile_cell::VolatileCellRestricted;
use lib::volatile_cell::{R,RW,W};
#[path="../../lib/ioreg.rs"] mod ioreg;
ioregion!(link_name="k20_iomem_MCG" _MCG, MCG:u8 -> C1:RW, C2:RW, C3:RW, C4:RW, C5:RW, C6:RW, S:R)
# And in the apps/ it works like this:
The biggest issue is that the app code needs to include this:
pub use zinc::lib::volatile_cell::VolatileCellReadable;
pub use zinc::lib::volatile_cell::VolatileCellWritable;
But afterwards it works as expected:
MCG.C1.set(0); // works
MCG.S.set(0) // compilation error, because S is RO
let _ = MCG.S.get(); // works