embassy-rs/embassy · error

Maximal allowed frequency for the ADC is

Error message

Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.

What it means

The G4-series ADC driver sets a prescaler on the ADC common clock register (CCR.PRESC) and computes the resulting frequency. If the ADC clock frequency still exceeds MAX_ADC_CLK_FREQ, the constructor panics, since running the ADC above its rated clock violates the ST datasheet and degrades conversion accuracy. The limit varies per package/voltage, so ST's docs are referenced.

Solutions

  1. Set RCC adc_clock_source / ADC prescaler so the ADC clock is within MAX_ADC_CLK_FREQ (G4 max typically 60 MHz on VREF>=2.7V, lower on reduced voltage)
  2. Choose a slower kernel clock source (e.g. HCLK divided or HSI) in the RCC config
  3. Check ST's G4 datasheet for the frequency limit at your operating voltage and adjust SYSCLK/PLL accordingly

Example fix

// before
config.rcc.adc_clock_source = AdcClockSource::Pll(SP::P); // 170MHz too fast
// after
config.rcc.adc_clock_source = AdcClockSource::Pll(SP::P);
config.rcc.adc_prescaler = AdcPrescaler::DividedBy4; // <= MAX_ADC_CLK_FREQ
Defensive patterns

Strategy: validation

Validate before calling

let adc_clk_hz = adc_kernel_clock_hz(); // e.g. PLLP or HCLK derived
// G4: max 60 MHz (VREF >= 2.7V), less at lower voltage
assert!(adc_clk_hz <= MAX_ADC_CLK_FREQ_HZ, "ADC clock too high: {} Hz", adc_clk_hz);

Prevention

When it happens

Trigger: Calling `Adc::new(...)` for an STM32G4 target when T::frequency() (the ADC kernel clock, e.g. from RCC's AdcClockSource) exceeds MAX_ADC_CLK_FREQ even after the driver sets CCR prescaler bits.

Common situations: Configuring the ADC kernel clock to PLL "P" output at a high rate and forgetting the ADC prescaler; running at 170 MHz with AHB/1 mapped to ADC; copying clock setup from another G4 board with different crystal/PLL values.

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/60f0eca8386dab17. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/adc/g4.rs:305

        // Clear JEOS by writing 1
        self.isr().modify(|r| r.set_jeos(true));
    }
}

impl<'d, T: DefaultInstance> Adc<'d, T> {
    /// Create a new ADC driver.
    pub fn new(adc: Peri<'d, T>, config: AdcConfig) -> Self {
        rcc::enable_and_reset::<T>();

        let prescaler = from_ker_ck(T::frequency());

        T::common_regs().ccr().modify(|w| w.set_presc(prescaler));

        let frequency = T::frequency() / prescaler;
        trace!("ADC frequency set to {}", frequency);

        if frequency > MAX_ADC_CLK_FREQ {
            panic!(
                "Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.",
                MAX_ADC_CLK_FREQ.0 / 1_000_000
            );
        }

        T::regs().cr().modify(|reg| {
            reg.set_deeppwd(false);
            reg.set_advregen(true);
        });

        block_for_us(20);

        T::regs().difsel().modify(|w| {
            for n in 0..18 {
                w.set_difsel(n, Difsel::SingleEnded);
            }
        });

View on GitHub (pinned to 463a07b963)