aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-06-02 16:13:58 +0200
committerGitHub <[email protected]>2021-06-02 16:13:58 +0200
commit9dcf75145c1a25fdb51b52c7be764a8696399c09 (patch)
treeabf3189566bbeffdc0ed089187507fa65e01ce50
parent56ff8ebbd7022d04f4b6e4bd1c0372c1d9e7235e (diff)
parentc3a521066d64888475d777241ec1dd04e3578558 (diff)
Merge pull request #217 from lulf/stm32-rcc-improvements
Add a way to enable more features of the STM32L0 RCC
-rw-r--r--embassy-stm32/src/clock.rs1
-rw-r--r--embassy-stm32/src/rcc/l0/mod.rs129
2 files changed, 88 insertions, 42 deletions
diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs
index f79cab4ab..aa83c5b45 100644
--- a/embassy-stm32/src/clock.rs
+++ b/embassy-stm32/src/clock.rs
@@ -10,7 +10,6 @@ use embassy::time::{Clock as EmbassyClock, TICKS_PER_SECOND};
10 10
11use crate::interrupt::{CriticalSection, Interrupt, Mutex}; 11use crate::interrupt::{CriticalSection, Interrupt, Mutex};
12use crate::pac::timer::TimGp16; 12use crate::pac::timer::TimGp16;
13use crate::rcc::get_freqs;
14use crate::time::Hertz; 13use crate::time::Hertz;
15 14
16// Clock timekeeping works with something we call "periods", which are time intervals 15// Clock timekeeping works with something we call "periods", which are time intervals
diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs
index f911f7fbd..a8be72033 100644
--- a/embassy-stm32/src/rcc/l0/mod.rs
+++ b/embassy-stm32/src/rcc/l0/mod.rs
@@ -1,11 +1,15 @@
1use crate::pac; 1use crate::pac;
2use crate::peripherals::{self, RCC}; 2use crate::peripherals::{self, CRS, RCC, SYSCFG};
3use crate::rcc::{set_freqs, Clocks}; 3use crate::rcc::{get_freqs, set_freqs, Clocks};
4use crate::time::Hertz; 4use crate::time::Hertz;
5use crate::time::U32Ext; 5use crate::time::U32Ext;
6use core::marker::PhantomData;
6use embassy::util::Unborrow; 7use embassy::util::Unborrow;
7use pac::rcc::vals; 8use embassy_extras::unborrow;
8use vals::{Hpre, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw}; 9use pac::dbg::vals::{DbgSleep, DbgStandby, DbgStop};
10use pac::rcc::vals::{
11 Crypen, Dbgen, Hpre, Iophen, Lptimen, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw,
12};
9 13
10/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 14/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
11/// and with the addition of the init function to configure a system clock. 15/// and with the addition of the init function to configure a system clock.
@@ -227,56 +231,99 @@ impl Config {
227} 231}
228 232
229/// RCC peripheral 233/// RCC peripheral
230pub struct Rcc {} 234pub struct Rcc<'d> {
235 _rb: peripherals::RCC,
236 phantom: PhantomData<&'d mut peripherals::RCC>,
237}
231 238
232impl Rcc { 239impl<'d> Rcc<'d> {
233 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'static) -> Self { 240 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
234 Self {} 241 unborrow!(rcc);
242 Self {
243 _rb: rcc,
244 phantom: PhantomData,
245 }
235 } 246 }
236}
237 247
238/* 248 // Safety: RCC init must have been called
239 pub fn enable_lse(&mut self, _: &PWR) -> LSE { 249 pub fn clocks(&self) -> &'static Clocks {
240 self.rb.csr.modify(|_, w| { 250 unsafe { get_freqs() }
241 // Enable LSE clock
242 w.lseon().set_bit()
243 });
244 while self.rb.csr.read().lserdy().bit_is_clear() {}
245 LSE(())
246 } 251 }
247}
248impl Rcc {
249 pub fn enable_hsi48(&mut self, syscfg: &mut SYSCFG, crs: CRS) -> HSI48 {
250 // Reset CRS peripheral
251 self.rb.apb1rstr.modify(|_, w| w.crsrst().set_bit());
252 self.rb.apb1rstr.modify(|_, w| w.crsrst().clear_bit());
253 252
254 // Enable CRS peripheral 253 /*
255 self.rb.apb1enr.modify(|_, w| w.crsen().set_bit()); 254 pub fn enable_lse(&mut self, _: &PWR) -> LSE {
255 self.rb.csr.modify(|_, w| {
256 // Enable LSE clock
257 w.lseon().set_bit()
258 });
259 while self.rb.csr.read().lserdy().bit_is_clear() {}
260 LSE(())
261 }
262 }
263 */
264
265 pub fn enable_debug_wfe(&mut self, _dbg: &mut peripherals::DBGMCU, enable_dma: bool) {
266 // NOTE(unsafe) We have exclusive access to the RCC and DBGMCU
267 unsafe {
268 if enable_dma {
269 pac::RCC.ahbenr().modify(|w| w.set_dmaen(Crypen::ENABLED));
270 }
271
272 pac::DBGMCU.cr().modify(|w| {
273 w.set_dbg_sleep(DbgSleep::ENABLED);
274 w.set_dbg_standby(DbgStandby::ENABLED);
275 w.set_dbg_stop(DbgStop::ENABLED);
276 });
277 }
278 }
279
280 pub fn enable_hsi48(&mut self, _syscfg: &mut SYSCFG, _crs: CRS) -> HSI48 {
281 let rcc = pac::RCC;
282 unsafe {
283 // Reset SYSCFG peripheral
284 rcc.apb2rstr().modify(|w| w.set_syscfgrst(true));
285 rcc.apb2rstr().modify(|w| w.set_syscfgrst(false));
286
287 // Enable SYSCFG peripheral
288 rcc.apb2enr().modify(|w| w.set_syscfgen(Dbgen::ENABLED));
289
290 // Reset CRS peripheral
291 rcc.apb1rstr().modify(|w| w.set_crsrst(true));
292 rcc.apb1rstr().modify(|w| w.set_crsrst(false));
293
294 // Enable CRS peripheral
295 rcc.apb1enr().modify(|w| w.set_crsen(Lptimen::ENABLED));
296
297 // Initialize CRS
298 let crs = pac::CRS;
299 crs.cfgr().write(|w|
256 300
257 // Initialize CRS
258 crs.cfgr.write(|w|
259 // Select LSE as synchronization source 301 // Select LSE as synchronization source
260 unsafe { w.syncsrc().bits(0b01) }); 302 w.set_syncsrc(0b01));
261 crs.cr 303 crs.cr().modify(|w| {
262 .modify(|_, w| w.autotrimen().set_bit().cen().set_bit()); 304 w.set_autotrimen(true);
305 w.set_cen(true);
306 });
263 307
264 // Enable VREFINT reference for HSI48 oscillator 308 // Enable VREFINT reference for HSI48 oscillator
265 syscfg 309 let syscfg = pac::SYSCFG;
266 .syscfg 310 syscfg.cfgr3().modify(|w| {
267 .cfgr3 311 w.set_enref_hsi48(true);
268 .modify(|_, w| w.enref_hsi48().set_bit().en_vrefint().set_bit()); 312 w.set_en_vrefint(true);
313 });
269 314
270 // Select HSI48 as USB clock 315 // Select HSI48 as USB clock
271 self.rb.ccipr.modify(|_, w| w.hsi48msel().set_bit()); 316 rcc.ccipr().modify(|w| w.set_hsi48msel(true));
272 317
273 // Enable dedicated USB clock 318 // Enable dedicated USB clock
274 self.rb.crrcr.modify(|_, w| w.hsi48on().set_bit()); 319 rcc.crrcr().modify(|w| w.set_hsi48on(true));
275 while self.rb.crrcr.read().hsi48rdy().bit_is_clear() {} 320 while !rcc.crrcr().read().hsi48rdy() {}
321 }
276 322
277 HSI48(()) 323 HSI48(())
278 } 324 }
279} 325}
326/*
280 327
281impl Rcc { 328impl Rcc {
282 /// Configure MCO (Microcontroller Clock Output). 329 /// Configure MCO (Microcontroller Clock Output).
@@ -479,7 +526,7 @@ pub struct LSE(());
479 526
480pub unsafe fn init(config: Config) { 527pub unsafe fn init(config: Config) {
481 let rcc = pac::RCC; 528 let rcc = pac::RCC;
482 let enabled = vals::Iophen::ENABLED; 529 let enabled = Iophen::ENABLED;
483 rcc.iopenr().write(|w| { 530 rcc.iopenr().write(|w| {
484 w.set_iopaen(enabled); 531 w.set_iopaen(enabled);
485 w.set_iopben(enabled); 532 w.set_iopben(enabled);