aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPiotr Esden-Tempski <[email protected]>2025-10-05 19:41:49 -0700
committerPiotr Esden-Tempski <[email protected]>2025-10-05 20:00:26 -0700
commit6831fdbfe896e9f848f93c31473703fa1c767198 (patch)
tree7ef2d8a6a882dddb765162471535cb5af2b8988c
parenta9727a17b593f7328f721e8905b7fc8dab9ae7ff (diff)
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.
-rw-r--r--embassy-stm32/src/adc/adc4.rs3
-rw-r--r--embassy-stm32/src/adc/c0.rs3
-rw-r--r--embassy-stm32/src/adc/g4.rs3
-rw-r--r--embassy-stm32/src/adc/v2.rs3
-rw-r--r--embassy-stm32/src/adc/v4.rs3
-rw-r--r--embassy-stm32/src/rcc/mod.rs30
6 files changed, 35 insertions, 10 deletions
diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs
index 1302dffb8..0b442330a 100644
--- a/embassy-stm32/src/adc/adc4.rs
+++ b/embassy-stm32/src/adc/adc4.rs
@@ -128,8 +128,7 @@ enum Prescaler {
128 128
129impl Prescaler { 129impl Prescaler {
130 fn from_ker_ck(frequency: Hertz) -> Self { 130 fn from_ker_ck(frequency: Hertz) -> Self {
131 // Calculate prescaler in a way where the clock can hit MAX CLK 131 let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
132 let raw_prescaler = frequency.0.saturating_sub(1) / MAX_ADC_CLK_FREQ.0;
133 match raw_prescaler { 132 match raw_prescaler {
134 0 => Self::NotDivided, 133 0 => Self::NotDivided,
135 1 => Self::DividedBy2, 134 1 => Self::DividedBy2,
diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs
index bd9a3e2c6..5b3438ea1 100644
--- a/embassy-stm32/src/adc/c0.rs
+++ b/embassy-stm32/src/adc/c0.rs
@@ -66,8 +66,7 @@ pub enum Prescaler {
66 66
67impl Prescaler { 67impl Prescaler {
68 fn from_ker_ck(frequency: Hertz) -> Self { 68 fn from_ker_ck(frequency: Hertz) -> Self {
69 // Calculate prescaler in a way where the clock can hit MAX CLK 69 let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
70 let raw_prescaler = frequency.0.saturating_sub(1) / MAX_ADC_CLK_FREQ.0;
71 match raw_prescaler { 70 match raw_prescaler {
72 0 => Self::NotDivided, 71 0 => Self::NotDivided,
73 1 => Self::DividedBy2, 72 1 => Self::DividedBy2,
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index ac0a6196f..6c7789c0e 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -72,8 +72,7 @@ enum Prescaler {
72 72
73impl Prescaler { 73impl Prescaler {
74 fn from_ker_ck(frequency: Hertz) -> Self { 74 fn from_ker_ck(frequency: Hertz) -> Self {
75 // Calculate prescaler in a way where the clock can hit MAX CLK 75 let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
76 let raw_prescaler = frequency.0.saturating_sub(1) / MAX_ADC_CLK_FREQ.0;
77 match raw_prescaler { 76 match raw_prescaler {
78 0 => Self::NotDivided, 77 0 => Self::NotDivided,
79 1 => Self::DividedBy2, 78 1 => Self::DividedBy2,
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 57f252e13..09e0f4d11 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -71,8 +71,7 @@ impl Prescaler {
71 // Datasheet for both F4 and F7 specifies min frequency 0.6 MHz, typ freq. 30 MHz and max 36 MHz. 71 // Datasheet for both F4 and F7 specifies min frequency 0.6 MHz, typ freq. 30 MHz and max 36 MHz.
72 #[cfg(not(stm32f2))] 72 #[cfg(not(stm32f2))]
73 const MAX_FREQUENCY: Hertz = Hertz(36_000_000); 73 const MAX_FREQUENCY: Hertz = Hertz(36_000_000);
74 // Calculate prescaler divider including MAX_FREQ 74 let raw_div = rcc::raw_prescaler(freq.0, MAX_FREQUENCY.0);
75 let raw_div = freq.0.saturating_sub(1) / MAX_FREQUENCY.0;
76 match raw_div { 75 match raw_div {
77 0..=1 => Self::Div2, 76 0..=1 => Self::Div2,
78 2..=3 => Self::Div4, 77 2..=3 => Self::Div4,
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index c68684cb2..6c8ce7b64 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -93,8 +93,7 @@ enum Prescaler {
93 93
94impl Prescaler { 94impl Prescaler {
95 fn from_ker_ck(frequency: Hertz) -> Self { 95 fn from_ker_ck(frequency: Hertz) -> Self {
96 // Calculate prescaler in a way where the clock can hit MAX CLK 96 let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
97 let raw_prescaler = frequency.0.saturating_sub(1) / MAX_ADC_CLK_FREQ.0;
98 match raw_prescaler { 97 match raw_prescaler {
99 0 => Self::NotDivided, 98 0 => Self::NotDivided,
100 1 => Self::DividedBy2, 99 1 => Self::DividedBy2,
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index c41f81816..8509838ed 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -409,3 +409,33 @@ pub(crate) fn init_rcc(_cs: CriticalSection, config: Config) {
409 } 409 }
410 } 410 }
411} 411}
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)]
439pub(crate) fn raw_prescaler(freq_in: u32, freq_max: u32) -> u32 {
440 freq_in.saturating_sub(1) / freq_max
441}