stm32f3xx_hal/
usb.rs

1//! # USB peripheral.
2//!
3//! Mostly builds upon the [`stm32_usbd`] crate.
4//!
5//! ## Examples
6//!
7//! See [examples/usb_serial.rs] for a usage example.
8//!
9//! [examples/usb_serial.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/usb_serial.rs
10
11use core::fmt;
12
13use crate::pac::USB;
14use crate::rcc::{Enable, Reset};
15use stm32_usbd::UsbPeripheral;
16
17use crate::gpio;
18use crate::gpio::gpioa::{PA11, PA12};
19#[allow(clippy::module_name_repetitions)]
20pub use stm32_usbd::UsbBus;
21
22/// Trait implemented by all pins that can be the "D-" pin for the USB peripheral
23pub trait DmPin: crate::private::Sealed {}
24
25/// Trait implemented by all pins that can be the "D+" pin for the USB peripheral
26pub trait DpPin: crate::private::Sealed {}
27
28#[cfg(any(feature = "stm32f303xb", feature = "stm32f303xc"))]
29impl DmPin for PA11<gpio::AF14<gpio::PushPull>> {}
30
31#[cfg(any(feature = "stm32f303xb", feature = "stm32f303xc"))]
32impl DpPin for PA12<gpio::AF14<gpio::PushPull>> {}
33
34#[cfg(any(feature = "stm32f303xd", feature = "stm32f303xe"))]
35impl<Mode> DmPin for PA11<Mode> {}
36
37#[cfg(any(feature = "stm32f303xd", feature = "stm32f303xe"))]
38impl<Mode> DpPin for PA12<Mode> {}
39
40/// USB Peripheral
41///
42/// Constructs the peripheral, which
43/// than gets passed to the [`UsbBus`].
44pub struct Peripheral<Dm: DmPin, Dp: DpPin> {
45    /// USB Register Block
46    pub usb: USB,
47    /// Data Negativ Pin
48    pub pin_dm: Dm,
49    /// Data Positiv Pin
50    pub pin_dp: Dp,
51}
52
53#[cfg(feature = "defmt")]
54impl<Dm: DmPin + defmt::Format, Dp: DpPin + defmt::Format> defmt::Format for Peripheral<Dm, Dp> {
55    fn format(&self, f: defmt::Formatter) {
56        defmt::write!(
57            f,
58            "Peripheral {{ usb: USB, pin_dm: {}, pin_dp: {}}}",
59            self.pin_dm,
60            self.pin_dp
61        );
62    }
63}
64
65impl<Dm, Dp> fmt::Debug for Peripheral<Dm, Dp>
66where
67    Dm: DmPin + fmt::Debug,
68    Dp: DpPin + fmt::Debug,
69{
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        f.debug_struct("Peripheral")
72            .field("usb", &"USB")
73            .field("pin_dm", &self.pin_dm)
74            .field("pin_dp", &self.pin_dp)
75            .finish()
76    }
77}
78
79// SAFETY: Implementation of Peripheral is thread-safe by using cricitcal sections to ensure
80// mutually exclusive access to the USB peripheral
81unsafe impl<Dm: DmPin, Dp: DpPin> Sync for Peripheral<Dm, Dp> {}
82
83// SAFETY: The Peirpheral has the same register block layout as STM32 USBFS
84unsafe impl<Dm: DmPin + Send, Dp: DpPin + Send> UsbPeripheral for Peripheral<Dm, Dp> {
85    const REGISTERS: *const () = USB::ptr().cast::<()>();
86    const DP_PULL_UP_FEATURE: bool = false;
87    const EP_MEMORY: *const () = 0x4000_6000 as _;
88    #[cfg(any(feature = "stm32f303xb", feature = "stm32f303xc"))]
89    const EP_MEMORY_SIZE: usize = 512;
90    #[cfg(any(feature = "stm32f303xd", feature = "stm32f303xe"))]
91    const EP_MEMORY_SIZE: usize = 1024;
92    #[cfg(any(feature = "stm32f303xb", feature = "stm32f303xc"))]
93    const EP_MEMORY_ACCESS_2X16: bool = false;
94    #[cfg(any(feature = "stm32f303xd", feature = "stm32f303xe"))]
95    const EP_MEMORY_ACCESS_2X16: bool = true;
96
97    fn enable() {
98        // SAFETY: the cricitcal section ensures, that the RCC access to enable the USB peripheral
99        // is mutually exclusive
100        critical_section::with(|_| unsafe {
101            // Enable USB peripheral
102            USB::enable_unchecked();
103            // Reset USB peripheral
104            USB::reset_unchecked();
105        });
106    }
107
108    fn startup_delay() {
109        // There is a chip specific startup delay. For STM32F103xx it's 1µs and this should wait for
110        // at least that long.
111        // 72 Mhz is the highest frequency, so this ensures a minimum of 1µs wait time.
112        cortex_m::asm::delay(72);
113    }
114}
115
116/// Type of the `UsbBus`
117#[cfg(any(feature = "stm32f303xb", feature = "stm32f303xc"))]
118#[allow(clippy::module_name_repetitions)]
119pub type UsbBusType<Dm = PA11<gpio::AF14<gpio::PushPull>>, Dp = PA12<gpio::AF14<gpio::PushPull>>> =
120    UsbBus<Peripheral<Dm, Dp>>;
121
122/// Type of the UsbBus
123#[cfg(any(feature = "stm32f303xd", feature = "stm32f303xe"))]
124pub type UsbBusType<Dm = PA11<gpio::Input>, Dp = PA12<gpio::Input>> = UsbBus<Peripheral<Dm, Dp>>;