stm32_eth/
peripherals.rs

1//! Re-export or add abstracted versions of `ETHERNET_MAC`, `ETHERNET_DMA`
2//! and `ETHERNET_PTP` that introduce a delay for some registers on F4 parts.
3
4#[cfg(any(feature = "stm32f107", feature = "stm32f7xx-hal"))]
5pub use crate::hal::pac::{ETHERNET_DMA, ETHERNET_MAC};
6
7#[cfg(all(any(feature = "stm32f107", feature = "stm32f7xx-hal"), feature = "ptp"))]
8pub use crate::hal::pac::ETHERNET_PTP;
9
10#[cfg(feature = "stm32f4xx-hal")]
11pub use pac_override_impl::{ETHERNET_DMA, ETHERNET_MAC};
12
13#[cfg(all(feature = "stm32f4xx-hal", feature = "ptp"))]
14pub use pac_override_impl::ETHERNET_PTP;
15
16#[cfg(feature = "stm32f4xx-hal")]
17mod pac_override_impl {
18    #![allow(non_camel_case_types)]
19
20    macro_rules ! setup_use {
21        ($(($feat:literal, $name:ident)),*) => {
22            $(
23                #[cfg(feature = $feat)]
24                use stm32f4::$name as stm32;
25            )*
26        }
27    }
28
29    setup_use!(
30        ("stm32f407", stm32f407),
31        ("stm32f417", stm32f407),
32        ("stm32f427", stm32f427),
33        ("stm32f429", stm32f429),
34        ("stm32f437", stm32f427),
35        ("stm32f439", stm32f429),
36        ("stm32f469", stm32f469),
37        ("stm32f479", stm32f469)
38    );
39
40    use core::marker::PhantomData;
41
42    use stm32::{
43        ethernet_dma::*, ethernet_mac::*, ethernet_ptp::*, ETHERNET_DMA as PAC_ETHERNET_DMA,
44        ETHERNET_MAC as PAC_ETHERNET_MAC, ETHERNET_PTP as PAC_ETHERNET_PTP,
45    };
46    use stm32f4::{Readable, Reg, RegisterSpec, Resettable, Writable, W};
47
48    pub struct DelayedReg<T: RegisterSpec> {
49        inner: Reg<T>,
50    }
51
52    impl<REG: Readable> DelayedReg<REG> {
53        /// Reads the contents of a `Readable` register.
54        ///
55        /// You can read the raw contents of a register by using `bits`:
56        /// ```ignore
57        /// let bits = periph.reg.read().bits();
58        /// ```
59        /// or get the content of a particular field of a register:
60        /// ```ignore
61        /// let reader = periph.reg.read();
62        /// let bits = reader.field1().bits();
63        /// let flag = reader.field2().bit_is_set();
64        /// ```
65        #[inline(always)]
66        pub fn read(&self) -> REG::Reader {
67            self.inner.read()
68        }
69    }
70
71    impl<REG: Readable + Writable> DelayedReg<REG> {
72        /// Modifies the contents of the register by reading and then writing it.
73        ///
74        /// This version of `modify` _always_ adds a 29 cycle delay to mitigate the effects
75        /// of an erratum.
76        ///
77        /// E.g. to do a read-modify-write sequence to change parts of a register:
78        /// ```ignore
79        /// periph.reg.modify(|r, w| unsafe { w.bits(
80        ///    r.bits() | 3
81        /// ) });
82        /// ```
83        /// or
84        /// ```ignore
85        /// periph.reg.modify(|_, w| w
86        ///     .field1().bits(newfield1bits)
87        ///     .field2().set_bit()
88        ///     .field3().variant(VARIANT)
89        /// );
90        /// ```
91        /// Other fields will have the value they had before the call to `modify`.
92        #[inline(always)]
93        pub fn modify<F>(&self, f: F)
94        where
95            for<'w> F: FnOnce(&REG::Reader, &'w mut REG::Writer) -> &'w mut W<REG>,
96        {
97            delay();
98            self.inner.modify(f)
99        }
100    }
101
102    impl<REG: Writable + Resettable> DelayedReg<REG> {
103        /// Writes the reset value to `Writable` register.
104        ///
105        /// Resets the register to its initial state.
106        /// This version of `reset` _always_ adds a 29 cycle delay to mitigate the effects
107        /// of an erratum.
108        #[inline(always)]
109        #[allow(unused)]
110        pub fn reset(&self) {
111            delay();
112            self.inner.reset()
113        }
114
115        /// Writes bits to a `Writable` register.
116        ///
117        /// This version of `wrote` _always_ adds a 29 cycle delay to mitigate the effects
118        /// of an erratum.
119        ///
120        /// You can write raw bits into a register:
121        /// ```ignore
122        /// periph.reg.write(|w| unsafe { w.bits(rawbits) });
123        /// ```
124        /// or write only the fields you need:
125        /// ```ignore
126        /// periph.reg.write(|w| w
127        ///     .field1().bits(newfield1bits)
128        ///     .field2().set_bit()
129        ///     .field3().variant(VARIANT)
130        /// );
131        /// ```
132        /// In the latter case, other fields will be set to their reset value.
133        #[inline(always)]
134        #[allow(unused)]
135        pub fn write<F>(&self, f: F)
136        where
137            F: FnOnce(&mut REG::Writer) -> &mut W<REG>,
138        {
139            delay();
140            self.inner.write(f)
141        }
142    }
143
144    #[repr(C)]
145    pub struct MacRegisterBlock {
146        #[doc = "0x00 - Ethernet MAC configuration register"]
147        pub maccr: DelayedReg<maccr::MACCR_SPEC>,
148        #[doc = "0x04 - Ethernet MAC frame filter register"]
149        pub macffr: DelayedReg<macffr::MACFFR_SPEC>,
150        #[doc = "0x08 - Ethernet MAC hash table high register"]
151        pub machthr: DelayedReg<machthr::MACHTHR_SPEC>,
152        #[doc = "0x0c - Ethernet MAC hash table low register"]
153        pub machtlr: DelayedReg<machtlr::MACHTLR_SPEC>,
154        #[doc = "0x10 - Ethernet MAC MII address register"]
155        pub macmiiar: Reg<macmiiar::MACMIIAR_SPEC>,
156        #[doc = "0x14 - Ethernet MAC MII data register"]
157        pub macmiidr: Reg<macmiidr::MACMIIDR_SPEC>,
158        #[doc = "0x18 - Ethernet MAC flow control register"]
159        pub macfcr: DelayedReg<macfcr::MACFCR_SPEC>,
160        #[doc = "0x1c - Ethernet MAC VLAN tag register"]
161        pub macvlantr: DelayedReg<macvlantr::MACVLANTR_SPEC>,
162        _reserved8: [u8; 0x0c],
163        #[doc = "0x2c - Ethernet MAC PMT control and status register"]
164        pub macpmtcsr: DelayedReg<macpmtcsr::MACPMTCSR_SPEC>,
165        _reserved9: [u8; 0x04],
166        #[doc = "0x34 - Ethernet MAC debug register"]
167        pub macdbgr: Reg<macdbgr::MACDBGR_SPEC>,
168        #[doc = "0x38 - Ethernet MAC interrupt status register"]
169        pub macsr: Reg<macsr::MACSR_SPEC>,
170        #[doc = "0x3c - Ethernet MAC interrupt mask register"]
171        pub macimr: Reg<macimr::MACIMR_SPEC>,
172        #[doc = "0x40 - Ethernet MAC address 0 high register"]
173        pub maca0hr: DelayedReg<maca0hr::MACA0HR_SPEC>,
174        #[doc = "0x44 - Ethernet MAC address 0 low register"]
175        pub maca0lr: DelayedReg<maca0lr::MACA0LR_SPEC>,
176        #[doc = "0x48 - Ethernet MAC address 1 high register"]
177        pub maca1hr: DelayedReg<maca1hr::MACA1HR_SPEC>,
178        #[doc = "0x4c - Ethernet MAC address1 low register"]
179        pub maca1lr: DelayedReg<maca1lr::MACA1LR_SPEC>,
180        #[doc = "0x50 - Ethernet MAC address 2 high register"]
181        pub maca2hr: DelayedReg<maca2hr::MACA2HR_SPEC>,
182        #[doc = "0x54 - Ethernet MAC address 2 low register"]
183        pub maca2lr: DelayedReg<maca2lr::MACA2LR_SPEC>,
184        #[doc = "0x58 - Ethernet MAC address 3 high register"]
185        pub maca3hr: DelayedReg<maca3hr::MACA3HR_SPEC>,
186        #[doc = "0x5c - Ethernet MAC address 3 low register"]
187        pub maca3lr: DelayedReg<maca3lr::MACA3LR_SPEC>,
188    }
189
190    pub struct ETHERNET_MAC {
191        _marker: PhantomData<*const ()>,
192    }
193
194    unsafe impl core::marker::Send for ETHERNET_MAC {}
195
196    impl ETHERNET_MAC {
197        #[doc = r"Pointer to the register block"]
198        pub const PTR: *const MacRegisterBlock = 0x4002_8000 as *const _;
199
200        #[doc = r"Return the pointer to the register block"]
201        #[inline(always)]
202        pub const fn ptr() -> *const MacRegisterBlock {
203            Self::PTR
204        }
205    }
206
207    impl core::ops::Deref for ETHERNET_MAC {
208        type Target = MacRegisterBlock;
209
210        fn deref(&self) -> &Self::Target {
211            unsafe { &*Self::PTR }
212        }
213    }
214
215    impl From<PAC_ETHERNET_MAC> for ETHERNET_MAC {
216        fn from(_value: PAC_ETHERNET_MAC) -> Self {
217            Self {
218                _marker: Default::default(),
219            }
220        }
221    }
222
223    #[repr(C)]
224    pub struct DmaRegisterBlock {
225        #[doc = "0x00 - Ethernet DMA bus mode register"]
226        pub dmabmr: DelayedReg<dmabmr::DMABMR_SPEC>,
227        #[doc = "0x04 - Ethernet DMA transmit poll demand register"]
228        pub dmatpdr: Reg<dmatpdr::DMATPDR_SPEC>,
229        #[doc = "0x08 - EHERNET DMA receive poll demand register"]
230        pub dmarpdr: Reg<dmarpdr::DMARPDR_SPEC>,
231        #[doc = "0x0c - Ethernet DMA receive descriptor list address register"]
232        pub dmardlar: Reg<dmardlar::DMARDLAR_SPEC>,
233        #[doc = "0x10 - Ethernet DMA transmit descriptor list address register"]
234        pub dmatdlar: Reg<dmatdlar::DMATDLAR_SPEC>,
235        #[doc = "0x14 - Ethernet DMA status register"]
236        pub dmasr: Reg<dmasr::DMASR_SPEC>,
237        #[doc = "0x18 - Ethernet DMA operation mode register"]
238        pub dmaomr: DelayedReg<dmaomr::DMAOMR_SPEC>,
239        #[doc = "0x1c - Ethernet DMA interrupt enable register"]
240        pub dmaier: Reg<dmaier::DMAIER_SPEC>,
241        #[doc = "0x20 - Ethernet DMA missed frame and buffer overflow counter register"]
242        pub dmamfbocr: Reg<dmamfbocr::DMAMFBOCR_SPEC>,
243        #[doc = "0x24 - Ethernet DMA receive status watchdog timer register"]
244        pub dmarswtr: Reg<dmarswtr::DMARSWTR_SPEC>,
245        _reserved10: [u8; 0x20],
246        #[doc = "0x48 - Ethernet DMA current host transmit descriptor register"]
247        pub dmachtdr: Reg<dmachtdr::DMACHTDR_SPEC>,
248        #[doc = "0x4c - Ethernet DMA current host receive descriptor register"]
249        pub dmachrdr: Reg<dmachrdr::DMACHRDR_SPEC>,
250        #[doc = "0x50 - Ethernet DMA current host transmit buffer address register"]
251        pub dmachtbar: Reg<dmachtbar::DMACHTBAR_SPEC>,
252        #[doc = "0x54 - Ethernet DMA current host receive buffer address register"]
253        pub dmachrbar: Reg<dmachrbar::DMACHRBAR_SPEC>,
254    }
255
256    pub struct ETHERNET_DMA {
257        _marker: PhantomData<*const ()>,
258    }
259
260    unsafe impl core::marker::Send for ETHERNET_DMA {}
261
262    impl ETHERNET_DMA {
263        #[doc = r"Pointer to the register block"]
264        pub const PTR: *const DmaRegisterBlock = 0x4002_9000 as *const _;
265
266        pub const fn ptr() -> *const DmaRegisterBlock {
267            Self::PTR
268        }
269    }
270
271    impl core::ops::Deref for ETHERNET_DMA {
272        type Target = DmaRegisterBlock;
273
274        fn deref(&self) -> &Self::Target {
275            unsafe { &*Self::PTR }
276        }
277    }
278
279    impl core::borrow::Borrow<ETHERNET_DMA> for PAC_ETHERNET_DMA {
280        fn borrow(&self) -> &ETHERNET_DMA {
281            &ETHERNET_DMA {
282                _marker: PhantomData,
283            }
284        }
285    }
286
287    impl From<PAC_ETHERNET_DMA> for ETHERNET_DMA {
288        fn from(_value: PAC_ETHERNET_DMA) -> Self {
289            Self {
290                _marker: Default::default(),
291            }
292        }
293    }
294
295    #[repr(C)]
296    pub struct PtpRegisterBlock {
297        #[doc = "0x00 - Ethernet PTP time stamp control register"]
298        pub ptptscr: DelayedReg<ptptscr::PTPTSCR_SPEC>,
299        #[doc = "0x04 - Ethernet PTP subsecond increment register"]
300        pub ptpssir: Reg<ptpssir::PTPSSIR_SPEC>,
301        #[doc = "0x08 - Ethernet PTP time stamp high register"]
302        pub ptptshr: Reg<ptptshr::PTPTSHR_SPEC>,
303        #[doc = "0x0c - Ethernet PTP time stamp low register"]
304        pub ptptslr: Reg<ptptslr::PTPTSLR_SPEC>,
305        #[doc = "0x10 - Ethernet PTP time stamp high update register"]
306        pub ptptshur: Reg<ptptshur::PTPTSHUR_SPEC>,
307        #[doc = "0x14 - Ethernet PTP time stamp low update register"]
308        pub ptptslur: Reg<ptptslur::PTPTSLUR_SPEC>,
309        #[doc = "0x18 - Ethernet PTP time stamp addend register"]
310        pub ptptsar: Reg<ptptsar::PTPTSAR_SPEC>,
311        #[doc = "0x1c - Ethernet PTP target time high register"]
312        pub ptptthr: Reg<ptptthr::PTPTTHR_SPEC>,
313        #[doc = "0x20 - Ethernet PTP target time low register"]
314        pub ptpttlr: Reg<ptpttlr::PTPTTLR_SPEC>,
315        _reserved9: [u8; 0x04],
316        #[doc = "0x28 - Ethernet PTP time stamp status register"]
317        pub ptptssr: Reg<ptptssr::PTPTSSR_SPEC>,
318        #[doc = "0x2c - Ethernet PTP PPS control register"]
319        pub ptpppscr: Reg<ptpppscr::PTPPPSCR_SPEC>,
320    }
321
322    pub struct ETHERNET_PTP {
323        _marker: PhantomData<*const ()>,
324    }
325
326    unsafe impl core::marker::Send for ETHERNET_PTP {}
327
328    impl ETHERNET_PTP {
329        #[doc = r"Pointer to the register block"]
330        pub const PTR: *const PtpRegisterBlock = 0x4002_8700 as *const _;
331
332        #[doc = r"Return the pointer to the register block"]
333        #[inline(always)]
334        #[allow(unused)]
335        pub const fn ptr() -> *const PtpRegisterBlock {
336            Self::PTR
337        }
338    }
339
340    impl core::ops::Deref for ETHERNET_PTP {
341        type Target = PtpRegisterBlock;
342
343        fn deref(&self) -> &Self::Target {
344            unsafe { &*Self::PTR }
345        }
346    }
347
348    impl From<PAC_ETHERNET_PTP> for ETHERNET_PTP {
349        fn from(_value: PAC_ETHERNET_PTP) -> Self {
350            Self {
351                _marker: Default::default(),
352            }
353        }
354    }
355
356    #[inline(always)]
357    /// Preventative measure for issues described in:
358    /// Section 2.11.5 of [ES0182, Rev 13] (for F40x and F41x)
359    /// Section 2.17.5 of [ES0206, Rev 18] (for F42x and F43x)
360    /// Section 2.18.5 of [ES0321, Rev 8] (for F46x and F47x)
361    ///
362    /// [ES0182, Rev 13]: https://www.st.com/resource/en/errata_sheet/es0182-stm32f405407xx-and-stm32f415417xx-device-limitations-stmicroelectronics.pdf
363    /// [ES0206, Rev 18]: https://www.st.com/resource/en/errata_sheet/es0206-stm32f427437-and-stm32f429439-line-limitations-stmicroelectronics.pdf
364    /// [ES0321, Rev 8]: https://www.st.com/resource/en/errata_sheet/es0321-stm32f469xx-and-stm32f479xx-device-errata-stmicroelectronics.pdf
365    fn delay() {
366        // Max speed: 180_000_000 Hz
367        //
368        // Minimum required delay: 4 clocks @ 25 MHz = 160 ns
369        //
370        // Minimum required delay clocks: ceil(180_000_000/25_000_000) * 4 = 29 clocks = 161.111... ns
371        cortex_m::asm::delay(29);
372    }
373}