1//! Universal Serial Bus (USB)
2
3#[cfg_attr(usb, path = "usb.rs")]
4#[cfg_attr(otg, path = "otg.rs")]
5mod _version;
6pub use _version::*;
7
8use crate::interrupt::typelevel::Interrupt;
9use crate::rcc;
10
11/// clock, power initialization stuff that's common for USB and OTG.
12fn common_init<T: Instance>() {
13 // Check the USB clock is enabled and running at exactly 48 MHz.
14 // frequency() will panic if not enabled
15 let freq = T::frequency();
16
17 // On the H7RS, the USBPHYC embeds a PLL accepting one of the input frequencies listed below and providing 48MHz to OTG_FS and 60MHz to OTG_HS internally
18 #[cfg(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs)))]
19 if ![16_000_000, 19_200_000, 20_000_000, 24_000_000, 26_000_000, 32_000_000].contains(&freq.0) {
20 panic!(
21 "USB clock should be one of 16, 19.2, 20, 24, 26, 32Mhz but is {} Hz. Please double-check your RCC settings.",
22 freq.0
23 )
24 }
25 // Check frequency is within the 0.25% tolerance allowed by the spec.
26 // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user
27 // has tight clock restrictions due to something else (like audio).
28 #[cfg(not(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs))))]
29 if freq.0.abs_diff(48_000_000) > 120_000 {
30 panic!(
31 "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.",
32 freq.0
33 )
34 }
35
36 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32u0))]
37 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
38
39 #[cfg(pwr_h5)]
40 critical_section::with(|_| crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)));
41
42 #[cfg(stm32h7)]
43 {
44 // If true, VDD33USB is generated by internal regulator from VDD50USB
45 // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
46 // TODO: unhardcode
47 let internal_regulator = false;
48
49 // Enable USB power
50 critical_section::with(|_| {
51 crate::pac::PWR.cr3().modify(|w| {
52 w.set_usb33den(true);
53 w.set_usbregen(internal_regulator);
54 })
55 });
56
57 // Wait for USB power to stabilize
58 while !crate::pac::PWR.cr3().read().usb33rdy() {}
59 }
60
61 #[cfg(stm32h7rs)]
62 {
63 // If true, VDD33USB is generated by internal regulator from VDD50USB
64 // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
65 // TODO: unhardcode
66 let internal_regulator = false;
67
68 // Enable USB power
69 critical_section::with(|_| {
70 crate::pac::PWR.csr2().modify(|w| {
71 w.set_usbregen(internal_regulator);
72 w.set_usb33den(true);
73 w.set_usbhsregen(true);
74 })
75 });
76
77 // Wait for USB power to stabilize
78 while !crate::pac::PWR.csr2().read().usb33rdy() {}
79 }
80
81 #[cfg(stm32u5)]
82 {
83 // Enable USB power
84 critical_section::with(|_| {
85 crate::pac::PWR.svmcr().modify(|w| {
86 w.set_usv(true);
87 w.set_uvmen(true);
88 })
89 });
90
91 // Wait for USB power to stabilize
92 while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
93
94 // Now set up transceiver power if it's a OTG-HS
95 #[cfg(peri_usb_otg_hs)]
96 {
97 crate::pac::PWR.vosr().modify(|w| {
98 w.set_usbpwren(true);
99 w.set_usbboosten(true);
100 });
101 while !crate::pac::PWR.vosr().read().usbboostrdy() {}
102 }
103 }
104
105 T::Interrupt::unpend();
106 unsafe { T::Interrupt::enable() };
107
108 rcc::enable_and_reset::<T>();
109}
110