stm32/rcc: g4: consistent PllSource, add pll pqr limits, simplify a bit.
This commit is contained in:
		
							parent
							
								
									20760ff4f7
								
							
						
					
					
						commit
						b4567bb8c5
					
				| @ -1,12 +1,9 @@ | |||||||
| use stm32_metapac::flash::vals::Latency; | use crate::pac::flash::vals::Latency; | ||||||
| use stm32_metapac::rcc::vals::Sw; |  | ||||||
| use stm32_metapac::FLASH; |  | ||||||
| 
 |  | ||||||
| pub use crate::pac::rcc::vals::{ | pub use crate::pac::rcc::vals::{ | ||||||
|     Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc, |     Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, | ||||||
|     Ppre as APBPrescaler, Sw as Sysclk, |     Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, | ||||||
| }; | }; | ||||||
| use crate::pac::{PWR, RCC}; | use crate::pac::{FLASH, PWR, RCC}; | ||||||
| use crate::time::Hertz; | use crate::time::Hertz; | ||||||
| 
 | 
 | ||||||
| /// HSI speed
 | /// HSI speed
 | ||||||
| @ -37,7 +34,7 @@ pub struct Hse { | |||||||
| /// frequency ranges for each of these settings.
 | /// frequency ranges for each of these settings.
 | ||||||
| pub struct Pll { | pub struct Pll { | ||||||
|     /// PLL Source clock selection.
 |     /// PLL Source clock selection.
 | ||||||
|     pub source: Pllsrc, |     pub source: PllSource, | ||||||
| 
 | 
 | ||||||
|     /// PLL pre-divider
 |     /// PLL pre-divider
 | ||||||
|     pub prediv: PllPreDiv, |     pub prediv: PllPreDiv, | ||||||
| @ -73,7 +70,7 @@ pub struct Config { | |||||||
|     /// PLL Configuration
 |     /// PLL Configuration
 | ||||||
|     pub pll: Option<Pll>, |     pub pll: Option<Pll>, | ||||||
| 
 | 
 | ||||||
|     /// Iff PLL is requested as the main clock source in the `mux` field then the PLL configuration
 |     /// If PLL is requested as the main clock source in the `sys` field then the PLL configuration
 | ||||||
|     /// MUST turn on the PLLR output.
 |     /// MUST turn on the PLLR output.
 | ||||||
|     pub ahb_pre: AHBPrescaler, |     pub ahb_pre: AHBPrescaler, | ||||||
|     pub apb1_pre: APBPrescaler, |     pub apb1_pre: APBPrescaler, | ||||||
| @ -112,6 +109,7 @@ impl Default for Config { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Default)] | ||||||
| pub struct PllFreq { | pub struct PllFreq { | ||||||
|     pub pll_p: Option<Hertz>, |     pub pll_p: Option<Hertz>, | ||||||
|     pub pll_q: Option<Hertz>, |     pub pll_q: Option<Hertz>, | ||||||
| @ -154,10 +152,12 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
|     // Configure HSI48 if required
 |     // Configure HSI48 if required
 | ||||||
|     let hsi48 = config.hsi48.map(super::init_hsi48); |     let hsi48 = config.hsi48.map(super::init_hsi48); | ||||||
| 
 | 
 | ||||||
|     let pll_freq = config.pll.map(|pll_config| { |     let pll = config | ||||||
|  |         .pll | ||||||
|  |         .map(|pll_config| { | ||||||
|             let src_freq = match pll_config.source { |             let src_freq = match pll_config.source { | ||||||
|             Pllsrc::HSI => unwrap!(hsi), |                 PllSource::HSI => unwrap!(hsi), | ||||||
|             Pllsrc::HSE => unwrap!(hse), |                 PllSource::HSE => unwrap!(hse), | ||||||
|                 _ => unreachable!(), |                 _ => unreachable!(), | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
| @ -183,7 +183,7 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
|                     w.set_pllpen(true); |                     w.set_pllpen(true); | ||||||
|                 }); |                 }); | ||||||
|                 let freq = internal_freq / div_p; |                 let freq = internal_freq / div_p; | ||||||
|             assert!(max::PCLK.contains(&freq)); |                 assert!(max::PLL_P.contains(&freq)); | ||||||
|                 freq |                 freq | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
| @ -193,7 +193,7 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
|                     w.set_pllqen(true); |                     w.set_pllqen(true); | ||||||
|                 }); |                 }); | ||||||
|                 let freq = internal_freq / div_q; |                 let freq = internal_freq / div_q; | ||||||
|             assert!(max::PCLK.contains(&freq)); |                 assert!(max::PLL_Q.contains(&freq)); | ||||||
|                 freq |                 freq | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
| @ -203,7 +203,7 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
|                     w.set_pllren(true); |                     w.set_pllren(true); | ||||||
|                 }); |                 }); | ||||||
|                 let freq = internal_freq / div_r; |                 let freq = internal_freq / div_r; | ||||||
|             assert!(max::PCLK.contains(&freq)); |                 assert!(max::PLL_R.contains(&freq)); | ||||||
|                 freq |                 freq | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
| @ -216,29 +216,27 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
|                 pll_q: pll_q_freq, |                 pll_q: pll_q_freq, | ||||||
|                 pll_r: pll_r_freq, |                 pll_r: pll_r_freq, | ||||||
|             } |             } | ||||||
|     }); |         }) | ||||||
|  |         .unwrap_or_default(); | ||||||
| 
 | 
 | ||||||
|     let (sys_clk, sw) = match config.sys { |     let sys = match config.sys { | ||||||
|         Sysclk::HSI => (HSI_FREQ, Sw::HSI), |         Sysclk::HSI => unwrap!(hsi), | ||||||
|         Sysclk::HSE => (unwrap!(hse), Sw::HSE), |         Sysclk::HSE => unwrap!(hse), | ||||||
|         Sysclk::PLL1_R => { |         Sysclk::PLL1_R => unwrap!(pll.pll_r), | ||||||
|             assert!(pll_freq.is_some()); |  | ||||||
|             assert!(pll_freq.as_ref().unwrap().pll_r.is_some()); |  | ||||||
| 
 |  | ||||||
|             let freq = pll_freq.as_ref().unwrap().pll_r.unwrap().0; |  | ||||||
| 
 |  | ||||||
|             assert!(max::SYSCLK.contains(&Hertz(freq))); |  | ||||||
| 
 |  | ||||||
|             (Hertz(freq), Sw::PLL1_R) |  | ||||||
|         } |  | ||||||
|         _ => unreachable!(), |         _ => unreachable!(), | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     // Calculate the AHB frequency (HCLK), among other things so we can calculate the correct flash read latency.
 |     assert!(max::SYSCLK.contains(&sys)); | ||||||
|     let hclk = sys_clk / config.ahb_pre; |  | ||||||
| 
 | 
 | ||||||
|  |     // Calculate the AHB frequency (HCLK), among other things so we can calculate the correct flash read latency.
 | ||||||
|  |     let hclk = sys / config.ahb_pre; | ||||||
|     assert!(max::HCLK.contains(&hclk)); |     assert!(max::HCLK.contains(&hclk)); | ||||||
| 
 | 
 | ||||||
|  |     let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); | ||||||
|  |     let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre); | ||||||
|  |     assert!(max::PCLK.contains(&pclk2)); | ||||||
|  |     assert!(max::PCLK.contains(&pclk2)); | ||||||
|  | 
 | ||||||
|     // Configure Core Boost mode ([RM0440] p234 – inverted because setting r1mode to 0 enables boost mode!)
 |     // Configure Core Boost mode ([RM0440] p234 – inverted because setting r1mode to 0 enables boost mode!)
 | ||||||
|     if config.boost { |     if config.boost { | ||||||
|         // RM0440 p235
 |         // RM0440 p235
 | ||||||
| @ -253,9 +251,7 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
|         // 4. Configure and switch to new frequency
 |         // 4. Configure and switch to new frequency
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Configure flash read access latency based on boost mode and frequency (RM0440 p98)
 |     let latency = match (config.boost, hclk.0) { | ||||||
|     FLASH.acr().modify(|w| { |  | ||||||
|         w.set_latency(match (config.boost, hclk.0) { |  | ||||||
|         (true, ..=34_000_000) => Latency::WS0, |         (true, ..=34_000_000) => Latency::WS0, | ||||||
|         (true, ..=68_000_000) => Latency::WS1, |         (true, ..=68_000_000) => Latency::WS1, | ||||||
|         (true, ..=102_000_000) => Latency::WS2, |         (true, ..=102_000_000) => Latency::WS2, | ||||||
| @ -267,9 +263,16 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
|         (false, ..=90_000_000) => Latency::WS2, |         (false, ..=90_000_000) => Latency::WS2, | ||||||
|         (false, ..=120_000_000) => Latency::WS3, |         (false, ..=120_000_000) => Latency::WS3, | ||||||
|         (false, _) => Latency::WS4, |         (false, _) => Latency::WS4, | ||||||
|         }) |     }; | ||||||
|  | 
 | ||||||
|  |     // Configure flash read access latency based on boost mode and frequency (RM0440 p98)
 | ||||||
|  |     FLASH.acr().modify(|w| { | ||||||
|  |         w.set_latency(latency); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     // Spin until the effective flash latency is set.
 | ||||||
|  |     while FLASH.acr().read().latency() != latency {} | ||||||
|  | 
 | ||||||
|     if config.boost { |     if config.boost { | ||||||
|         // 5. Wait for at least 1us and then reconfigure the AHB prescaler to get the needed HCLK clock frequency.
 |         // 5. Wait for at least 1us and then reconfigure the AHB prescaler to get the needed HCLK clock frequency.
 | ||||||
|         cortex_m::asm::delay(16); |         cortex_m::asm::delay(16); | ||||||
| @ -277,17 +280,14 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
| 
 | 
 | ||||||
|     // Now that boost mode and flash read access latency are configured, set up SYSCLK
 |     // Now that boost mode and flash read access latency are configured, set up SYSCLK
 | ||||||
|     RCC.cfgr().modify(|w| { |     RCC.cfgr().modify(|w| { | ||||||
|         w.set_sw(sw); |         w.set_sw(config.sys); | ||||||
|         w.set_hpre(config.ahb_pre); |         w.set_hpre(config.ahb_pre); | ||||||
|         w.set_ppre1(config.apb1_pre); |         w.set_ppre1(config.apb1_pre); | ||||||
|         w.set_ppre2(config.apb2_pre); |         w.set_ppre2(config.apb2_pre); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     let (apb1_freq, apb1_tim_freq) = super::util::calc_pclk(hclk, config.apb1_pre); |  | ||||||
|     let (apb2_freq, apb2_tim_freq) = super::util::calc_pclk(hclk, config.apb2_pre); |  | ||||||
| 
 |  | ||||||
|     if config.low_power_run { |     if config.low_power_run { | ||||||
|         assert!(sys_clk <= Hertz(2_000_000)); |         assert!(sys <= Hertz(2_000_000)); | ||||||
|         PWR.cr1().modify(|w| w.set_lpr(true)); |         PWR.cr1().modify(|w| w.set_lpr(true)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -296,17 +296,18 @@ pub(crate) unsafe fn init(config: Config) { | |||||||
|     config.mux.init(); |     config.mux.init(); | ||||||
| 
 | 
 | ||||||
|     set_clocks!( |     set_clocks!( | ||||||
|         sys: Some(sys_clk), |         sys: Some(sys), | ||||||
|         hclk1: Some(hclk), |         hclk1: Some(hclk), | ||||||
|         hclk2: Some(hclk), |         hclk2: Some(hclk), | ||||||
|         hclk3: Some(hclk), |         hclk3: Some(hclk), | ||||||
|         pclk1: Some(apb1_freq), |         pclk1: Some(pclk1), | ||||||
|         pclk1_tim: Some(apb1_tim_freq), |         pclk1_tim: Some(pclk1_tim), | ||||||
|         pclk2: Some(apb2_freq), |         pclk2: Some(pclk2), | ||||||
|         pclk2_tim: Some(apb2_tim_freq), |         pclk2_tim: Some(pclk2_tim), | ||||||
|         pll1_p: pll_freq.as_ref().and_then(|pll| pll.pll_p), |         pll1_p: pll.pll_p, | ||||||
|         pll1_q: pll_freq.as_ref().and_then(|pll| pll.pll_q), |         pll1_q: pll.pll_q, | ||||||
|         pll1_r: pll_freq.as_ref().and_then(|pll| pll.pll_r), |         pll1_r: pll.pll_r, | ||||||
|  |         hsi: hsi, | ||||||
|         hse: hse, |         hse: hse, | ||||||
|         hsi48: hsi48, |         hsi48: hsi48, | ||||||
|         rtc: rtc, |         rtc: rtc, | ||||||
| @ -342,4 +343,7 @@ mod max { | |||||||
| 
 | 
 | ||||||
|     /// PLL VCO (internal) Frequency Range (STM32G474 Datasheet p123, Table 46)
 |     /// PLL VCO (internal) Frequency Range (STM32G474 Datasheet p123, Table 46)
 | ||||||
|     pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(96_000_000)..=Hertz(344_000_000); |     pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(96_000_000)..=Hertz(344_000_000); | ||||||
|  |     pub(crate) const PLL_P: RangeInclusive<Hertz> = Hertz(2_064_500)..=Hertz(170_000_000); | ||||||
|  |     pub(crate) const PLL_Q: RangeInclusive<Hertz> = Hertz(8_000_000)..=Hertz(170_000_000); | ||||||
|  |     pub(crate) const PLL_R: RangeInclusive<Hertz> = Hertz(8_000_000)..=Hertz(170_000_000); | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { | |||||||
|     { |     { | ||||||
|         use embassy_stm32::rcc::*; |         use embassy_stm32::rcc::*; | ||||||
|         config.rcc.pll = Some(Pll { |         config.rcc.pll = Some(Pll { | ||||||
|             source: Pllsrc::HSI, |             source: PllSource::HSI, | ||||||
|             prediv: PllPreDiv::DIV4, |             prediv: PllPreDiv::DIV4, | ||||||
|             mul: PllMul::MUL85, |             mul: PllMul::MUL85, | ||||||
|             divp: None, |             divp: None, | ||||||
|  | |||||||
| @ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { | |||||||
|             mode: HseMode::Oscillator, |             mode: HseMode::Oscillator, | ||||||
|         }); |         }); | ||||||
|         config.rcc.pll = Some(Pll { |         config.rcc.pll = Some(Pll { | ||||||
|             source: Pllsrc::HSE, |             source: PllSource::HSE, | ||||||
|             prediv: PllPreDiv::DIV6, |             prediv: PllPreDiv::DIV6, | ||||||
|             mul: PllMul::MUL85, |             mul: PllMul::MUL85, | ||||||
|             divp: None, |             divp: None, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ | |||||||
| 
 | 
 | ||||||
| use defmt::*; | use defmt::*; | ||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllRDiv, Pllsrc, Sysclk}; |  | ||||||
| use embassy_stm32::Config; | use embassy_stm32::Config; | ||||||
| use embassy_time::Timer; | use embassy_time::Timer; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
| @ -11,10 +10,11 @@ use {defmt_rtt as _, panic_probe as _}; | |||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
| async fn main(_spawner: Spawner) { | async fn main(_spawner: Spawner) { | ||||||
|     let mut config = Config::default(); |     let mut config = Config::default(); | ||||||
| 
 |     { | ||||||
|  |         use embassy_stm32::rcc::*; | ||||||
|         config.rcc.hsi = true; |         config.rcc.hsi = true; | ||||||
|         config.rcc.pll = Some(Pll { |         config.rcc.pll = Some(Pll { | ||||||
|         source: Pllsrc::HSI, |             source: PllSource::HSI, | ||||||
|             prediv: PllPreDiv::DIV4, |             prediv: PllPreDiv::DIV4, | ||||||
|             mul: PllMul::MUL85, |             mul: PllMul::MUL85, | ||||||
|             divp: None, |             divp: None, | ||||||
| @ -22,9 +22,8 @@ async fn main(_spawner: Spawner) { | |||||||
|             // Main system clock at 170 MHz
 |             // Main system clock at 170 MHz
 | ||||||
|             divr: Some(PllRDiv::DIV2), |             divr: Some(PllRDiv::DIV2), | ||||||
|         }); |         }); | ||||||
| 
 |  | ||||||
|         config.rcc.sys = Sysclk::PLL1_R; |         config.rcc.sys = Sysclk::PLL1_R; | ||||||
| 
 |     } | ||||||
|     let _p = embassy_stm32::init(config); |     let _p = embassy_stm32::init(config); | ||||||
|     info!("Hello World!"); |     info!("Hello World!"); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ async fn main(_spawner: Spawner) { | |||||||
|             mode: HseMode::Oscillator, |             mode: HseMode::Oscillator, | ||||||
|         }); |         }); | ||||||
|         config.rcc.pll = Some(Pll { |         config.rcc.pll = Some(Pll { | ||||||
|             source: Pllsrc::HSE, |             source: PllSource::HSE, | ||||||
|             prediv: PllPreDiv::DIV2, |             prediv: PllPreDiv::DIV2, | ||||||
|             mul: PllMul::MUL72, |             mul: PllMul::MUL72, | ||||||
|             divp: None, |             divp: None, | ||||||
|  | |||||||
| @ -456,7 +456,7 @@ pub fn config() -> Config { | |||||||
|             mode: HseMode::Oscillator, |             mode: HseMode::Oscillator, | ||||||
|         }); |         }); | ||||||
|         config.rcc.pll = Some(Pll { |         config.rcc.pll = Some(Pll { | ||||||
|             source: Pllsrc::HSE, |             source: PllSource::HSE, | ||||||
|             prediv: PllPreDiv::DIV6, |             prediv: PllPreDiv::DIV6, | ||||||
|             mul: PllMul::MUL85, |             mul: PllMul::MUL85, | ||||||
|             divp: None, |             divp: None, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user