aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/rcc/l0l1.rs189
-rw-r--r--embassy-stm32/src/rcc/l4l5.rs3
-rw-r--r--examples/stm32l0/src/bin/button_exti.rs2
-rw-r--r--examples/stm32l0/src/bin/lora_cad.rs2
-rw-r--r--examples/stm32l0/src/bin/lora_lorawan.rs2
-rw-r--r--examples/stm32l0/src/bin/lora_p2p_receive.rs2
-rw-r--r--examples/stm32l0/src/bin/lora_p2p_send.rs2
-rw-r--r--tests/stm32/src/common.rs26
8 files changed, 120 insertions, 108 deletions
diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs
index 9fb2062d6..3af279595 100644
--- a/embassy-stm32/src/rcc/l0l1.rs
+++ b/embassy-stm32/src/rcc/l0l1.rs
@@ -1,8 +1,8 @@
1pub use crate::pac::pwr::vals::Vos as VoltageScale; 1pub use crate::pac::pwr::vals::Vos as VoltageScale;
2pub use crate::pac::rcc::vals::{ 2pub use crate::pac::rcc::vals::{
3 Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler, 3 Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Plldiv as PllDiv, Pllmul as PLLMul, Pllmul as PllMul,
4 Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
4}; 5};
5use crate::pac::rcc::vals::{Pllsrc, Sw};
6#[cfg(crs)] 6#[cfg(crs)]
7use crate::pac::{crs, CRS, SYSCFG}; 7use crate::pac::{crs, CRS, SYSCFG};
8use crate::pac::{FLASH, PWR, RCC}; 8use crate::pac::{FLASH, PWR, RCC};
@@ -12,39 +12,50 @@ use crate::time::Hertz;
12/// HSI speed 12/// HSI speed
13pub const HSI_FREQ: Hertz = Hertz(16_000_000); 13pub const HSI_FREQ: Hertz = Hertz(16_000_000);
14 14
15/// System clock mux source 15#[derive(Clone, Copy, Eq, PartialEq)]
16#[derive(Clone, Copy)] 16pub enum HseMode {
17pub enum ClockSrc { 17 /// crystal/ceramic oscillator (HSEBYP=0)
18 MSI(MSIRange), 18 Oscillator,
19 PLL(PLLSource, PLLMul, PLLDiv), 19 /// external analog clock (low swing) (HSEBYP=1)
20 HSE(Hertz), 20 Bypass,
21 HSI,
22} 21}
23 22
24/// PLL clock input source 23#[derive(Clone, Copy, Eq, PartialEq)]
25#[derive(Clone, Copy)] 24pub struct Hse {
26pub enum PLLSource { 25 /// HSE frequency.
27 HSI, 26 pub freq: Hertz,
28 HSE(Hertz), 27 /// HSE mode.
28 pub mode: HseMode,
29} 29}
30 30
31impl From<PLLSource> for Pllsrc { 31#[derive(Clone, Copy)]
32 fn from(val: PLLSource) -> Pllsrc { 32pub struct Pll {
33 match val { 33 /// PLL source
34 PLLSource::HSI => Pllsrc::HSI, 34 pub source: PLLSource,
35 PLLSource::HSE(_) => Pllsrc::HSE, 35
36 } 36 /// PLL multiplication factor.
37 } 37 pub mul: PllMul,
38
39 /// PLL main output division factor.
40 pub div: PllDiv,
38} 41}
39 42
40/// Clocks configutation 43/// Clocks configutation
41pub struct Config { 44pub struct Config {
45 // base clock sources
46 pub msi: Option<MSIRange>,
47 pub hsi: bool,
48 pub hse: Option<Hse>,
49 #[cfg(crs)]
50 pub hsi48: bool,
51
52 pub pll: Option<Pll>,
53
42 pub mux: ClockSrc, 54 pub mux: ClockSrc,
43 pub ahb_pre: AHBPrescaler, 55 pub ahb_pre: AHBPrescaler,
44 pub apb1_pre: APBPrescaler, 56 pub apb1_pre: APBPrescaler,
45 pub apb2_pre: APBPrescaler, 57 pub apb2_pre: APBPrescaler,
46 #[cfg(crs)] 58
47 pub enable_hsi48: bool,
48 pub ls: super::LsConfig, 59 pub ls: super::LsConfig,
49 pub voltage_scale: VoltageScale, 60 pub voltage_scale: VoltageScale,
50} 61}
@@ -53,12 +64,18 @@ impl Default for Config {
53 #[inline] 64 #[inline]
54 fn default() -> Config { 65 fn default() -> Config {
55 Config { 66 Config {
56 mux: ClockSrc::MSI(MSIRange::RANGE5), 67 msi: Some(MSIRange::RANGE5),
68 hse: None,
69 hsi: false,
70 #[cfg(crs)]
71 hsi48: false,
72
73 pll: None,
74
75 mux: ClockSrc::MSI,
57 ahb_pre: AHBPrescaler::DIV1, 76 ahb_pre: AHBPrescaler::DIV1,
58 apb1_pre: APBPrescaler::DIV1, 77 apb1_pre: APBPrescaler::DIV1,
59 apb2_pre: APBPrescaler::DIV1, 78 apb2_pre: APBPrescaler::DIV1,
60 #[cfg(crs)]
61 enable_hsi48: false,
62 voltage_scale: VoltageScale::RANGE1, 79 voltage_scale: VoltageScale::RANGE1,
63 ls: Default::default(), 80 ls: Default::default(),
64 } 81 }
@@ -71,71 +88,67 @@ pub(crate) unsafe fn init(config: Config) {
71 PWR.cr().write(|w| w.set_vos(config.voltage_scale)); 88 PWR.cr().write(|w| w.set_vos(config.voltage_scale));
72 while PWR.csr().read().vosf() {} 89 while PWR.csr().read().vosf() {}
73 90
74 let (sys_clk, sw) = match config.mux { 91 let rtc = config.ls.init();
75 ClockSrc::MSI(range) => {
76 // Set MSI range
77 RCC.icscr().write(|w| w.set_msirange(range));
78 92
79 // Enable MSI 93 let msi = config.msi.map(|range| {
80 RCC.cr().write(|w| w.set_msion(true)); 94 RCC.icscr().modify(|w| w.set_msirange(range));
81 while !RCC.cr().read().msirdy() {}
82 95
83 let freq = 32_768 * (1 << (range as u8 + 1)); 96 RCC.cr().modify(|w| w.set_msion(true));
84 (Hertz(freq), Sw::MSI) 97 while !RCC.cr().read().msirdy() {}
85 }
86 ClockSrc::HSI => {
87 // Enable HSI
88 RCC.cr().write(|w| w.set_hsion(true));
89 while !RCC.cr().read().hsirdy() {}
90 98
91 (HSI_FREQ, Sw::HSI) 99 Hertz(32_768 * (1 << (range as u8 + 1)))
92 } 100 });
93 ClockSrc::HSE(freq) => {
94 // Enable HSE
95 RCC.cr().write(|w| w.set_hseon(true));
96 while !RCC.cr().read().hserdy() {}
97 101
98 (freq, Sw::HSE) 102 let hsi = config.hsi.then(|| {
99 } 103 RCC.cr().modify(|w| w.set_hsion(true));
100 ClockSrc::PLL(src, mul, div) => { 104 while !RCC.cr().read().hsirdy() {}
101 let freq = match src {
102 PLLSource::HSE(freq) => {
103 // Enable HSE
104 RCC.cr().write(|w| w.set_hseon(true));
105 while !RCC.cr().read().hserdy() {}
106 freq
107 }
108 PLLSource::HSI => {
109 // Enable HSI
110 RCC.cr().write(|w| w.set_hsion(true));
111 while !RCC.cr().read().hsirdy() {}
112 HSI_FREQ
113 }
114 };
115
116 // Disable PLL
117 RCC.cr().modify(|w| w.set_pllon(false));
118 while RCC.cr().read().pllrdy() {}
119
120 let freq = freq * mul / div;
121
122 assert!(freq <= Hertz(32_000_000));
123
124 RCC.cfgr().write(move |w| {
125 w.set_pllmul(mul);
126 w.set_plldiv(div);
127 w.set_pllsrc(src.into());
128 });
129
130 // Enable PLL
131 RCC.cr().modify(|w| w.set_pllon(true));
132 while !RCC.cr().read().pllrdy() {}
133
134 (freq, Sw::PLL1_P)
135 }
136 };
137 105
138 let rtc = config.ls.init(); 106 HSI_FREQ
107 });
108
109 let hse = config.hse.map(|hse| {
110 RCC.cr().modify(|w| {
111 w.set_hsebyp(hse.mode == HseMode::Bypass);
112 w.set_hseon(true);
113 });
114 while !RCC.cr().read().hserdy() {}
115
116 hse.freq
117 });
118
119 let pll = config.pll.map(|pll| {
120 let freq = match pll.source {
121 PLLSource::HSE => hse.unwrap(),
122 PLLSource::HSI => hsi.unwrap(),
123 };
124
125 // Disable PLL
126 RCC.cr().modify(|w| w.set_pllon(false));
127 while RCC.cr().read().pllrdy() {}
128
129 let freq = freq * pll.mul / pll.div;
130
131 assert!(freq <= Hertz(32_000_000));
132
133 RCC.cfgr().write(move |w| {
134 w.set_pllmul(pll.mul);
135 w.set_plldiv(pll.div);
136 w.set_pllsrc(pll.source);
137 });
138
139 // Enable PLL
140 RCC.cr().modify(|w| w.set_pllon(true));
141 while !RCC.cr().read().pllrdy() {}
142
143 freq
144 });
145
146 let sys_clk = match config.mux {
147 ClockSrc::HSE => hse.unwrap(),
148 ClockSrc::HSI => hsi.unwrap(),
149 ClockSrc::MSI => msi.unwrap(),
150 ClockSrc::PLL1_P => pll.unwrap(),
151 };
139 152
140 let wait_states = match (config.voltage_scale, sys_clk.0) { 153 let wait_states = match (config.voltage_scale, sys_clk.0) {
141 (VoltageScale::RANGE1, ..=16_000_000) => 0, 154 (VoltageScale::RANGE1, ..=16_000_000) => 0,
@@ -150,7 +163,7 @@ pub(crate) unsafe fn init(config: Config) {
150 FLASH.acr().modify(|w| w.set_latency(wait_states != 0)); 163 FLASH.acr().modify(|w| w.set_latency(wait_states != 0));
151 164
152 RCC.cfgr().modify(|w| { 165 RCC.cfgr().modify(|w| {
153 w.set_sw(sw); 166 w.set_sw(config.mux);
154 w.set_hpre(config.ahb_pre); 167 w.set_hpre(config.ahb_pre);
155 w.set_ppre1(config.apb1_pre); 168 w.set_ppre1(config.apb1_pre);
156 w.set_ppre2(config.apb2_pre); 169 w.set_ppre2(config.apb2_pre);
@@ -161,7 +174,7 @@ pub(crate) unsafe fn init(config: Config) {
161 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); 174 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
162 175
163 #[cfg(crs)] 176 #[cfg(crs)]
164 if config.enable_hsi48 { 177 if config.hsi48 {
165 // Reset CRS peripheral 178 // Reset CRS peripheral
166 RCC.apb1rstr().modify(|w| w.set_crsrst(true)); 179 RCC.apb1rstr().modify(|w| w.set_crsrst(true));
167 RCC.apb1rstr().modify(|w| w.set_crsrst(false)); 180 RCC.apb1rstr().modify(|w| w.set_crsrst(false));
diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs
index 0d052713f..44748620c 100644
--- a/embassy-stm32/src/rcc/l4l5.rs
+++ b/embassy-stm32/src/rcc/l4l5.rs
@@ -193,9 +193,6 @@ pub(crate) unsafe fn init(config: Config) {
193 }); 193 });
194 while !RCC.cr().read().msirdy() {} 194 while !RCC.cr().read().msirdy() {}
195 195
196 // Enable as clock source for USB, RNG if running at 48 MHz
197 if range == MSIRange::RANGE48M {}
198
199 msirange_to_hertz(range) 196 msirange_to_hertz(range)
200 }); 197 });
201 198
diff --git a/examples/stm32l0/src/bin/button_exti.rs b/examples/stm32l0/src/bin/button_exti.rs
index af82b9955..441b00c6d 100644
--- a/examples/stm32l0/src/bin/button_exti.rs
+++ b/examples/stm32l0/src/bin/button_exti.rs
@@ -12,7 +12,7 @@ use {defmt_rtt as _, panic_probe as _};
12#[embassy_executor::main] 12#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 13async fn main(_spawner: Spawner) {
14 let mut config = Config::default(); 14 let mut config = Config::default();
15 config.rcc.enable_hsi48 = true; 15 config.rcc.hsi48 = true;
16 let p = embassy_stm32::init(config); 16 let p = embassy_stm32::init(config);
17 17
18 let button = Input::new(p.PB2, Pull::Up); 18 let button = Input::new(p.PB2, Pull::Up);
diff --git a/examples/stm32l0/src/bin/lora_cad.rs b/examples/stm32l0/src/bin/lora_cad.rs
index 5c2b331cc..61024ef79 100644
--- a/examples/stm32l0/src/bin/lora_cad.rs
+++ b/examples/stm32l0/src/bin/lora_cad.rs
@@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
24async fn main(_spawner: Spawner) { 24async fn main(_spawner: Spawner) {
25 let mut config = embassy_stm32::Config::default(); 25 let mut config = embassy_stm32::Config::default();
26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; 26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
27 config.rcc.enable_hsi48 = true; 27 config.rcc.hsi48 = true;
28 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
29 29
30 let mut spi_config = spi::Config::default(); 30 let mut spi_config = spi::Config::default();
diff --git a/examples/stm32l0/src/bin/lora_lorawan.rs b/examples/stm32l0/src/bin/lora_lorawan.rs
index d44d03d3b..9c4f32916 100644
--- a/examples/stm32l0/src/bin/lora_lorawan.rs
+++ b/examples/stm32l0/src/bin/lora_lorawan.rs
@@ -34,7 +34,7 @@ const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set th
34async fn main(_spawner: Spawner) { 34async fn main(_spawner: Spawner) {
35 let mut config = embassy_stm32::Config::default(); 35 let mut config = embassy_stm32::Config::default();
36 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; 36 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
37 config.rcc.enable_hsi48 = true; 37 config.rcc.hsi48 = true;
38 let p = embassy_stm32::init(config); 38 let p = embassy_stm32::init(config);
39 39
40 let mut spi_config = spi::Config::default(); 40 let mut spi_config = spi::Config::default();
diff --git a/examples/stm32l0/src/bin/lora_p2p_receive.rs b/examples/stm32l0/src/bin/lora_p2p_receive.rs
index 0478ce1ea..4a50182c2 100644
--- a/examples/stm32l0/src/bin/lora_p2p_receive.rs
+++ b/examples/stm32l0/src/bin/lora_p2p_receive.rs
@@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
24async fn main(_spawner: Spawner) { 24async fn main(_spawner: Spawner) {
25 let mut config = embassy_stm32::Config::default(); 25 let mut config = embassy_stm32::Config::default();
26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; 26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
27 config.rcc.enable_hsi48 = true; 27 config.rcc.hsi48 = true;
28 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
29 29
30 let mut spi_config = spi::Config::default(); 30 let mut spi_config = spi::Config::default();
diff --git a/examples/stm32l0/src/bin/lora_p2p_send.rs b/examples/stm32l0/src/bin/lora_p2p_send.rs
index 88a836d36..f6de6a5cd 100644
--- a/examples/stm32l0/src/bin/lora_p2p_send.rs
+++ b/examples/stm32l0/src/bin/lora_p2p_send.rs
@@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
24async fn main(_spawner: Spawner) { 24async fn main(_spawner: Spawner) {
25 let mut config = embassy_stm32::Config::default(); 25 let mut config = embassy_stm32::Config::default();
26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; 26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
27 config.rcc.enable_hsi48 = true; 27 config.rcc.hsi48 = true;
28 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
29 29
30 let mut spi_config = spi::Config::default(); 30 let mut spi_config = spi::Config::default();
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index ff808281a..54e23e436 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -460,23 +460,25 @@ pub fn config() -> Config {
460 #[cfg(feature = "stm32l073rz")] 460 #[cfg(feature = "stm32l073rz")]
461 { 461 {
462 use embassy_stm32::rcc::*; 462 use embassy_stm32::rcc::*;
463 config.rcc.mux = ClockSrc::PLL( 463 config.rcc.hsi = true;
464 // 32Mhz clock (16 * 4 / 2) 464 config.rcc.pll = Some(Pll {
465 PLLSource::HSI, 465 source: PLLSource::HSI,
466 PLLMul::MUL4, 466 mul: PLLMul::MUL4,
467 PLLDiv::DIV2, 467 div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
468 ); 468 });
469 config.rcc.mux = ClockSrc::PLL1_P;
469 } 470 }
470 471
471 #[cfg(any(feature = "stm32l152re"))] 472 #[cfg(any(feature = "stm32l152re"))]
472 { 473 {
473 use embassy_stm32::rcc::*; 474 use embassy_stm32::rcc::*;
474 config.rcc.mux = ClockSrc::PLL( 475 config.rcc.hsi = true;
475 // 32Mhz clock (16 * 4 / 2) 476 config.rcc.pll = Some(Pll {
476 PLLSource::HSI, 477 source: PLLSource::HSI,
477 PLLMul::MUL4, 478 mul: PLLMul::MUL4,
478 PLLDiv::DIV2, 479 div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
479 ); 480 });
481 config.rcc.mux = ClockSrc::PLL1_P;
480 } 482 }
481 483
482 config 484 config