From 30a9171031f85be68c37e55fe4f8063a7eaa2ea8 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 27 Sep 2020 11:31:59 +0800 Subject: [PATCH] lib: replae `usize` with `Register` This ensures we can't write to random values in memory. Signed-off-by: Sean Cross --- src/lib.rs | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 10a5343..43f8969 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,15 @@ use std::convert::TryInto; +pub struct Register { + /// Offset of this register within this CSR + offset: usize, +} + +impl Register { + pub const fn new(offset: usize) -> Register { + Register { offset } + } +} + pub struct Field { /// A bitmask we use to AND to the value, unshifted. /// E.g. for a width of `3` bits, this mask would be 0b111. @@ -66,22 +77,26 @@ where pub fn new(base: *mut T) -> Self { CSR { base } } - pub fn r(&mut self, reg: usize, field: Field) -> T { + pub fn r(&mut self, reg: Register, field: Field) -> T { let usize_base: *mut usize = unsafe { core::mem::transmute(&self.base) }; - ((unsafe { usize_base.add(reg).read_volatile() } >> field.offset) & field.mask) + ((unsafe { usize_base.add(reg.offset).read_volatile() } >> field.offset) & field.mask) .try_into() .unwrap_or_default() } - pub fn rw(&mut self, reg: usize, field: Field, value: T) { + pub fn rw(&mut self, reg: Register, field: Field, value: T) { let usize_base: *mut usize = unsafe { core::mem::transmute(&self.base) }; let value_as_usize: usize = value.try_into().unwrap_or_default() << field.offset; - let previous = unsafe { usize_base.add(reg).read_volatile() } & ! field.mask; - unsafe { usize_base.add(reg).write_volatile(previous | value_as_usize)}; + let previous = unsafe { usize_base.add(reg.offset).read_volatile() } & !field.mask; + unsafe { + usize_base + .add(reg.offset) + .write_volatile(previous | value_as_usize) + }; } - pub fn ow(&mut self, reg: usize, field: Field, value: T) { + pub fn ow(&mut self, reg: Register, field: Field, value: T) { let usize_base: *mut usize = unsafe { core::mem::transmute(&self.base) }; let value_as_usize: usize = value.try_into().unwrap_or_default() << field.offset; - unsafe { usize_base.add(reg).write_volatile(value_as_usize)}; + unsafe { usize_base.add(reg.offset).write_volatile(value_as_usize) }; } } @@ -89,14 +104,15 @@ where mod tests { pub mod pac { pub mod audio { - pub const RX_CTL: usize = 0x0c; + pub const RX_CTL: crate::Register = crate::Register::new(0x0c); pub const RX_CTL_ENABLE: crate::Field = crate::Field::new(1, 0); pub const RX_CTL_RESET: crate::Field = crate::Field::new(1, 1); } pub mod uart { - pub const RXTX: usize = 0x00; + pub const RXTX: crate::Register = crate::Register::new(0x00); pub const RXTX_RXTX: crate::Field = crate::Field::new(8, 0); - pub const TXFULL: usize = 0x04; + + pub const TXFULL: crate::Register = crate::Register::new(0x04); pub const TXFULL_TXFULL: crate::Field = crate::Field::new(1, 0); } }