aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/usb
diff options
context:
space:
mode:
authorDave Marples <[email protected]>2024-12-05 16:35:56 +0000
committerMarvin Drees <[email protected]>2024-12-10 10:51:28 +0100
commit501d3942e8b6b04fd1cb4c14728ba4c2e118d8b5 (patch)
treed8b71167fc51871c4d2ab44203076e2c0d241b85 /embassy-stm32/src/usb
parent86578acaa4d4dbed06ed4fcecec25884f6883e82 (diff)
Add support for stm32u595/5a5 OTG_HS in client mode
Diffstat (limited to 'embassy-stm32/src/usb')
-rw-r--r--embassy-stm32/src/usb/mod.rs20
-rw-r--r--embassy-stm32/src/usb/otg.rs32
2 files changed, 45 insertions, 7 deletions
diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs
index a473285bf..9737b9b3f 100644
--- a/embassy-stm32/src/usb/mod.rs
+++ b/embassy-stm32/src/usb/mod.rs
@@ -26,6 +26,7 @@ fn common_init<T: Instance>() {
26 // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user 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). 27 // has tight clock restrictions due to something else (like audio).
28 #[cfg(not(stm32h7rs))] 28 #[cfg(not(stm32h7rs))]
29 #[cfg(not(all(stm32u5, peri_usb_otg_hs)))]
29 if freq.0.abs_diff(48_000_000) > 120_000 { 30 if freq.0.abs_diff(48_000_000) > 120_000 {
30 panic!( 31 panic!(
31 "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.", 32 "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.",
@@ -33,6 +34,15 @@ fn common_init<T: Instance>() {
33 ) 34 )
34 } 35 }
35 36
37 // For OTG-HS on STM32U5 only the 32MHz clock is fast enough (Table 762, Sect 73.14.4)
38 #[cfg(all(stm32u5, peri_usb_otg_hs))]
39 if freq.0.abs_diff(32_000_000) > 120_000 {
40 panic!(
41 "USB clock should be 32Mhz but is {} Hz. Please double-check your RCC settings.",
42 freq.0
43 )
44 }
45
36 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32u0))] 46 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32u0))]
37 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); 47 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
38 48
@@ -90,6 +100,16 @@ fn common_init<T: Instance>() {
90 100
91 // Wait for USB power to stabilize 101 // Wait for USB power to stabilize
92 while !crate::pac::PWR.svmsr().read().vddusbrdy() {} 102 while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
103
104 // Now set up transceiver power if it's a OTG-HS
105 #[cfg(peri_usb_otg_hs)]
106 {
107 crate::pac::PWR.vosr().modify(|w| {
108 w.set_usbpwren(true);
109 w.set_usbboosten(true);
110 });
111 while !crate::pac::PWR.vosr().read().usbboostrdy() {}
112 }
93 } 113 }
94 114
95 T::Interrupt::unpend(); 115 T::Interrupt::unpend();
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs
index 6ca28b156..d1b38a558 100644
--- a/embassy-stm32/src/usb/otg.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -26,7 +26,6 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
26 unsafe fn on_interrupt() { 26 unsafe fn on_interrupt() {
27 let r = T::regs(); 27 let r = T::regs();
28 let state = T::state(); 28 let state = T::state();
29
30 on_interrupt_impl(r, state, T::ENDPOINT_COUNT); 29 on_interrupt_impl(r, state, T::ENDPOINT_COUNT);
31 } 30 }
32} 31}
@@ -103,15 +102,18 @@ impl<'d, T: Instance> Driver<'d, T> {
103 pub fn new_hs( 102 pub fn new_hs(
104 _peri: impl Peripheral<P = T> + 'd, 103 _peri: impl Peripheral<P = T> + 'd,
105 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 104 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
106 dp: impl Peripheral<P = impl DpPin<T>> + 'd, 105 _dp: impl Peripheral<P = impl DpPin<T>> + 'd,
107 dm: impl Peripheral<P = impl DmPin<T>> + 'd, 106 _dm: impl Peripheral<P = impl DmPin<T>> + 'd,
108 ep_out_buffer: &'d mut [u8], 107 ep_out_buffer: &'d mut [u8],
109 config: Config, 108 config: Config,
110 ) -> Self { 109 ) -> Self {
111 into_ref!(dp, dm); 110 // For STM32U5 High speed pins need to be left in analog mode
112 111 #[cfg(not(all(stm32u5, peri_usb_otg_hs)))]
113 dp.set_as_af(dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); 112 {
114 dm.set_as_af(dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); 113 into_ref!(_dp, _dm);
114 _dp.set_as_af(_dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
115 _dm.set_as_af(_dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
116 }
115 117
116 let instance = OtgInstance { 118 let instance = OtgInstance {
117 regs: T::regs(), 119 regs: T::regs(),
@@ -311,6 +313,22 @@ impl<'d, T: Instance> Bus<'d, T> {
311 }); 313 });
312 }); 314 });
313 315
316 #[cfg(all(stm32u5, peri_usb_otg_hs))]
317 {
318 // Only the 32MHz clock is suitable here, which the magic number represents
319 crate::pac::SYSCFG.otghsphycr().modify(|w| {
320 w.set_clksel(11);
321 w.set_en(true);
322 });
323
324 critical_section::with(|_| {
325 crate::pac::RCC.ahb2enr1().modify(|w| {
326 w.set_usb_otg_hsen(true);
327 w.set_usb_otg_hs_phyen(true);
328 });
329 });
330 }
331
314 let r = T::regs(); 332 let r = T::regs();
315 let core_id = r.cid().read().0; 333 let core_id = r.cid().read().0;
316 trace!("Core id {:08x}", core_id); 334 trace!("Core id {:08x}", core_id);