From d90abb8ac91440602386b807edb221cae59e82f9 Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Tue, 19 Mar 2024 21:33:20 +0100
Subject: [PATCH] stm32/usb: assert usb clock is okay.

---
 embassy-stm32/src/usb/mod.rs | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs
index 130c728e6..788f61f16 100644
--- a/embassy-stm32/src/usb/mod.rs
+++ b/embassy-stm32/src/usb/mod.rs
@@ -10,6 +10,19 @@ use crate::rcc::sealed::RccPeripheral;
 
 /// 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))]
     critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));