embassy-rs/embassy · error

HCLK results in MDC clock > 2.5MHz even for the highest CSR…

Error message

HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider

What it means

The ETH_MAC needs an MDC management clock in the 1-2.5 MHz window, derived from HCLK via a fixed table of CSR dividers. The match on hclk_mhz fell into the panic arm, meaning even the largest divider (divide by 124, for ~250 MHz HCLK) leaves MDC above 2.5 MHz — the input HCLK is above what the divider table supports (or below the 25 MHz minimum).

Solutions

  1. Lower HCLK1 to <= 216 MHz (150..=216 arm) in the RCC config.
  2. Add a divider so the ETH kernel clock (hclk1) is in range.
  3. Use a v2 MAC/chip whose CSR clock range supports higher HCLK.

Example fix

// before
config.pll = Pll { freq: 240.MHz(), .. };
// after
config.pll = Pll { freq: 216.MHz(), .. }; // Cr150168
Defensive patterns

Strategy: validation

Validate before calling

let hclk_mhz = embassy_stm32::rcc::get_freqs().hclk1.0 / 1_000_000;
assert!(hclk_mhz <= 216, "v1 Ethernet requires HCLK1 <= 216 MHz, got {} MHz", hclk_mhz);

Prevention

When it happens

Trigger: Creating StationManagement on an eth v1 part with hclk_mhz > 216 (catch-all match arm).

Common situations: Overclocked HCLK1 on F4/F7 v1 parts; reusing H5-style high-frequency RCC configs on v1 boards.

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/3d1f64668f47455f. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/eth/sma/v1.rs:53

            reg.modify(|w| {
                w.set_ethen(true);
            })
        });

        let hclk = unsafe { crate::rcc::get_freqs().hclk1.to_hertz() };
        let hclk = unwrap!(hclk, "SMA requires HCLK to be enabled, but it was not.");
        let hclk_mhz = hclk.0 / 1_000_000;

        // Set the MDC clock frequency in the range 1MHz - 2.5MHz
        let clock_range = match hclk_mhz {
            0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."),
            25..=34 => Cr::Cr2035,     // Divide by 16
            35..=59 => Cr::Cr3560,     // Divide by 26
            60..=99 => Cr::Cr60100,    // Divide by 42
            100..=149 => Cr::Cr100150, // Divide by 62
            150..=216 => Cr::Cr150168, // Divide by 102
            _ => {
                panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider")
            }
        };

        Self {
            _peri: peri,
            clock_range,
            _pins: [
                new_pin!(mdio, AfType::output(OutputType::PushPull, Speed::VeryHigh)).unwrap(),
                new_pin!(mdc, AfType::output(OutputType::PushPull, Speed::VeryHigh)).unwrap(),
            ],
        }
    }
}

impl<T: Instance> StationManagement for Sma<'_, T> {
    fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
        let (macmiiar, macmiidr) = T::regs();

View on GitHub (pinned to 463a07b963)