70 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //! Universal Serial Bus (USB)
 | |
| 
 | |
| #[cfg_attr(usb, path = "usb.rs")]
 | |
| #[cfg_attr(otg, path = "otg.rs")]
 | |
| mod _version;
 | |
| pub use _version::*;
 | |
| 
 | |
| use crate::interrupt::typelevel::Interrupt;
 | |
| use crate::rcc;
 | |
| 
 | |
| /// clock, power initialization stuff that's common for USB and OTG.
 | |
| fn common_init<T: Instance>() {
 | |
|     // Check the USB clock is enabled and running at exactly 48 MHz.
 | |
|     // frequency() will panic if not enabled
 | |
|     let freq = T::frequency();
 | |
|     // Check frequency is within the 0.25% tolerance allowed by the spec.
 | |
|     // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user
 | |
|     // has tight clock restrictions due to something else (like audio).
 | |
|     if freq.0.abs_diff(48_000_000) > 120_000 {
 | |
|         panic!(
 | |
|             "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.",
 | |
|             freq.0
 | |
|         )
 | |
|     }
 | |
| 
 | |
|     #[cfg(any(stm32l4, stm32l5, stm32wb, stm32u0))]
 | |
|     critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
 | |
| 
 | |
|     #[cfg(pwr_h5)]
 | |
|     critical_section::with(|_| crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)));
 | |
| 
 | |
|     #[cfg(stm32h7)]
 | |
|     {
 | |
|         // If true, VDD33USB is generated by internal regulator from VDD50USB
 | |
|         // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
 | |
|         // TODO: unhardcode
 | |
|         let internal_regulator = false;
 | |
| 
 | |
|         // Enable USB power
 | |
|         critical_section::with(|_| {
 | |
|             crate::pac::PWR.cr3().modify(|w| {
 | |
|                 w.set_usb33den(true);
 | |
|                 w.set_usbregen(internal_regulator);
 | |
|             })
 | |
|         });
 | |
| 
 | |
|         // Wait for USB power to stabilize
 | |
|         while !crate::pac::PWR.cr3().read().usb33rdy() {}
 | |
|     }
 | |
| 
 | |
|     #[cfg(stm32u5)]
 | |
|     {
 | |
|         // Enable USB power
 | |
|         critical_section::with(|_| {
 | |
|             crate::pac::PWR.svmcr().modify(|w| {
 | |
|                 w.set_usv(true);
 | |
|                 w.set_uvmen(true);
 | |
|             })
 | |
|         });
 | |
| 
 | |
|         // Wait for USB power to stabilize
 | |
|         while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
 | |
|     }
 | |
| 
 | |
|     T::Interrupt::unpend();
 | |
|     unsafe { T::Interrupt::enable() };
 | |
| 
 | |
|     rcc::enable_and_reset::<T>();
 | |
| }
 |