aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-09-10 13:33:17 -0500
committerxoviat <[email protected]>2023-09-10 13:33:17 -0500
commit08415e001e93a35579a8fc8e41147df96d80da84 (patch)
tree2dc48380b549dc5c366567d0dbb7e9a356486ef7
parenta47fb42962fffda51efbce072087c8ca2504a225 (diff)
stm32/f3: add high res for hrtim and misc.
-rw-r--r--embassy-stm32/src/adc/f1.rs2
-rw-r--r--embassy-stm32/src/hrtim/mod.rs36
-rw-r--r--embassy-stm32/src/hrtim/traits.rs12
-rw-r--r--embassy-stm32/src/rcc/f1.rs2
-rw-r--r--embassy-stm32/src/rcc/f3.rs199
-rw-r--r--embassy-stm32/src/rcc/mod.rs8
-rw-r--r--examples/stm32f334/src/bin/adc.rs16
-rw-r--r--examples/stm32f334/src/bin/pwm.rs2
8 files changed, 184 insertions, 93 deletions
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index e577ec289..147349de6 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -60,7 +60,7 @@ impl<'d, T: Instance> Adc<'d, T> {
60 } 60 }
61 61
62 fn freq() -> Hertz { 62 fn freq() -> Hertz {
63 unsafe { get_freqs() }.adc 63 unsafe { get_freqs() }.adc.unwrap()
64 } 64 }
65 65
66 pub fn sample_time_for_us(&self, us: u32) -> SampleTime { 66 pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 31c488144..c47b0c092 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -8,6 +8,8 @@ pub use traits::Instance;
8#[allow(unused_imports)] 8#[allow(unused_imports)]
9use crate::gpio::sealed::{AFType, Pin}; 9use crate::gpio::sealed::{AFType, Pin};
10use crate::gpio::AnyPin; 10use crate::gpio::AnyPin;
11#[cfg(stm32f334)]
12use crate::rcc::get_freqs;
11use crate::time::Hertz; 13use crate::time::Hertz;
12use crate::Peripheral; 14use crate::Peripheral;
13 15
@@ -158,17 +160,29 @@ impl<'d, T: Instance> AdvancedPwm<'d, T> {
158 T::enable(); 160 T::enable();
159 <T as crate::rcc::sealed::RccPeripheral>::reset(); 161 <T as crate::rcc::sealed::RccPeripheral>::reset();
160 162
161 // // Enable and and stabilize the DLL 163 #[cfg(stm32f334)]
162 // T::regs().dllcr().modify(|w| { 164 if unsafe { get_freqs() }.hrtim.is_some() {
163 // // w.set_calen(true); 165 // Enable and and stabilize the DLL
164 // // w.set_calrte(11); 166 T::regs().dllcr().modify(|w| {
165 // w.set_cal(true); 167 w.set_cal(true);
166 // }); 168 });
167 // 169
168 // debug!("wait for dll calibration"); 170 trace!("hrtim: wait for dll calibration");
169 // while !T::regs().isr().read().dllrdy() {} 171 while !T::regs().isr().read().dllrdy() {}
170 // 172
171 // debug!("dll calibration complete"); 173 trace!("hrtim: dll calibration complete");
174
175 // Enable periodic calibration
176 // Cal must be disabled before we can enable it
177 T::regs().dllcr().modify(|w| {
178 w.set_cal(false);
179 });
180
181 T::regs().dllcr().modify(|w| {
182 w.set_calen(true);
183 w.set_calrte(11);
184 });
185 }
172 186
173 Self { 187 Self {
174 _inner: tim, 188 _inner: tim,
diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs
index 095109598..37cfb9b90 100644
--- a/embassy-stm32/src/hrtim/traits.rs
+++ b/embassy-stm32/src/hrtim/traits.rs
@@ -104,7 +104,13 @@ foreach_interrupt! {
104 use crate::rcc::sealed::RccPeripheral; 104 use crate::rcc::sealed::RccPeripheral;
105 105
106 let f = frequency.0; 106 let f = frequency.0;
107 #[cfg(not(stm32f334))]
107 let timer_f = Self::frequency().0; 108 let timer_f = Self::frequency().0;
109 #[cfg(stm32f334)]
110 let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(
111 Self::frequency()
112 ).0;
113
108 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); 114 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
109 let psc = if Self::regs().isr().read().dllrdy() { 115 let psc = if Self::regs().isr().read().dllrdy() {
110 Prescaler::compute_min_high_res(psc_min) 116 Prescaler::compute_min_high_res(psc_min)
@@ -125,7 +131,13 @@ foreach_interrupt! {
125 use crate::rcc::sealed::RccPeripheral; 131 use crate::rcc::sealed::RccPeripheral;
126 132
127 let f = frequency.0; 133 let f = frequency.0;
134 #[cfg(not(stm32f334))]
128 let timer_f = Self::frequency().0; 135 let timer_f = Self::frequency().0;
136 #[cfg(stm32f334)]
137 let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(
138 Self::frequency()
139 ).0;
140
129 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); 141 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
130 let psc = if Self::regs().isr().read().dllrdy() { 142 let psc = if Self::regs().isr().read().dllrdy() {
131 Prescaler::compute_min_high_res(psc_min) 143 Prescaler::compute_min_high_res(psc_min)
diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs
index b6200231e..304d8f504 100644
--- a/embassy-stm32/src/rcc/f1.rs
+++ b/embassy-stm32/src/rcc/f1.rs
@@ -184,6 +184,6 @@ pub(crate) unsafe fn init(config: Config) {
184 apb1_tim: Hertz(pclk1 * timer_mul1), 184 apb1_tim: Hertz(pclk1 * timer_mul1),
185 apb2_tim: Hertz(pclk2 * timer_mul2), 185 apb2_tim: Hertz(pclk2 * timer_mul2),
186 ahb1: Hertz(hclk), 186 ahb1: Hertz(hclk),
187 adc: Hertz(adcclk), 187 adc: Some(Hertz(adcclk)),
188 }); 188 });
189} 189}
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index f8726c24a..cbbe4f98b 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -1,3 +1,5 @@
1#[cfg(rcc_f3)]
2use crate::pac::adccommon::vals::Ckmode;
1use crate::pac::flash::vals::Latency; 3use crate::pac::flash::vals::Latency;
2use crate::pac::rcc::vals::{Adcpres, Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}; 4use crate::pac::rcc::vals::{Adcpres, Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
3use crate::pac::{FLASH, RCC}; 5use crate::pac::{FLASH, RCC};
@@ -10,44 +12,80 @@ pub const HSI_FREQ: Hertz = Hertz(8_000_000);
10/// LSI speed 12/// LSI speed
11pub const LSI_FREQ: Hertz = Hertz(40_000); 13pub const LSI_FREQ: Hertz = Hertz(40_000);
12 14
13#[repr(u16)] 15impl From<AdcClockSource> for Adcpres {
14#[derive(Clone, Copy)] 16 fn from(value: AdcClockSource) -> Self {
15pub enum ADCPrescaler { 17 match value {
16 Div1 = 1, 18 AdcClockSource::PllDiv1 => Adcpres::DIV1,
17 Div2 = 2, 19 AdcClockSource::PllDiv2 => Adcpres::DIV2,
18 Div4 = 4, 20 AdcClockSource::PllDiv4 => Adcpres::DIV4,
19 Div6 = 6, 21 AdcClockSource::PllDiv6 => Adcpres::DIV6,
20 Div8 = 8, 22 AdcClockSource::PllDiv8 => Adcpres::DIV8,
21 Div12 = 12, 23 AdcClockSource::PllDiv12 => Adcpres::DIV12,
22 Div16 = 16, 24 AdcClockSource::PllDiv16 => Adcpres::DIV16,
23 Div32 = 32, 25 AdcClockSource::PllDiv32 => Adcpres::DIV32,
24 Div64 = 64, 26 AdcClockSource::PllDiv64 => Adcpres::DIV64,
25 Div128 = 128, 27 AdcClockSource::PllDiv128 => Adcpres::DIV128,
26 Div256 = 256, 28 AdcClockSource::PllDiv256 => Adcpres::DIV256,
29 _ => unreachable!(),
30 }
31 }
27} 32}
28 33
29impl From<ADCPrescaler> for Adcpres { 34#[cfg(rcc_f3)]
30 fn from(value: ADCPrescaler) -> Self { 35impl From<AdcClockSource> for Ckmode {
36 fn from(value: AdcClockSource) -> Self {
31 match value { 37 match value {
32 ADCPrescaler::Div1 => Adcpres::DIV1, 38 AdcClockSource::BusDiv1 => Ckmode::SYNCDIV1,
33 ADCPrescaler::Div2 => Adcpres::DIV2, 39 AdcClockSource::BusDiv2 => Ckmode::SYNCDIV2,
34 ADCPrescaler::Div4 => Adcpres::DIV4, 40 AdcClockSource::BusDiv4 => Ckmode::SYNCDIV4,
35 ADCPrescaler::Div6 => Adcpres::DIV6, 41 _ => unreachable!(),
36 ADCPrescaler::Div8 => Adcpres::DIV8,
37 ADCPrescaler::Div12 => Adcpres::DIV12,
38 ADCPrescaler::Div16 => Adcpres::DIV16,
39 ADCPrescaler::Div32 => Adcpres::DIV32,
40 ADCPrescaler::Div64 => Adcpres::DIV64,
41 ADCPrescaler::Div128 => Adcpres::DIV128,
42 ADCPrescaler::Div256 => Adcpres::DIV256,
43 } 42 }
44 } 43 }
45} 44}
46 45
47#[derive(Clone, Copy)] 46#[derive(Clone, Copy)]
48pub enum ADCClock { 47pub enum AdcClockSource {
49 AHB(ADCPrescaler), 48 PllDiv1 = 1,
50 PLL(ADCPrescaler), 49 PllDiv2 = 2,
50 PllDiv4 = 4,
51 PllDiv6 = 6,
52 PllDiv8 = 8,
53 PllDiv12 = 12,
54 PllDiv16 = 16,
55 PllDiv32 = 32,
56 PllDiv64 = 64,
57 PllDiv128 = 128,
58 PllDiv256 = 256,
59 BusDiv1,
60 BusDiv2,
61 BusDiv4,
62}
63
64impl AdcClockSource {
65 pub fn is_bus(&self) -> bool {
66 match self {
67 Self::BusDiv1 => true,
68 Self::BusDiv2 => true,
69 Self::BusDiv4 => true,
70 _ => false,
71 }
72 }
73
74 pub fn bus_div(&self) -> u32 {
75 match self {
76 Self::BusDiv1 => 1,
77 Self::BusDiv2 => 2,
78 Self::BusDiv4 => 4,
79 _ => unreachable!(),
80 }
81 }
82}
83
84#[derive(Default)]
85pub enum HrtimClockSource {
86 #[default]
87 BusClk,
88 PllClk,
51} 89}
52 90
53/// Clocks configutation 91/// Clocks configutation
@@ -79,11 +117,13 @@ pub struct Config {
79 #[cfg(rcc_f3)] 117 #[cfg(rcc_f3)]
80 /// ADC clock setup 118 /// ADC clock setup
81 /// - For AHB, a psc of 4 or less must be used 119 /// - For AHB, a psc of 4 or less must be used
82 pub adc: Option<ADCClock>, 120 pub adc: Option<AdcClockSource>,
83 #[cfg(rcc_f3)] 121 #[cfg(rcc_f3)]
84 /// ADC clock setup 122 /// ADC clock setup
85 /// - For AHB, a psc of 4 or less must be used 123 /// - For AHB, a psc of 4 or less must be used
86 pub adc34: Option<ADCClock>, 124 pub adc34: Option<AdcClockSource>,
125 #[cfg(stm32f334)]
126 pub hrtim: HrtimClockSource,
87} 127}
88 128
89// Information required to setup the PLL clock 129// Information required to setup the PLL clock
@@ -197,44 +237,6 @@ pub(crate) unsafe fn init(config: Config) {
197 }); 237 });
198 } 238 }
199 239
200 #[cfg(rcc_f3)]
201 let adc = config.adc.map(|adc| match adc {
202 ADCClock::PLL(psc) => RCC.cfgr2().modify(|w| {
203 // Make sure that we're using the PLL
204 pll_config.unwrap();
205 w.set_adc12pres(psc.into());
206
207 Hertz(sysclk / psc as u32)
208 }),
209 ADCClock::AHB(psc) => {
210 assert!(psc as u16 <= 4);
211 assert!(!(psc as u16 == 1 && hpre_bits != Hpre::DIV1));
212
213 // To select this scheme, bits CKMODE[1:0] of the ADCx_CCR register must be
214 // different from “00”.
215 todo!();
216 }
217 });
218
219 #[cfg(rcc_f3)]
220 let adc34 = config.adc34.map(|adc| match adc {
221 ADCClock::PLL(psc) => RCC.cfgr2().modify(|w| {
222 // Make sure that we're using the PLL
223 pll_config.unwrap();
224 w.set_adc34pres(psc.into());
225
226 Hertz(sysclk / psc as u32)
227 }),
228 ADCClock::AHB(psc) => {
229 assert!(psc as u16 <= 4);
230 assert!(!(psc as u16 == 1 && hpre_bits != Hpre::DIV1));
231
232 // To select this scheme, bits CKMODE[1:0] of the ADCx_CCR register must be
233 // different from “00”.
234 todo!();
235 }
236 });
237
238 // Set prescalers 240 // Set prescalers
239 // CFGR has been written before (PLL, PLL48) don't overwrite these settings 241 // CFGR has been written before (PLL, PLL48) don't overwrite these settings
240 RCC.cfgr().modify(|w| { 242 RCC.cfgr().modify(|w| {
@@ -257,6 +259,61 @@ pub(crate) unsafe fn init(config: Config) {
257 }) 259 })
258 }); 260 });
259 261
262 #[cfg(rcc_f3)]
263 let adc = config.adc.map(|adc| {
264 if !adc.is_bus() {
265 RCC.cfgr2().modify(|w| {
266 // Make sure that we're using the PLL
267 pll_config.unwrap();
268 w.set_adc12pres(adc.into());
269
270 Hertz(sysclk / adc as u32)
271 })
272 } else {
273 crate::pac::ADC_COMMON.ccr().modify(|w| {
274 assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1));
275
276 w.set_ckmode(adc.into());
277
278 Hertz(sysclk / adc.bus_div() as u32)
279 })
280 }
281 });
282
283 #[cfg(rcc_f3)]
284 let adc34 = config.adc.map(|adc| {
285 if !adc.is_bus() {
286 RCC.cfgr2().modify(|w| {
287 // Make sure that we're using the PLL
288 pll_config.unwrap();
289 w.set_adc12pres(adc.into());
290
291 Hertz(sysclk / adc as u32)
292 })
293 } else {
294 // TODO: need to use only if adc32_common is present
295
296 todo!()
297 }
298 });
299
300 #[cfg(stm32f334)]
301 let hrtim = match config.hrtim {
302 // Must be configured after the bus is ready, otherwise it won't work
303 HrtimClockSource::BusClk => None,
304 HrtimClockSource::PllClk => {
305 use crate::pac::rcc::vals::Timsw;
306
307 // Make sure that we're using the PLL
308 pll_config.unwrap();
309 assert!((pclk2 == sysclk) || (pclk2 * 2 == sysclk));
310
311 RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL));
312
313 Some(Hertz(sysclk * 2))
314 }
315 };
316
260 set_freqs(Clocks { 317 set_freqs(Clocks {
261 sys: Hertz(sysclk), 318 sys: Hertz(sysclk),
262 apb1: Hertz(pclk1), 319 apb1: Hertz(pclk1),
@@ -268,6 +325,8 @@ pub(crate) unsafe fn init(config: Config) {
268 adc: adc, 325 adc: adc,
269 #[cfg(rcc_f3)] 326 #[cfg(rcc_f3)]
270 adc34: adc34, 327 adc34: adc34,
328 #[cfg(stm32f334)]
329 hrtim: hrtim,
271 }); 330 });
272} 331}
273 332
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 535ab6ad4..4f0b7fd09 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -71,15 +71,15 @@ pub struct Clocks {
71 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] 71 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
72 pub pllsai: Option<Hertz>, 72 pub pllsai: Option<Hertz>,
73 73
74 #[cfg(stm32f1)] 74 #[cfg(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_f3, rcc_g4))]
75 pub adc: Hertz,
76
77 #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_f3, rcc_g4))]
78 pub adc: Option<Hertz>, 75 pub adc: Option<Hertz>,
79 76
80 #[cfg(any(rcc_f3, rcc_g4))] 77 #[cfg(any(rcc_f3, rcc_g4))]
81 pub adc34: Option<Hertz>, 78 pub adc34: Option<Hertz>,
82 79
80 #[cfg(stm32f334)]
81 pub hrtim: Option<Hertz>,
82
83 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] 83 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
84 /// Set only if the lsi or lse is configured, indicates stop is supported 84 /// Set only if the lsi or lse is configured, indicates stop is supported
85 pub rtc: Option<Hertz>, 85 pub rtc: Option<Hertz>,
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
index 6dffd6731..e8b2cd8a7 100644
--- a/examples/stm32f334/src/bin/adc.rs
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -4,9 +4,9 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, VREF_INT}; 7use embassy_stm32::adc::{Adc, SampleTime, VREF_INT};
8use embassy_stm32::rcc::{ADCClock, ADCPrescaler}; 8use embassy_stm32::rcc::AdcClockSource;
9use embassy_stm32::time::Hertz; 9use embassy_stm32::time::mhz;
10use embassy_stm32::Config; 10use embassy_stm32::Config;
11use embassy_time::{Delay, Duration, Timer}; 11use embassy_time::{Delay, Duration, Timer};
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -14,9 +14,11 @@ use {defmt_rtt as _, panic_probe as _};
14#[embassy_executor::main] 14#[embassy_executor::main]
15async fn main(_spawner: Spawner) -> ! { 15async fn main(_spawner: Spawner) -> ! {
16 let mut config = Config::default(); 16 let mut config = Config::default();
17 config.rcc.hse = Some(Hertz(8_000_000)); 17 config.rcc.sysclk = Some(mhz(64));
18 config.rcc.sysclk = Some(Hertz(16_000_000)); 18 config.rcc.hclk = Some(mhz(64));
19 config.rcc.adc = Some(ADCClock::PLL(ADCPrescaler::Div1)); 19 config.rcc.pclk1 = Some(mhz(32));
20 config.rcc.pclk2 = Some(mhz(64));
21 config.rcc.adc = Some(AdcClockSource::PllDiv1);
20 22
21 let mut p = embassy_stm32::init(config); 23 let mut p = embassy_stm32::init(config);
22 24
@@ -24,6 +26,8 @@ async fn main(_spawner: Spawner) -> ! {
24 26
25 let mut adc = Adc::new(p.ADC1, &mut Delay); 27 let mut adc = Adc::new(p.ADC1, &mut Delay);
26 28
29 adc.set_sample_time(SampleTime::Cycles601_5);
30
27 info!("enable vrefint..."); 31 info!("enable vrefint...");
28 32
29 let mut vrefint = adc.enable_vref(&mut Delay); 33 let mut vrefint = adc.enable_vref(&mut Delay);
diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs
index 2660b10c5..aebc421b3 100644
--- a/examples/stm32f334/src/bin/pwm.rs
+++ b/examples/stm32f334/src/bin/pwm.rs
@@ -5,6 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::hrtim::*; 7use embassy_stm32::hrtim::*;
8use embassy_stm32::rcc::HrtimClockSource;
8use embassy_stm32::time::{khz, mhz}; 9use embassy_stm32::time::{khz, mhz};
9use embassy_stm32::Config; 10use embassy_stm32::Config;
10use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
@@ -17,6 +18,7 @@ async fn main(_spawner: Spawner) {
17 config.rcc.hclk = Some(mhz(64)); 18 config.rcc.hclk = Some(mhz(64));
18 config.rcc.pclk1 = Some(mhz(32)); 19 config.rcc.pclk1 = Some(mhz(32));
19 config.rcc.pclk2 = Some(mhz(64)); 20 config.rcc.pclk2 = Some(mhz(64));
21 config.rcc.hrtim = HrtimClockSource::PllClk;
20 22
21 let p = embassy_stm32::init(config); 23 let p = embassy_stm32::init(config);
22 info!("Hello World!"); 24 info!("Hello World!");