File tree Expand file tree Collapse file tree 7 files changed +36
-5
lines changed Expand file tree Collapse file tree 7 files changed +36
-5
lines changed Original file line number Diff line number Diff line change @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4141- 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 ) )
4242- feat: stm32/usart: add ` de_assertion_time ` and ` de_deassertion_time ` config options
4343- change: stm32/uart: BufferedUartRx now returns all available bytes from the internal buffer
44+ - fix: stm32/adc: Calculate the ADC prescaler in a way that it allows for the max frequency to be reached
4445- fix: Prevent a HardFault crash on STM32H5 devices by changing ` uid() ` to return ` [u8; 12] ` by value instead of a reference. (Fixes #2696 )
4546- change: timer: added output compare values
4647- feat: timer: add ability to set master mode
Original file line number Diff line number Diff line change @@ -77,7 +77,7 @@ pub const fn resolution_to_max_count(res: Resolution) -> u32 {
7777}
7878
7979fn from_ker_ck ( frequency : Hertz ) -> Presc {
80- let raw_prescaler = frequency. 0 / MAX_ADC_CLK_FREQ . 0 ;
80+ let raw_prescaler = rcc :: raw_prescaler ( frequency. 0 , MAX_ADC_CLK_FREQ . 0 ) ;
8181 match raw_prescaler {
8282 0 => Presc :: DIV1 ,
8383 1 => Presc :: DIV2 ,
Original file line number Diff line number Diff line change @@ -30,7 +30,7 @@ impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
3030}
3131
3232fn from_ker_ck ( frequency : Hertz ) -> Presc {
33- let raw_prescaler = frequency. 0 / MAX_ADC_CLK_FREQ . 0 ;
33+ let raw_prescaler = rcc :: raw_prescaler ( frequency. 0 , MAX_ADC_CLK_FREQ . 0 ) ;
3434 match raw_prescaler {
3535 0 => Presc :: DIV1 ,
3636 1 => Presc :: DIV2 ,
Original file line number Diff line number Diff line change @@ -33,7 +33,7 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60);
3333const MAX_ADC_CLK_FREQ : Hertz = Hertz :: mhz ( 50 ) ;
3434
3535fn from_ker_ck ( frequency : Hertz ) -> Presc {
36- let raw_prescaler = frequency. 0 / MAX_ADC_CLK_FREQ . 0 ;
36+ let raw_prescaler = rcc :: raw_prescaler ( frequency. 0 , MAX_ADC_CLK_FREQ . 0 ) ;
3737 match raw_prescaler {
3838 0 => Presc :: DIV1 ,
3939 1 => Presc :: DIV2 ,
Original file line number Diff line number Diff line change @@ -58,7 +58,7 @@ fn from_pclk2(freq: Hertz) -> Adcpre {
5858 // Datasheet for both F4 and F7 specifies min frequency 0.6 MHz, typ freq. 30 MHz and max 36 MHz.
5959 #[ cfg( not( stm32f2) ) ]
6060 const MAX_FREQUENCY : Hertz = Hertz ( 36_000_000 ) ;
61- let raw_div = freq. 0 / MAX_FREQUENCY . 0 ;
61+ let raw_div = rcc :: raw_prescaler ( freq. 0 , MAX_FREQUENCY . 0 ) ;
6262 match raw_div {
6363 0 ..=1 => Adcpre :: DIV2 ,
6464 2 ..=3 => Adcpre :: DIV4 ,
Original file line number Diff line number Diff line change @@ -60,7 +60,7 @@ impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
6060}
6161
6262fn from_ker_ck ( frequency : Hertz ) -> Presc {
63- let raw_prescaler = frequency. 0 / MAX_ADC_CLK_FREQ . 0 ;
63+ let raw_prescaler = rcc :: raw_prescaler ( frequency. 0 , MAX_ADC_CLK_FREQ . 0 ) ;
6464 match raw_prescaler {
6565 0 => Presc :: DIV1 ,
6666 1 => Presc :: DIV2 ,
Original file line number Diff line number Diff line change @@ -413,3 +413,33 @@ pub(crate) fn init_rcc(_cs: CriticalSection, config: Config) {
413413 }
414414 }
415415}
416+
417+ /// Calculate intermediate prescaler number used to calculate peripheral prescalers
418+ ///
419+ /// This function is intended to calculate a number indicating a minimum division
420+ /// necessary to result in a frequency lower than the provided `freq_max`.
421+ ///
422+ /// The returned value indicates the `val + 1` divider is necessary to result in
423+ /// the output frequency that is below the maximum provided.
424+ ///
425+ /// For example:
426+ /// 0 = divider of 1 => no division necessary as the input frequency is below max
427+ /// 1 = divider of 2 => division by 2 necessary
428+ /// ...
429+ ///
430+ /// The provided max frequency is inclusive. So if `freq_in == freq_max` the result
431+ /// will be 0, indicating that no division is necessary. To accomplish that we subtract
432+ /// 1 from the input frequency so that the integer rounding plays in our favor.
433+ ///
434+ /// For example:
435+ /// Let the input frequency be 110 and the max frequency be 55.
436+ /// If we naiively do `110/55 = 2` the renult will indicate that we need a divider by 3
437+ /// which in reality will be rounded up to 4 as usually a 3 division is not available.
438+ /// In either case the resulting frequency will be either 36 or 27 which is lower than
439+ /// what we would want. The result should be 1.
440+ /// If we do the following instead `109/55 = 1` indicating that we need a divide by 2
441+ /// which will result in the correct 55.
442+ #[ allow( unused) ]
443+ pub ( crate ) fn raw_prescaler ( freq_in : u32 , freq_max : u32 ) -> u32 {
444+ freq_in. saturating_sub ( 1 ) / freq_max
445+ }
You can’t perform that action at this time.
0 commit comments