stm32_eth/
peripherals.rs

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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
//! Re-export or add abstracted versions of `ETHERNET_MAC`, `ETHERNET_DMA`
//! and `ETHERNET_PTP` that introduce a delay for some registers on F4 parts.

#[cfg(any(feature = "stm32f107", feature = "stm32f7xx-hal"))]
pub use crate::hal::pac::{ETHERNET_DMA, ETHERNET_MAC};

#[cfg(all(any(feature = "stm32f107", feature = "stm32f7xx-hal"), feature = "ptp"))]
pub use crate::hal::pac::ETHERNET_PTP;

#[cfg(feature = "stm32f4xx-hal")]
pub use pac_override_impl::{ETHERNET_DMA, ETHERNET_MAC};

#[cfg(all(feature = "stm32f4xx-hal", feature = "ptp"))]
pub use pac_override_impl::ETHERNET_PTP;

#[cfg(feature = "stm32f4xx-hal")]
mod pac_override_impl {
    #![allow(non_camel_case_types)]

    macro_rules ! setup_use {
        ($(($feat:literal, $name:ident)),*) => {
            $(
                #[cfg(feature = $feat)]
                use stm32f4::$name as stm32;
            )*
        }
    }

    setup_use!(
        ("stm32f407", stm32f407),
        ("stm32f417", stm32f407),
        ("stm32f427", stm32f427),
        ("stm32f429", stm32f429),
        ("stm32f437", stm32f427),
        ("stm32f439", stm32f429),
        ("stm32f469", stm32f469),
        ("stm32f479", stm32f469)
    );

    use core::marker::PhantomData;

    use stm32::{
        ethernet_dma::*, ethernet_mac::*, ethernet_ptp::*, ETHERNET_DMA as PAC_ETHERNET_DMA,
        ETHERNET_MAC as PAC_ETHERNET_MAC, ETHERNET_PTP as PAC_ETHERNET_PTP,
    };
    use stm32f4::{Readable, Reg, RegisterSpec, Resettable, Writable, W};

    pub struct DelayedReg<T: RegisterSpec> {
        inner: Reg<T>,
    }

    impl<REG: Readable> DelayedReg<REG> {
        /// Reads the contents of a `Readable` register.
        ///
        /// You can read the raw contents of a register by using `bits`:
        /// ```ignore
        /// let bits = periph.reg.read().bits();
        /// ```
        /// or get the content of a particular field of a register:
        /// ```ignore
        /// let reader = periph.reg.read();
        /// let bits = reader.field1().bits();
        /// let flag = reader.field2().bit_is_set();
        /// ```
        #[inline(always)]
        pub fn read(&self) -> REG::Reader {
            self.inner.read()
        }
    }

    impl<REG: Readable + Writable> DelayedReg<REG> {
        /// Modifies the contents of the register by reading and then writing it.
        ///
        /// This version of `modify` _always_ adds a 29 cycle delay to mitigate the effects
        /// of an erratum.
        ///
        /// E.g. to do a read-modify-write sequence to change parts of a register:
        /// ```ignore
        /// periph.reg.modify(|r, w| unsafe { w.bits(
        ///    r.bits() | 3
        /// ) });
        /// ```
        /// or
        /// ```ignore
        /// periph.reg.modify(|_, w| w
        ///     .field1().bits(newfield1bits)
        ///     .field2().set_bit()
        ///     .field3().variant(VARIANT)
        /// );
        /// ```
        /// Other fields will have the value they had before the call to `modify`.
        #[inline(always)]
        pub fn modify<F>(&self, f: F)
        where
            for<'w> F: FnOnce(&REG::Reader, &'w mut REG::Writer) -> &'w mut W<REG>,
        {
            delay();
            self.inner.modify(f)
        }
    }

    impl<REG: Writable + Resettable> DelayedReg<REG> {
        /// Writes the reset value to `Writable` register.
        ///
        /// Resets the register to its initial state.
        /// This version of `reset` _always_ adds a 29 cycle delay to mitigate the effects
        /// of an erratum.
        #[inline(always)]
        #[allow(unused)]
        pub fn reset(&self) {
            delay();
            self.inner.reset()
        }

        /// Writes bits to a `Writable` register.
        ///
        /// This version of `wrote` _always_ adds a 29 cycle delay to mitigate the effects
        /// of an erratum.
        ///
        /// You can write raw bits into a register:
        /// ```ignore
        /// periph.reg.write(|w| unsafe { w.bits(rawbits) });
        /// ```
        /// or write only the fields you need:
        /// ```ignore
        /// periph.reg.write(|w| w
        ///     .field1().bits(newfield1bits)
        ///     .field2().set_bit()
        ///     .field3().variant(VARIANT)
        /// );
        /// ```
        /// In the latter case, other fields will be set to their reset value.
        #[inline(always)]
        #[allow(unused)]
        pub fn write<F>(&self, f: F)
        where
            F: FnOnce(&mut REG::Writer) -> &mut W<REG>,
        {
            delay();
            self.inner.write(f)
        }
    }

    #[repr(C)]
    pub struct MacRegisterBlock {
        #[doc = "0x00 - Ethernet MAC configuration register"]
        pub maccr: DelayedReg<maccr::MACCR_SPEC>,
        #[doc = "0x04 - Ethernet MAC frame filter register"]
        pub macffr: DelayedReg<macffr::MACFFR_SPEC>,
        #[doc = "0x08 - Ethernet MAC hash table high register"]
        pub machthr: DelayedReg<machthr::MACHTHR_SPEC>,
        #[doc = "0x0c - Ethernet MAC hash table low register"]
        pub machtlr: DelayedReg<machtlr::MACHTLR_SPEC>,
        #[doc = "0x10 - Ethernet MAC MII address register"]
        pub macmiiar: Reg<macmiiar::MACMIIAR_SPEC>,
        #[doc = "0x14 - Ethernet MAC MII data register"]
        pub macmiidr: Reg<macmiidr::MACMIIDR_SPEC>,
        #[doc = "0x18 - Ethernet MAC flow control register"]
        pub macfcr: DelayedReg<macfcr::MACFCR_SPEC>,
        #[doc = "0x1c - Ethernet MAC VLAN tag register"]
        pub macvlantr: DelayedReg<macvlantr::MACVLANTR_SPEC>,
        _reserved8: [u8; 0x0c],
        #[doc = "0x2c - Ethernet MAC PMT control and status register"]
        pub macpmtcsr: DelayedReg<macpmtcsr::MACPMTCSR_SPEC>,
        _reserved9: [u8; 0x04],
        #[doc = "0x34 - Ethernet MAC debug register"]
        pub macdbgr: Reg<macdbgr::MACDBGR_SPEC>,
        #[doc = "0x38 - Ethernet MAC interrupt status register"]
        pub macsr: Reg<macsr::MACSR_SPEC>,
        #[doc = "0x3c - Ethernet MAC interrupt mask register"]
        pub macimr: Reg<macimr::MACIMR_SPEC>,
        #[doc = "0x40 - Ethernet MAC address 0 high register"]
        pub maca0hr: DelayedReg<maca0hr::MACA0HR_SPEC>,
        #[doc = "0x44 - Ethernet MAC address 0 low register"]
        pub maca0lr: DelayedReg<maca0lr::MACA0LR_SPEC>,
        #[doc = "0x48 - Ethernet MAC address 1 high register"]
        pub maca1hr: DelayedReg<maca1hr::MACA1HR_SPEC>,
        #[doc = "0x4c - Ethernet MAC address1 low register"]
        pub maca1lr: DelayedReg<maca1lr::MACA1LR_SPEC>,
        #[doc = "0x50 - Ethernet MAC address 2 high register"]
        pub maca2hr: DelayedReg<maca2hr::MACA2HR_SPEC>,
        #[doc = "0x54 - Ethernet MAC address 2 low register"]
        pub maca2lr: DelayedReg<maca2lr::MACA2LR_SPEC>,
        #[doc = "0x58 - Ethernet MAC address 3 high register"]
        pub maca3hr: DelayedReg<maca3hr::MACA3HR_SPEC>,
        #[doc = "0x5c - Ethernet MAC address 3 low register"]
        pub maca3lr: DelayedReg<maca3lr::MACA3LR_SPEC>,
    }

    pub struct ETHERNET_MAC {
        _marker: PhantomData<*const ()>,
    }

    unsafe impl core::marker::Send for ETHERNET_MAC {}

    impl ETHERNET_MAC {
        #[doc = r"Pointer to the register block"]
        pub const PTR: *const MacRegisterBlock = 0x4002_8000 as *const _;

        #[doc = r"Return the pointer to the register block"]
        #[inline(always)]
        pub const fn ptr() -> *const MacRegisterBlock {
            Self::PTR
        }
    }

    impl core::ops::Deref for ETHERNET_MAC {
        type Target = MacRegisterBlock;

        fn deref(&self) -> &Self::Target {
            unsafe { &*Self::PTR }
        }
    }

    impl From<PAC_ETHERNET_MAC> for ETHERNET_MAC {
        fn from(_value: PAC_ETHERNET_MAC) -> Self {
            Self {
                _marker: Default::default(),
            }
        }
    }

    #[repr(C)]
    pub struct DmaRegisterBlock {
        #[doc = "0x00 - Ethernet DMA bus mode register"]
        pub dmabmr: DelayedReg<dmabmr::DMABMR_SPEC>,
        #[doc = "0x04 - Ethernet DMA transmit poll demand register"]
        pub dmatpdr: Reg<dmatpdr::DMATPDR_SPEC>,
        #[doc = "0x08 - EHERNET DMA receive poll demand register"]
        pub dmarpdr: Reg<dmarpdr::DMARPDR_SPEC>,
        #[doc = "0x0c - Ethernet DMA receive descriptor list address register"]
        pub dmardlar: Reg<dmardlar::DMARDLAR_SPEC>,
        #[doc = "0x10 - Ethernet DMA transmit descriptor list address register"]
        pub dmatdlar: Reg<dmatdlar::DMATDLAR_SPEC>,
        #[doc = "0x14 - Ethernet DMA status register"]
        pub dmasr: Reg<dmasr::DMASR_SPEC>,
        #[doc = "0x18 - Ethernet DMA operation mode register"]
        pub dmaomr: DelayedReg<dmaomr::DMAOMR_SPEC>,
        #[doc = "0x1c - Ethernet DMA interrupt enable register"]
        pub dmaier: Reg<dmaier::DMAIER_SPEC>,
        #[doc = "0x20 - Ethernet DMA missed frame and buffer overflow counter register"]
        pub dmamfbocr: Reg<dmamfbocr::DMAMFBOCR_SPEC>,
        #[doc = "0x24 - Ethernet DMA receive status watchdog timer register"]
        pub dmarswtr: Reg<dmarswtr::DMARSWTR_SPEC>,
        _reserved10: [u8; 0x20],
        #[doc = "0x48 - Ethernet DMA current host transmit descriptor register"]
        pub dmachtdr: Reg<dmachtdr::DMACHTDR_SPEC>,
        #[doc = "0x4c - Ethernet DMA current host receive descriptor register"]
        pub dmachrdr: Reg<dmachrdr::DMACHRDR_SPEC>,
        #[doc = "0x50 - Ethernet DMA current host transmit buffer address register"]
        pub dmachtbar: Reg<dmachtbar::DMACHTBAR_SPEC>,
        #[doc = "0x54 - Ethernet DMA current host receive buffer address register"]
        pub dmachrbar: Reg<dmachrbar::DMACHRBAR_SPEC>,
    }

    pub struct ETHERNET_DMA {
        _marker: PhantomData<*const ()>,
    }

    unsafe impl core::marker::Send for ETHERNET_DMA {}

    impl ETHERNET_DMA {
        #[doc = r"Pointer to the register block"]
        pub const PTR: *const DmaRegisterBlock = 0x4002_9000 as *const _;

        pub const fn ptr() -> *const DmaRegisterBlock {
            Self::PTR
        }
    }

    impl core::ops::Deref for ETHERNET_DMA {
        type Target = DmaRegisterBlock;

        fn deref(&self) -> &Self::Target {
            unsafe { &*Self::PTR }
        }
    }

    impl core::borrow::Borrow<ETHERNET_DMA> for PAC_ETHERNET_DMA {
        fn borrow(&self) -> &ETHERNET_DMA {
            &ETHERNET_DMA {
                _marker: PhantomData,
            }
        }
    }

    impl From<PAC_ETHERNET_DMA> for ETHERNET_DMA {
        fn from(_value: PAC_ETHERNET_DMA) -> Self {
            Self {
                _marker: Default::default(),
            }
        }
    }

    #[repr(C)]
    pub struct PtpRegisterBlock {
        #[doc = "0x00 - Ethernet PTP time stamp control register"]
        pub ptptscr: DelayedReg<ptptscr::PTPTSCR_SPEC>,
        #[doc = "0x04 - Ethernet PTP subsecond increment register"]
        pub ptpssir: Reg<ptpssir::PTPSSIR_SPEC>,
        #[doc = "0x08 - Ethernet PTP time stamp high register"]
        pub ptptshr: Reg<ptptshr::PTPTSHR_SPEC>,
        #[doc = "0x0c - Ethernet PTP time stamp low register"]
        pub ptptslr: Reg<ptptslr::PTPTSLR_SPEC>,
        #[doc = "0x10 - Ethernet PTP time stamp high update register"]
        pub ptptshur: Reg<ptptshur::PTPTSHUR_SPEC>,
        #[doc = "0x14 - Ethernet PTP time stamp low update register"]
        pub ptptslur: Reg<ptptslur::PTPTSLUR_SPEC>,
        #[doc = "0x18 - Ethernet PTP time stamp addend register"]
        pub ptptsar: Reg<ptptsar::PTPTSAR_SPEC>,
        #[doc = "0x1c - Ethernet PTP target time high register"]
        pub ptptthr: Reg<ptptthr::PTPTTHR_SPEC>,
        #[doc = "0x20 - Ethernet PTP target time low register"]
        pub ptpttlr: Reg<ptpttlr::PTPTTLR_SPEC>,
        _reserved9: [u8; 0x04],
        #[doc = "0x28 - Ethernet PTP time stamp status register"]
        pub ptptssr: Reg<ptptssr::PTPTSSR_SPEC>,
        #[doc = "0x2c - Ethernet PTP PPS control register"]
        pub ptpppscr: Reg<ptpppscr::PTPPPSCR_SPEC>,
    }

    pub struct ETHERNET_PTP {
        _marker: PhantomData<*const ()>,
    }

    unsafe impl core::marker::Send for ETHERNET_PTP {}

    impl ETHERNET_PTP {
        #[doc = r"Pointer to the register block"]
        pub const PTR: *const PtpRegisterBlock = 0x4002_8700 as *const _;

        #[doc = r"Return the pointer to the register block"]
        #[inline(always)]
        #[allow(unused)]
        pub const fn ptr() -> *const PtpRegisterBlock {
            Self::PTR
        }
    }

    impl core::ops::Deref for ETHERNET_PTP {
        type Target = PtpRegisterBlock;

        fn deref(&self) -> &Self::Target {
            unsafe { &*Self::PTR }
        }
    }

    impl From<PAC_ETHERNET_PTP> for ETHERNET_PTP {
        fn from(_value: PAC_ETHERNET_PTP) -> Self {
            Self {
                _marker: Default::default(),
            }
        }
    }

    #[inline(always)]
    /// Preventative measure for issues described in:
    /// Section 2.11.5 of [ES0182, Rev 13] (for F40x and F41x)
    /// Section 2.17.5 of [ES0206, Rev 18] (for F42x and F43x)
    /// Section 2.18.5 of [ES0321, Rev 8] (for F46x and F47x)
    ///
    /// [ES0182, Rev 13]: https://www.st.com/resource/en/errata_sheet/es0182-stm32f405407xx-and-stm32f415417xx-device-limitations-stmicroelectronics.pdf
    /// [ES0206, Rev 18]: https://www.st.com/resource/en/errata_sheet/es0206-stm32f427437-and-stm32f429439-line-limitations-stmicroelectronics.pdf
    /// [ES0321, Rev 8]: https://www.st.com/resource/en/errata_sheet/es0321-stm32f469xx-and-stm32f479xx-device-errata-stmicroelectronics.pdf
    fn delay() {
        // Max speed: 180_000_000 Hz
        //
        // Minimum required delay: 4 clocks @ 25 MHz = 160 ns
        //
        // Minimum required delay clocks: ceil(180_000_000/25_000_000) * 4 = 29 clocks = 161.111... ns
        cortex_m::asm::delay(29);
    }
}