diff options
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/pipe.rs | 3 | ||||
-rw-r--r-- | src/pipe/addr.rs | 89 | ||||
-rw-r--r-- | src/pipe/ctrl_pipe.rs | 60 | ||||
-rw-r--r-- | src/pipe/ext_reg.rs | 57 | ||||
-rw-r--r-- | src/pipe/pck_size.rs | 76 | ||||
-rw-r--r-- | src/pipe/register.rs | 95 | ||||
-rw-r--r-- | src/pipe/status_bk.rs | 56 | ||||
-rw-r--r-- | src/pipe/status_pipe.rs | 72 |
9 files changed, 185 insertions, 324 deletions
@@ -16,6 +16,7 @@ starb = "~0.3" log = "~0.4" embedded-hal = "~0.2" atsamd-hal = "~0.7" +vcell = "~0.1" [dev-dependencies.atsamd-hal] version = "~0.7" diff --git a/src/pipe.rs b/src/pipe.rs index 3715149..84e4435 100644 --- a/src/pipe.rs +++ b/src/pipe.rs @@ -6,6 +6,7 @@ pub mod ctrl_pipe; pub mod ext_reg; #[allow(unused)] pub mod pck_size; +pub mod register; #[allow(unused)] pub mod status_bk; #[allow(unused)] @@ -728,7 +729,7 @@ impl PipeDesc { } } -#[repr(C, packed)] +#[repr(C)] // 16 bytes per bank. pub(crate) struct BankDesc { pub addr: Addr, diff --git a/src/pipe/addr.rs b/src/pipe/addr.rs index d71ee2d..81b6bec 100644 --- a/src/pipe/addr.rs +++ b/src/pipe/addr.rs @@ -1,60 +1,29 @@ +use super::register::{Readable, Register, Writable, R as GenR, W as GenW}; + /// § 32.8.7.2 /// Address of the Data Buffer. /// /// Offset: 0x00 & 0x10 /// Reset: 0xxxxxxxxx /// Property: NA -#[derive(Clone, Copy, Debug)] -#[repr(C, packed)] -pub struct Addr(u32); - -pub struct R { - bits: u32, -} - -pub struct W { - bits: u32, -} - -impl Addr { - pub fn read(self) -> R { - R { bits: self.0 } - } - - pub fn write<F>(&mut self, f: F) - where - F: FnOnce(&mut W) -> &mut W, - { - let mut w = W { bits: self.0 }; - f(&mut w); - self.0 = w.bits; - } +pub type Addr = Register<u32, _Addr>; +impl Readable for Addr {} +impl Writable for Addr {} - pub fn modify<F>(&mut self, f: F) - where - for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W, - { - let r = R { bits: self.0 }; - let mut w = W { bits: self.0 }; - f(&r, &mut w); - self.0 = w.bits; - } -} +pub type R = GenR<u32, Addr>; +pub type W = GenW<u32, Addr>; -impl From<u32> for Addr { - fn from(v: u32) -> Self { - Self(v) - } -} +pub struct _Addr; impl R { - /// Value in raw bits. - pub fn bits(&self) -> u32 { - self.bits + pub fn addr(&self) -> AddrR { + AddrR::new(self.bits) } +} - pub fn addr(&self) -> AddrR { - AddrR(self.bits) +impl W { + pub fn addr(&mut self) -> AddrW { + AddrW { w: self } } } @@ -63,36 +32,14 @@ impl R { /// These bits define the data pointer address as an absolute double /// word address in RAM. The two least significant bits must be zero /// to ensure the descriptor is 32-bit aligned. -pub struct AddrR(u32); -impl AddrR { - pub fn bits(&self) -> u32 { - self.0 - } -} - -impl W { - /// Write raw bits. - pub unsafe fn bits(&mut self, v: u32) -> &mut Self { - self.bits = v; - self - } - - pub fn addr(&mut self) -> AddrW { - AddrW { w: self } - } -} +pub type AddrR = GenR<u32, Addr>; pub struct AddrW<'a> { w: &'a mut W, } + impl<'a> AddrW<'a> { - pub unsafe fn bits(self, v: u32) -> &'a mut W { - // Address must be 32-bit aligned. cf §32.8.7.2 of SAMD21 data - // sheet. - debug_assert!(v.trailing_zeros() >= 2); - self.w.bits = v; - self.w + pub unsafe fn bits(self, bits: u32) -> &'a mut W { + self.w.bits(bits) } - - // TODO: "safe" method take a pointer instead of raw u32 } diff --git a/src/pipe/ctrl_pipe.rs b/src/pipe/ctrl_pipe.rs index 360a0e7..5db00c1 100644 --- a/src/pipe/ctrl_pipe.rs +++ b/src/pipe/ctrl_pipe.rs @@ -1,57 +1,20 @@ +use super::register::{Readable, Register, Writable, R as GenR, W as GenW}; + /// Host Control Pipe. /// /// Offset: 0x0c /// Reset: 0xXXXX /// Property: PAC Write-Protection, Write-Synchronized, Read-Synchronized -#[derive(Clone, Copy, Debug)] -#[repr(C, packed)] -pub struct CtrlPipe(u16); - -pub struct R { - bits: u16, -} - -pub struct W { - bits: u16, -} - -impl CtrlPipe { - pub fn read(self) -> R { - R { bits: self.0 } - } - - pub fn write<F>(&mut self, f: F) - where - F: FnOnce(&mut W) -> &mut W, - { - let mut w = W { bits: self.0 }; - f(&mut w); - self.0 = w.bits; - } +pub type CtrlPipe = Register<u16, _CtrlPipe>; +impl Readable for CtrlPipe {} +impl Writable for CtrlPipe {} - pub fn modify<F>(&mut self, f: F) - where - for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W, - { - let r = R { bits: self.0 }; - let mut w = W { bits: self.0 }; - f(&r, &mut w); - self.0 = w.bits; - } -} +pub type R = GenR<u16, CtrlPipe>; +pub type W = GenW<u16, CtrlPipe>; -impl From<u16> for CtrlPipe { - fn from(v: u16) -> Self { - Self(v) - } -} +pub struct _CtrlPipe; impl R { - /// Value in raw bits. - pub fn bits(&self) -> u16 { - self.bits - } - pub fn permax(&self) -> PErMaxR { let bits = { const POS: u8 = 12; @@ -115,13 +78,6 @@ impl PDAddrR { } impl W { - /// Write raw bits. - - pub unsafe fn bits(&mut self, v: u16) -> &mut Self { - self.bits = v; - self - } - pub fn permax(&mut self) -> PErMaxW { PErMaxW { w: self } } diff --git a/src/pipe/ext_reg.rs b/src/pipe/ext_reg.rs index cd2a8dc..95a8f04 100644 --- a/src/pipe/ext_reg.rs +++ b/src/pipe/ext_reg.rs @@ -1,48 +1,21 @@ +use super::register::{Readable, Register, Writable, R as GenR, W as GenW}; + /// §32.8.7.4 /// Extended Register. /// /// Offset: 0x08 /// Reset: 0xxxxxxxx /// Property: NA -#[derive(Clone, Copy, Debug)] -#[repr(C, packed)] -pub(crate) struct ExtReg(u16); - -pub(crate) struct R { - bits: u16, -} - -pub(crate) struct W { - bits: u16, -} - -impl ExtReg { - pub fn read(self) -> R { - R { bits: self.0 } - } +pub type ExtReg = Register<u16, _ExtReg>; +impl Readable for ExtReg {} +impl Writable for ExtReg {} - pub fn write<F>(&mut self, f: F) - where - F: FnOnce(&mut W) -> &mut W, - { - let mut w = W { bits: self.0 }; - f(&mut w); - self.0 = w.bits; - } -} +pub type R = GenR<u16, ExtReg>; +pub type W = GenW<u16, ExtReg>; -impl From<u16> for ExtReg { - fn from(v: u16) -> Self { - Self(v) - } -} +pub struct _ExtReg; impl R { - /// Value in raw bits. - pub fn bits(&self) -> u16 { - self.bits - } - pub fn variable(&self) -> VariableR { let bits = { const POS: u8 = 4; @@ -89,7 +62,7 @@ impl R { /// in the reference document ENGINEERING CHANGE NOTICE, USB 2.0 Link /// Power Management Addendum" and "Table X-X1 in Errata for ECN USB /// 2.0 Link Power Management. -pub(crate) struct VariableR(u16); +pub struct VariableR(u16); impl VariableR { pub fn bits(&self) -> u16 { self.0 @@ -107,7 +80,7 @@ impl VariableR { /// field should be set as described in “Table 2.2 SubPID Types in the /// reference document ENGINEERING CHANGE NOTICE, USB 2.0 Link Power /// Management Addendum”. -pub(crate) struct SubPIDR(u8); +pub struct SubPIDR(u8); impl SubPIDR { pub fn bits(&self) -> u8 { self.0 @@ -115,12 +88,6 @@ impl SubPIDR { } impl W { - /// Write raw bits. - pub unsafe fn bits(&mut self, v: u16) -> &mut Self { - self.bits = v; - self - } - pub fn variable(&mut self) -> VariableW { VariableW { w: self } } @@ -129,7 +96,7 @@ impl W { } } -pub(crate) struct VariableW<'a> { +pub struct VariableW<'a> { w: &'a mut W, } impl<'a> VariableW<'a> { @@ -142,7 +109,7 @@ impl<'a> VariableW<'a> { } } -pub(crate) struct SubPIDW<'a> { +pub struct SubPIDW<'a> { w: &'a mut W, } impl<'a> SubPIDW<'a> { diff --git a/src/pipe/pck_size.rs b/src/pipe/pck_size.rs index 48441a8..f257522 100644 --- a/src/pipe/pck_size.rs +++ b/src/pipe/pck_size.rs @@ -1,58 +1,22 @@ +use super::register::{Readable, Register, Writable, R as GenR, W as GenW}; + /// § 32.8.7.3 /// Packet Size. /// /// Offset: 0x04 & 0x14 /// Reset: 0xxxxxxxxx /// Property: NA -#[derive(Clone, Copy, Debug)] -#[repr(C, packed)] -pub(crate) struct PckSize(u32); - -pub(crate) struct R { - bits: u32, -} - -pub(crate) struct W { - bits: u32, -} - -impl PckSize { - pub fn read(self) -> R { - R { bits: self.0 } - } - pub fn write<F>(&mut self, f: F) - where - F: FnOnce(&mut W) -> &mut W, - { - let mut w = W { bits: self.0 }; - f(&mut w); - self.0 = w.bits; - } +pub type PckSize = Register<u32, _PckSize>; +impl Readable for PckSize {} +impl Writable for PckSize {} - pub fn modify<F>(&mut self, f: F) - where - for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W, - { - let r = R { bits: self.0 }; - let mut w = W { bits: self.0 }; - f(&r, &mut w); - self.0 = w.bits; - } -} +pub type R = GenR<u32, PckSize>; +pub type W = GenW<u32, PckSize>; -impl From<u32> for PckSize { - fn from(v: u32) -> Self { - Self(v) - } -} +pub struct _PckSize; impl R { - /// Value in raw bits. - pub fn bits(&self) -> u32 { - self.bits - } - pub fn auto_zlp(&self) -> AutoZLPR { let bits = { const POS: u8 = 31; @@ -104,7 +68,7 @@ impl R { /// When enabled, the USB module will manage the ZLP handshake by /// hardware. This bit is for OUT pipes only. When disabled the /// handshake should be managed by firmware. -pub(crate) struct AutoZLPR(bool); +pub struct AutoZLPR(bool); impl AutoZLPR { pub fn bit(&self) -> bool { self.0 @@ -125,7 +89,7 @@ impl AutoZLPR { /// /// These bits are cleared upon sending a USB reset. #[derive(Clone, Copy, Debug, PartialEq)] -pub(crate) enum SizeR { +pub enum SizeR { Bytes8, Bytes16, Bytes32, @@ -204,7 +168,7 @@ impl From<u8> for SizeR { /// For OUT pipes, MULTI_PACKET_SIZE holds the total data size for the /// complete transfer. This value must be a multiple of the maximum /// packet size. -pub(crate) struct MultiPacketSizeR(u16); +pub struct MultiPacketSizeR(u16); impl MultiPacketSizeR { pub fn bits(&self) -> u16 { self.0 @@ -217,7 +181,7 @@ impl MultiPacketSizeR { /// sent in the last OUT or SETUP transaction for an OUT pipe, or of /// the number of bytes to be received in the next IN transaction for /// an input pipe. -pub(crate) struct ByteCountR(u16); +pub struct ByteCountR(u16); impl ByteCountR { pub fn bits(&self) -> u16 { self.0 @@ -225,12 +189,6 @@ impl ByteCountR { } impl W { - /// Write raw bits. - pub unsafe fn bits(&mut self, v: u32) -> &mut Self { - self.bits = v; - self - } - pub fn auto_zlp(&mut self) -> AutoZLPW { AutoZLPW { w: self } } @@ -248,7 +206,7 @@ impl W { } } -pub(crate) struct AutoZLPW<'a> { +pub struct AutoZLPW<'a> { w: &'a mut W, } impl<'a> AutoZLPW<'a> { @@ -270,7 +228,7 @@ impl<'a> AutoZLPW<'a> { } #[derive(Copy, Clone, Debug, PartialEq)] -pub(crate) enum SizeW { +pub enum SizeW { Bytes8, Bytes16, Bytes32, @@ -296,7 +254,7 @@ impl SizeW { } /// Proxy for `SizeW` -pub(crate) struct _SizeW<'a> { +pub struct _SizeW<'a> { w: &'a mut W, } impl<'a> _SizeW<'a> { @@ -345,7 +303,7 @@ impl<'a> _SizeW<'a> { } } -pub(crate) struct MultiPacketSizeW<'a> { +pub struct MultiPacketSizeW<'a> { w: &'a mut W, } impl<'a> MultiPacketSizeW<'a> { @@ -360,7 +318,7 @@ impl<'a> MultiPacketSizeW<'a> { } } -pub(crate) struct ByteCountW<'a> { +pub struct ByteCountW<'a> { w: &'a mut W, } impl<'a> ByteCountW<'a> { 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 + } +} diff --git a/src/pipe/status_bk.rs b/src/pipe/status_bk.rs index 50a549c..892da96 100644 --- a/src/pipe/status_bk.rs +++ b/src/pipe/status_bk.rs @@ -1,48 +1,22 @@ +use super::register::{Readable, Register, Writable, R as GenR, W as GenW}; + /// §32.8.7.5 /// Host Status Bank. /// /// Offset: 0x0a & 0x1a /// Reset: 0xxxxxxx /// Property: NA -#[derive(Clone, Copy, Debug)] -#[repr(C, packed)] -pub(crate) struct StatusBk(u8); - -pub(crate) struct R { - bits: u8, -} -pub(crate) struct W { - bits: u8, -} +pub type StatusBk = Register<u8, _StatusBk>; +impl Readable for StatusBk {} +impl Writable for StatusBk {} -impl StatusBk { - pub fn read(self) -> R { - R { bits: self.0 } - } - - pub fn write<F>(&mut self, f: F) - where - F: FnOnce(&mut W) -> &mut W, - { - let mut w = W { bits: self.0 }; - f(&mut w); - self.0 = w.bits; - } -} +pub type R = GenR<u8, StatusBk>; +pub type W = GenW<u8, StatusBk>; -impl From<u8> for StatusBk { - fn from(v: u8) -> Self { - Self(v) - } -} +pub struct _StatusBk; impl R { - /// Value in raw bits. - pub fn bits(&self) -> u8 { - self.bits - } - pub fn errorflow(&self) -> ErrorFlowR { let bits = { const POS: u8 = 1; @@ -75,7 +49,7 @@ impl R { /// transfer, a NAK handshake has been received. For Isochronous IN /// transfer, an overrun condition has occurred. For Isochronous OUT /// transfer, an underflow condition has occurred. -pub(crate) struct ErrorFlowR(bool); +pub struct ErrorFlowR(bool); impl ErrorFlowR { pub fn bit(&self) -> bool { self.0 @@ -96,7 +70,7 @@ impl ErrorFlowR { /// /// This bit is set when a CRC error has been detected in an /// isochronous IN endpoint bank. -pub(crate) struct CRCErrR(bool); +pub struct CRCErrR(bool); impl CRCErrR { pub fn bit(&self) -> bool { self.0 @@ -112,12 +86,6 @@ impl CRCErrR { } impl W { - /// Write raw bits. - pub unsafe fn bits(&mut self, v: u8) -> &mut Self { - self.bits = v; - self - } - pub fn errorflow(&mut self) -> ErrorFlowW { ErrorFlowW { w: self } } @@ -127,7 +95,7 @@ impl W { } } -pub(crate) struct ErrorFlowW<'a> { +pub struct ErrorFlowW<'a> { w: &'a mut W, } impl<'a> ErrorFlowW<'a> { @@ -148,7 +116,7 @@ impl<'a> ErrorFlowW<'a> { } } -pub(crate) struct CRCErrW<'a> { +pub struct CRCErrW<'a> { w: &'a mut W, } impl<'a> CRCErrW<'a> { diff --git a/src/pipe/status_pipe.rs b/src/pipe/status_pipe.rs index d7db9c6..9bd1e32 100644 --- a/src/pipe/status_pipe.rs +++ b/src/pipe/status_pipe.rs @@ -1,46 +1,20 @@ +use super::register::{Readable, Register, Writable, R as GenR, W as GenW}; + /// Host Status Pipe. /// /// Offset: 0x0e & 0x1e /// Reset: 0xxxxxx /// Property: PAC Write-Protection, Write-Synchronized, Read-Synchronized -#[derive(Clone, Copy, Debug)] -#[repr(C, packed)] -pub(crate) struct StatusPipe(u8); - -pub(crate) struct R { - bits: u8, -} -pub(crate) struct W { - bits: u8, -} -impl StatusPipe { - pub fn read(self) -> R { - R { bits: self.0 } - } +pub type StatusPipe = Register<u8, _StatusPipe>; +impl Readable for StatusPipe {} +impl Writable for StatusPipe {} - pub fn write<F>(&mut self, f: F) - where - F: FnOnce(&mut W) -> &mut W, - { - let mut w = W { bits: self.0 }; - f(&mut w); - self.0 = w.bits; - } -} - -impl From<u8> for StatusPipe { - fn from(v: u8) -> Self { - Self(v) - } -} +pub type R = GenR<u8, StatusPipe>; +pub type W = GenW<u8, StatusPipe>; +pub struct _StatusPipe; impl R { - /// Value in raw bits. - pub fn bits(&self) -> u8 { - self.bits - } - pub fn ercnt(&self) -> ErCntR { let bits = { const POS: u8 = 5; @@ -109,7 +83,7 @@ impl R { /// Pipe Error Counter /// /// The number of errors detected on the pipe. -pub(crate) struct ErCntR(u8); +pub struct ErCntR(u8); impl ErCntR { pub fn bits(&self) -> u8 { self.0 @@ -122,7 +96,7 @@ impl ErCntR { /// /// This bit is set when a CRC 16 error has been detected during a IN /// transactions. -pub(crate) struct CRC16ErR(bool); +pub struct CRC16ErR(bool); impl CRC16ErR { pub fn bit(&self) -> bool { self.0 @@ -143,7 +117,7 @@ impl CRC16ErR { /// /// This bit is set when a Time Out error has been detected during a /// USB transaction. -pub(crate) struct TOutErrR(bool); +pub struct TOutErrR(bool); impl TOutErrR { pub fn bit(&self) -> bool { self.0 @@ -164,7 +138,7 @@ impl TOutErrR { /// /// This bit is set when a PID error has been detected during a USB /// transaction. -pub(crate) struct PIDErR(bool); +pub struct PIDErR(bool); impl PIDErR { pub fn bit(&self) -> bool { self.0 @@ -185,7 +159,7 @@ impl PIDErR { /// /// This bit is set when a Data PID error has been detected during a /// USB transaction. -pub(crate) struct DaPIDErR(bool); +pub struct DaPIDErR(bool); impl DaPIDErR { pub fn bit(&self) -> bool { self.0 @@ -205,7 +179,7 @@ impl DaPIDErR { /// This bit defines the Data Toggle Error Status. /// /// This bit is set when a Data Toggle Error has been detected. -pub(crate) struct DTglErR(bool); +pub struct DTglErR(bool); impl DTglErR { pub fn bit(&self) -> bool { self.0 @@ -221,12 +195,6 @@ impl DTglErR { } impl W { - /// Write raw bits. - pub unsafe fn bits(&mut self, v: u8) -> &mut Self { - self.bits = v; - self - } - pub fn ercnt(&mut self) -> ErCntW { ErCntW { w: self } } @@ -255,7 +223,7 @@ impl W { /// Pipe Error Counter /// /// The number of errors detected on the pipe. -pub(crate) struct ErCntW<'a> { +pub struct ErCntW<'a> { w: &'a mut W, } impl<'a> ErCntW<'a> { @@ -278,7 +246,7 @@ impl<'a> ErCntW<'a> { /// /// This bit is set when a CRC 16 error has been detected during a IN /// transactions. -pub(crate) struct CRC16ErW<'a> { +pub struct CRC16ErW<'a> { w: &'a mut W, } impl<'a> CRC16ErW<'a> { @@ -305,7 +273,7 @@ impl<'a> CRC16ErW<'a> { /// /// This bit is set when a Time Out error has been detected during a /// USB transaction. -pub(crate) struct TOutErW<'a> { +pub struct TOutErW<'a> { w: &'a mut W, } impl<'a> TOutErW<'a> { @@ -332,7 +300,7 @@ impl<'a> TOutErW<'a> { /// /// This bit is set when a PID error has been detected during a USB /// transaction. -pub(crate) struct PIDErW<'a> { +pub struct PIDErW<'a> { w: &'a mut W, } impl<'a> PIDErW<'a> { @@ -359,7 +327,7 @@ impl<'a> PIDErW<'a> { /// /// This bit is set when a Data PID error has been detected during a /// USB transaction. -pub(crate) struct DaPIDErW<'a> { +pub struct DaPIDErW<'a> { w: &'a mut W, } impl<'a> DaPIDErW<'a> { @@ -385,7 +353,7 @@ impl<'a> DaPIDErW<'a> { /// This bit defines the Data Toggle Error Status. /// /// This bit is set when a Data Toggle Error has been detected. -pub(crate) struct DTglErW<'a> { +pub struct DTglErW<'a> { w: &'a mut W, } impl<'a> DTglErW<'a> { |