aboutsummaryrefslogtreecommitdiffstats
path: root/src/pipe/register.rs
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-09-23 12:45:09 -0400
committerBrian Cully <bjc@kublai.com>2019-09-24 10:55:25 -0400
commitfcc6951c707144ba423b81e03bc2f34b6cfa7286 (patch)
tree574f64eb11e23920343137e352eb1279f1940a5d /src/pipe/register.rs
parent77d1fdf044326cfb039728bf94a998f1dd1e8d1e (diff)
downloadatsamd-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.rs95
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
+ }
+}