Skip to content

Commit 6831fdb

Browse files
committed
stm32: Add raw_prescaler function to make it more reusable.
This also puts the explanation why the calculation has to be done that way into one place so it does not need to be copied all over the codebase.
1 parent a9727a1 commit 6831fdb

File tree

6 files changed

+35
-10
lines changed

6 files changed

+35
-10
lines changed

embassy-stm32/src/adc/adc4.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,7 @@ enum Prescaler {
128128

129129
impl Prescaler {
130130
fn from_ker_ck(frequency: Hertz) -> Self {
131-
// Calculate prescaler in a way where the clock can hit MAX CLK
132-
let raw_prescaler = frequency.0.saturating_sub(1) / MAX_ADC_CLK_FREQ.0;
131+
let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
133132
match raw_prescaler {
134133
0 => Self::NotDivided,
135134
1 => Self::DividedBy2,

embassy-stm32/src/adc/c0.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ pub enum Prescaler {
6666

6767
impl Prescaler {
6868
fn from_ker_ck(frequency: Hertz) -> Self {
69-
// Calculate prescaler in a way where the clock can hit MAX CLK
70-
let raw_prescaler = frequency.0.saturating_sub(1) / MAX_ADC_CLK_FREQ.0;
69+
let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
7170
match raw_prescaler {
7271
0 => Self::NotDivided,
7372
1 => Self::DividedBy2,

embassy-stm32/src/adc/g4.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ enum Prescaler {
7272

7373
impl Prescaler {
7474
fn from_ker_ck(frequency: Hertz) -> Self {
75-
// Calculate prescaler in a way where the clock can hit MAX CLK
76-
let raw_prescaler = frequency.0.saturating_sub(1) / MAX_ADC_CLK_FREQ.0;
75+
let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
7776
match raw_prescaler {
7877
0 => Self::NotDivided,
7978
1 => Self::DividedBy2,

embassy-stm32/src/adc/v2.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ impl Prescaler {
7171
// Datasheet for both F4 and F7 specifies min frequency 0.6 MHz, typ freq. 30 MHz and max 36 MHz.
7272
#[cfg(not(stm32f2))]
7373
const MAX_FREQUENCY: Hertz = Hertz(36_000_000);
74-
// Calculate prescaler divider including MAX_FREQ
75-
let raw_div = freq.0.saturating_sub(1) / MAX_FREQUENCY.0;
74+
let raw_div = rcc::raw_prescaler(freq.0, MAX_FREQUENCY.0);
7675
match raw_div {
7776
0..=1 => Self::Div2,
7877
2..=3 => Self::Div4,

embassy-stm32/src/adc/v4.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ enum Prescaler {
9393

9494
impl Prescaler {
9595
fn from_ker_ck(frequency: Hertz) -> Self {
96-
// Calculate prescaler in a way where the clock can hit MAX CLK
97-
let raw_prescaler = frequency.0.saturating_sub(1) / MAX_ADC_CLK_FREQ.0;
96+
let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
9897
match raw_prescaler {
9998
0 => Self::NotDivided,
10099
1 => Self::DividedBy2,

embassy-stm32/src/rcc/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,3 +409,33 @@ pub(crate) fn init_rcc(_cs: CriticalSection, config: Config) {
409409
}
410410
}
411411
}
412+
413+
/// Calculate intermediate prescaler number used to calculate peripheral prescalers
414+
///
415+
/// This function is intended to calculate a number indicating a minimum division
416+
/// necessary to result in a frequency lower than the provided `freq_max`.
417+
///
418+
/// The returned value indicates the `val + 1` divider is necessary to result in
419+
/// the output frequency that is below the maximum provided.
420+
///
421+
/// For example:
422+
/// 0 = divider of 1 => no division necessary as the input frequency is below max
423+
/// 1 = divider of 2 => division by 2 necessary
424+
/// ...
425+
///
426+
/// The provided max frequency is inclusive. So if `freq_in == freq_max` the result
427+
/// will be 0, indicating that no division is necessary. To accomplish that we subtract
428+
/// 1 from the input frequency so that the integer rounding plays in our favor.
429+
///
430+
/// For example:
431+
/// Let the input frequency be 110 and the max frequency be 55.
432+
/// If we naiively do `110/55 = 2` the renult will indicate that we need a divider by 3
433+
/// which in reality will be rounded up to 4 as usually a 3 division is not available.
434+
/// In either case the resulting frequency will be either 36 or 27 which is lower than
435+
/// what we would want. The result should be 1.
436+
/// If we do the following instead `109/55 = 1` indicating that we need a divide by 2
437+
/// which will result in the correct 55.
438+
#[allow(unused)]
439+
pub(crate) fn raw_prescaler(freq_in: u32, freq_max: u32) -> u32 {
440+
freq_in.saturating_sub(1) / freq_max
441+
}

0 commit comments

Comments
 (0)