Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions embassy-stm32/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- feat: stm32/usart: add `eager_reads` option to control if buffered readers return as soon as possible or after more data is available ([#4668](https://github.com/embassy-rs/embassy/pull/4668))
- feat: stm32/usart: add `de_assertion_time` and `de_deassertion_time` config options
- change: stm32/uart: BufferedUartRx now returns all available bytes from the internal buffer
- fix: stm32/adc: Calculate the ADC prescaler in a way that it allows for the max frequency to be reached

## 0.4.0 - 2025-08-26

Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/adc/adc4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ enum Prescaler {

impl Prescaler {
fn from_ker_ck(frequency: Hertz) -> Self {
let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
match raw_prescaler {
0 => Self::NotDivided,
1 => Self::DividedBy2,
Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/adc/c0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub enum Prescaler {

impl Prescaler {
fn from_ker_ck(frequency: Hertz) -> Self {
let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
match raw_prescaler {
0 => Self::NotDivided,
1 => Self::DividedBy2,
Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/adc/g4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ enum Prescaler {

impl Prescaler {
fn from_ker_ck(frequency: Hertz) -> Self {
let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
match raw_prescaler {
0 => Self::NotDivided,
1 => Self::DividedBy2,
Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/adc/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl Prescaler {
// Datasheet for both F4 and F7 specifies min frequency 0.6 MHz, typ freq. 30 MHz and max 36 MHz.
#[cfg(not(stm32f2))]
const MAX_FREQUENCY: Hertz = Hertz(36_000_000);
let raw_div = freq.0 / MAX_FREQUENCY.0;
let raw_div = rcc::raw_prescaler(freq.0, MAX_FREQUENCY.0);
match raw_div {
0..=1 => Self::Div2,
2..=3 => Self::Div4,
Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/adc/v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ enum Prescaler {

impl Prescaler {
fn from_ker_ck(frequency: Hertz) -> Self {
let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
match raw_prescaler {
0 => Self::NotDivided,
1 => Self::DividedBy2,
Expand Down
30 changes: 30 additions & 0 deletions embassy-stm32/src/rcc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,33 @@ pub(crate) fn init_rcc(_cs: CriticalSection, config: Config) {
}
}
}

/// Calculate intermediate prescaler number used to calculate peripheral prescalers
///
/// This function is intended to calculate a number indicating a minimum division
/// necessary to result in a frequency lower than the provided `freq_max`.
///
/// The returned value indicates the `val + 1` divider is necessary to result in
/// the output frequency that is below the maximum provided.
///
/// For example:
/// 0 = divider of 1 => no division necessary as the input frequency is below max
/// 1 = divider of 2 => division by 2 necessary
/// ...
///
/// The provided max frequency is inclusive. So if `freq_in == freq_max` the result
/// will be 0, indicating that no division is necessary. To accomplish that we subtract
/// 1 from the input frequency so that the integer rounding plays in our favor.
///
/// For example:
/// Let the input frequency be 110 and the max frequency be 55.
/// If we naiively do `110/55 = 2` the renult will indicate that we need a divider by 3
/// which in reality will be rounded up to 4 as usually a 3 division is not available.
/// In either case the resulting frequency will be either 36 or 27 which is lower than
/// what we would want. The result should be 1.
/// If we do the following instead `109/55 = 1` indicating that we need a divide by 2
/// which will result in the correct 55.
#[allow(unused)]
pub(crate) fn raw_prescaler(freq_in: u32, freq_max: u32) -> u32 {
freq_in.saturating_sub(1) / freq_max
}