aboutsummaryrefslogtreecommitdiffstats
path: root/usbh/src/pipe/addr.rs
blob: aa260481390f58b33cdd215fcd3068340c694a14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/// § 32.8.7.2
/// Address of the Data Buffer.
///
/// Offset: 0x00 & 0x10
/// Reset: 0xxxxxxxxx
/// Property: NA
#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
pub(crate) struct Addr(u32);

pub(crate) struct R {
    bits: u32,
}

pub(crate) 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 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;
    }
}

impl From<u32> for Addr {
    fn from(v: u32) -> Self {
        Self(v)
    }
}

impl R {
    /// Value in raw bits.
    pub fn bits(&self) -> u32 {
        self.bits
    }

    pub fn addr(&self) -> AddrR {
        AddrR(self.bits)
    }
}

/// Data Pointer Address Value
///
/// 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(crate) 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(crate) 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.
        assert!((v & 0x3) == 0);
        self.w.bits = v;
        self.w
    }

    // TODO: "safe" method take a pointer instead of raw u32
}