embassy-rs/embassy · error
AHB frequency is too low
Error message
AHB frequency is too low
What it means
The USBHS (high-speed USB) driver computes the USB turn-around time (TRDT) from the AHB bus clock frequency. For high-speed operation the AHB clock must be at least 30 MHz (asserted directly), and for full-speed operation there is a lookup table with a minimum of ~14.2 MHz. A configured clock below these thresholds makes reliable USB timing impossible, so the driver panics.
Solutions
- Increase the AHB clock frequency in your clock initialization to ≥ 30 MHz for high-speed USB (≥ 14.2 MHz minimum for full speed).
- Reduce the AHB clock divider in the CCM configuration.
- If the clock cannot be raised, use a lower USB speed mode that the current frequency supports (per the TRDT lookup table).
Example fix
// before (board clock init) let mut ccm = CCM::new(...); ccm.set_ahb_divider(6); // AHB ends up ~12 MHz // after ccm.set_ahb_divider(2); // AHB >= 30 MHz, satisfies USBHS TRDT requirement
Defensive patterns
Strategy: validation
Validate before calling
let ahb_freq = clocks.ahb().raw();
assert!(ahb_freq >= 30_000_000, "AHB {} Hz too low for USBHS high speed", ahb_freq); Type guard
fn usbhs_ok(ahb_hz: u32, high_speed: bool) -> bool {
if high_speed { ahb_hz >= 30_000_000 } else { ahb_hz >= 14_200_000 }
} Prevention
- Initialize the clock tree before constructing the USB peripheral and log the resulting AHB frequency.
- Centralize clock setup in a board crate so USB cannot be built with a half-configured clock.
- Check the i.MX RT CCM divider settings whenever changing CPU frequency scaling.
When it happens
Trigger: Creating/configuring the USBHS peripheral with `Config` speed set to HIGH_SPEED while the AHB clock is < 30 MHz (hits the assert with the fuller message), or FULL_SPEED_EXTERNAL/FULL_SPEED_INTERNAL with AHB frequency below 14.2 MHz (hits the table's 0..=14_199_999 arm).
Common situations: Clock tree misconfiguration on i.MX RT chips where the AHB divider is too high; running USBHS off a default reset clock; changing board clock init after enabling USB.
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
- USB clock should be one of 16, 19.2, 20, 24, 26, 32Mhz but…
- USB clock should be 48Mhz but is
- USB HS PHY reference clock should be 19.2, 20 or 24 MHz but…
- AHB frequency is too low
- MCLK frequency < 9.5 MHz is not compatible with the TRNG
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/8fb58f6a356366b5.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-nrf/src/usb/usbhs.rs:353
}
fn current_hclk() -> u32 {
match pac::OSCILLATORS.pll().currentfreq().read().currentfreq() {
pac::oscillators::vals::Currentfreq::Ck128m => 128_000_000,
pac::oscillators::vals::Currentfreq::Ck64m => 64_000_000,
_ => unreachable!(),
}
}
fn calculate_trdt(speed: Dspd) -> u8 {
let ahb_freq = current_hclk();
match speed {
Dspd::HIGH_SPEED => {
assert!(ahb_freq >= 30_000_000, "AHB frequency is too low for USBHS");
0x9
}
Dspd::FULL_SPEED_EXTERNAL | Dspd::FULL_SPEED_INTERNAL => match ahb_freq {
0..=14_199_999 => panic!("AHB frequency is too low"),
14_200_000..=14_999_999 => 0xF,
15_000_000..=15_999_999 => 0xE,
16_000_000..=17_199_999 => 0xD,
17_200_000..=18_499_999 => 0xC,
18_500_000..=19_999_999 => 0xB,
20_000_000..=21_799_999 => 0xA,
21_800_000..=23_999_999 => 0x9,
24_000_000..=27_499_999 => 0x8,
27_500_000..=31_999_999 => 0x7,
32_000_000..=u32::MAX => 0x6,
},
_ => unimplemented!(),
}
}
fn busy_wait_us(us: u32) {
#[cfg(feature = "time")]
embassy_time::block_for(embassy_time::Duration::from_micros(us as u64));View on GitHub (pinned to 463a07b963)