embassy-rs/embassy · error

cannot select OTG_HS reference clock with source frequency…

Error message

cannot select OTG_HS reference clock with source frequency of {}, must be one of 16, 19.2, 20, 24, 26, 32 MHz

What it means

In embassy-stm32's STM32U5 RCC init, the OTG_HS USB reference clock selector only supports source frequencies of 16, 19.2, 20, 24, 26, or 32 MHz (Usbrefcksel register field). When config.usb_refck source is set to Some with a frequency outside this set, the driver panics because no hardware divider/selector value exists for it.

Solutions

  1. Choose a usb_refck source whose frequency is exactly 16, 19.2, 20, 24, 26, or 32 MHz (tune the PLL Q divider accordingly)
  2. Or leave usb_refck as None, which defaults to the 24 MHz selection
  3. Add/adjust a prescaler upstream so the source presented to OTG_HS is one of the supported frequencies

Example fix

// before
config.usb_refck = Some(UsbRefCkConfig { source: UsbRefCkSource::Pll1Q }); // PLL1.Q = 48 MHz -> panic
// after
// retune PLL1 so Q = 32 MHz, or pick a supported source
config.usb_refck = Some(UsbRefCkConfig { source: UsbRefCkSource::Pll1Q }); // PLL1.Q now 32 MHz
Defensive patterns

Strategy: validation

Validate before calling

const USB_REFCK_SUPPORTED: [u32; 6] = [16_000_000, 19_200_000, 20_000_000, 24_000_000, 26_000_000, 32_000_000];
if let Some(refck) = &config.usb_refck {
    let f = source_frequency(refck.source); // your resolved source freq
    assert!(USB_REFCK_SUPPORTED.contains(&f), "usb_refck source {} MHz unsupported", f / 1_000_000);
}

Type guard

fn usb_refck_supported(freq_hz: u32) -> bool {
    matches!(freq_hz, 16_000_000 | 19_200_000 | 20_000_000 | 24_000_000 | 26_000_000 | 32_000_000)
}

Prevention

When it happens

Trigger: rcc init with config.usb_refck = Some(...) whose source clock frequency (e.g. HSI 16 MHz is fine, but PLL outputs like 40 MHz, 48 MHz, 64 MHz) is not one of the six supported values.

Common situations: Feeding a PLL Q output at a nonstandard frequency into usb_refck; assuming any clock can be selected; upgrading embassy-stm32 and hitting the stricter validation; board designs using an external oscillator with an unsupported frequency.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/574c2d6eb53a4457. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/rcc/u5.rs:499

    let rtc = config.ls.init();

    #[cfg(all(stm32u5, peri_usb_otg_hs))]
    let usb_refck = match config.mux.otghssel {
        Otghssel::Hse => hse,
        Otghssel::HseDiv2 => hse.map(|hse_val| hse_val / 2u8),
        Otghssel::Pll1P => pll1.p,
        Otghssel::Pll1PDiv2 => pll1.p.map(|pll1p_val| pll1p_val / 2u8),
    };
    #[cfg(all(stm32u5, peri_usb_otg_hs))]
    let usb_refck_sel = match usb_refck {
        Some(clk_val) => match clk_val {
            Hertz(16_000_000) => Usbrefcksel::Mhz16,
            Hertz(19_200_000) => Usbrefcksel::Mhz192,
            Hertz(20_000_000) => Usbrefcksel::Mhz20,
            Hertz(24_000_000) => Usbrefcksel::Mhz24,
            Hertz(26_000_000) => Usbrefcksel::Mhz26,
            Hertz(32_000_000) => Usbrefcksel::Mhz32,
            _ => panic!(
                "cannot select OTG_HS reference clock with source frequency of {}, must be one of 16, 19.2, 20, 24, 26, 32 MHz",
                clk_val
            ),
        },
        None => Usbrefcksel::Mhz24,
    };
    #[cfg(all(stm32u5, peri_usb_otg_hs))]
    SYSCFG.otghsphycr().modify(|w| {
        w.set_clksel(usb_refck_sel);
    });

    let lse = config.ls.lse.map(|l| l.frequency);
    let lsi = config.ls.lsi.then_some(LSI_FREQ);

    // Disable HSI if not used
    if !config.hsi {
        RCC.cr().modify(|w| w.set_hsion(false));
    }

View on GitHub (pinned to 463a07b963)