diff options
author | Brian Cully <bjc@kublai.com> | 2019-09-23 12:45:09 -0400 |
---|---|---|
committer | Brian Cully <bjc@kublai.com> | 2019-09-24 10:55:25 -0400 |
commit | fcc6951c707144ba423b81e03bc2f34b6cfa7286 (patch) | |
tree | 574f64eb11e23920343137e352eb1279f1940a5d /src/pipe/register.rs | |
parent | 77d1fdf044326cfb039728bf94a998f1dd1e8d1e (diff) | |
download | atsamd-usb-host-fcc6951c707144ba423b81e03bc2f34b6cfa7286.tar.gz atsamd-usb-host-fcc6951c707144ba423b81e03bc2f34b6cfa7286.zip |
Mark pipe descriptor register memory as volatile.
Most of the values in the descriptor memory can be modified by the
hardware, so we need to tell Rust that.
Also, refactor the common register setup code into `register.rs`.
Diffstat (limited to 'src/pipe/register.rs')
-rw-r--r-- | src/pipe/register.rs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/pipe/register.rs b/src/pipe/register.rs new file mode 100644 index 0000000..555b70a --- /dev/null +++ b/src/pipe/register.rs @@ -0,0 +1,95 @@ +//! Generic register access. + +use core::marker::PhantomData; +use vcell::VolatileCell; + +pub trait Readable {} +pub trait Writable {} + +pub struct Register<T, Reg> { + value: VolatileCell<T>, + _marker: PhantomData<Reg>, +} + +impl<T, Reg> From<T> for Register<T, Reg> { + fn from(v: T) -> Self { + Self { + value: VolatileCell::new(v), + _marker: PhantomData, + } + } +} + +impl<T, Reg> Register<T, Reg> +where + Self: Readable, + T: Copy, +{ + pub fn read(&self) -> R<T, Self> { + R { + bits: self.value.get(), + _marker: PhantomData, + } + } +} + +impl<T, Reg> Register<T, Reg> +where + Self: Readable + Writable, + T: Copy, +{ + pub fn write<F>(&self, f: F) + where + F: FnOnce(&mut W<T, Self>) -> &mut W<T, Self>, + { + let mut w = W { + bits: self.value.get(), + _marker: PhantomData, + }; + self.value.set(f(&mut w).bits); + } + + pub fn modify<F>(&self, f: F) + where + F: FnOnce(T, &mut W<T, Self>) -> &mut W<T, Self>, + { + let mut w = W { + bits: self.value.get(), + _marker: PhantomData, + }; + self.value.set(f(w.bits, &mut w).bits); + } +} + +pub struct R<T, Reg> { + pub bits: T, + _marker: PhantomData<Reg>, +} + +impl<T, Reg> R<T, Reg> +where + T: Copy, +{ + pub fn new(bits: T) -> Self { + Self { + bits, + _marker: PhantomData, + } + } + + pub fn bits(&self) -> T { + self.bits + } +} + +pub struct W<T, Reg> { + pub bits: T, + _marker: PhantomData<Reg>, +} + +impl<T, Reg> W<T, Reg> { + pub unsafe fn bits(&mut self, bits: T) -> &mut Self { + self.bits = bits; + self + } +} |