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 VolatileCell { } } } + +pub struct VolatileCellRestricted { + cell : VolatileCell +} + +pub struct R; +pub struct W; +pub struct RW; + +pub trait VolatileCellReadable { + fn get(&self) -> T; +} + +pub trait VolatileCellWritable { + fn set(&self, value: T); +} + +impl VolatileCellReadable for VolatileCellRestricted { + fn get(&self) -> T { + self.cell.get() + } +} + +impl VolatileCellWritable for VolatileCellRestricted { + fn set(&self, value: T) { + self.cell.set(value) + } +} + +impl VolatileCellReadable for VolatileCellRestricted { + fn get(&self) -> T { + self.cell.get() + } +} + +impl VolatileCellWritable for VolatileCellRestricted { + 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