diff options
| author | Piotr Esden-Tempski <[email protected]> | 2025-10-05 19:41:49 -0700 |
|---|---|---|
| committer | Piotr Esden-Tempski <[email protected]> | 2025-10-05 20:00:26 -0700 |
| commit | 6831fdbfe896e9f848f93c31473703fa1c767198 (patch) | |
| tree | 7ef2d8a6a882dddb765162471535cb5af2b8988c | |
| parent | a9727a17b593f7328f721e8905b7fc8dab9ae7ff (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.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/c0.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/g4.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v2.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v4.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 30 |
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 | ||
| 129 | impl Prescaler { | 129 | impl 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 | ||
| 67 | impl Prescaler { | 67 | impl 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 | ||
| 73 | impl Prescaler { | 73 | impl 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 | ||
| 94 | impl Prescaler { | 94 | impl 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)] | ||
| 439 | pub(crate) fn raw_prescaler(freq_in: u32, freq_max: u32) -> u32 { | ||
| 440 | freq_in.saturating_sub(1) / freq_max | ||
| 441 | } | ||
