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
- 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)
- Choose a slower kernel clock source (e.g. HCLK divided or HSI) in the RCC config
- 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
- Set the CCR prescaler explicitly in RCC config rather than relying on defaults
- Remember G4 limits scale with VREF voltage
- Derive ADC clock from a divided source, not raw PLL output
- Print computed ADC frequency during development
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
- Maximal allowed frequency for ADC4 is
- Maximal allowed frequency for the ADC is
- Selected PCLK2 frequency is too high for ADC with largest…
- Maximal allowed frequency for the ADC is
- not implemented
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)