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
99
100
101
102
103
104
105
106
//! Memory-mapped registers.
use vcell::VolatileCell;

use super::*;

/// A memory-mapped register which owns its value.
///
/// [`Register`] is `#[repr(transparent)]` so that it can be placed in a `#[repr(C)]` struct
/// matching a peripheral's memory layout. Casting a value to a pointer to the register block allows
/// simple and safe access to a peripheral's entire register set.
#[repr(transparent)]
pub struct Register<S: RegisterSpec>(VolatileCell<S::Bits>);

pub type PaddingBytes<const BYTES: usize> = [Register<u8>; BYTES];

impl<S: RegisterSpec + RegisterReadable> Register<S> {
    /// Reads the current value of the register, providing access through an instance of
    /// [`RegisterReader`].
    ///
    /// The register's value is only read once: when `read` is called. This is the value accessed
    /// through bit or field getters on [`RegisterReader`] inside the `reader` closure.
    ///
    /// The return value of the `reader` closure is returned by `read`.
    pub fn read<R>(&self, reader: impl FnOnce(&RegisterReader<S>) -> R) -> R {
        let r = RegisterReader::new(self.0.get());
        reader(&r)
    }
}

impl<S: RegisterSpec + RegisterWritable> Register<S> {
    /// Writes a value built by an instance of [`RegisterWriter`], initialised to zero, to the
    /// register.
    ///
    /// The register's value is only written once: when the `writer` closure returns. The value
    /// written is the value built through bit or field setters on [`RegisterWriter`] inside the
    /// `writer` closure.
    ///
    /// # Safety
    /// Setting bits or fields to zero may result in undefined behaviour, as zero is not guaranteed
    /// to be a supported value. Refer to the register's definition to determine valid values.
    pub unsafe fn write_zero(&self, writer: impl FnOnce(&mut RegisterWriter<S>)) {
        let mut w = RegisterWriter::zero();
        writer(&mut w);
        self.0.set(w.bits);
    }
}

impl<S: RegisterSpec + RegisterInitial> Register<S> {
    /// Writes a value built by an instance of [`RegisterWriter`], initialised to the register's
    /// initial value (provided by [`RegisterInitial`]), to the register.
    ///
    /// The register's value is only written once: when the `writer` closure returns. The value
    /// written is the value built through bit or field setters on [`RegisterWriter`] inside the
    /// `writer` closure.
    pub fn write_initial(&self, writer: impl FnOnce(&mut RegisterWriter<S>)) {
        let mut w = RegisterWriter::initial();
        writer(&mut w);
        self.0.set(w.bits);
    }
}

#[macro_export]
macro_rules! memory_mapped_register {
    { $name:ident($bits:ty) } => {
        #[allow(non_camel_case_types)]
        #[allow(clippy::upper_case_acronyms)]
        pub struct $name;

        impl RegisterSpec for $name {
            type Bits = $bits;
        }
    };
    { $name:ident($bits:ty), r } => {
        reg!($name($bits));

        impl RegisterReadable for $name {}
    };
    { $name:ident($bits:ty), w } => {
        reg!($name($bits));

        impl RegisterWritable for $name {}
    };
    { $name:ident($bits:ty), wi=$initial:literal } => {
        reg!($name($bits));

        impl RegisterWritable for $name {}
        impl RegisterInitial for $name {
            const INITIAL_VALUE: Self::Bits = $initial;
        }
    };
    { $name:ident($bits:ty), rw } => {
        reg!($name($bits));

        impl RegisterReadable for $name {}
        impl RegisterWritable for $name {}
    };
    { $name:ident($bits:ty), rwi=$initial:literal } => {
        reg!($name($bits));

        impl RegisterReadable for $name {}
        impl RegisterWritable for $name {}
        impl RegisterInitial for $name {
            const INITIAL_VALUE: Self::Bits = $initial;
        }
    };
}