diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-06-02 16:13:58 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-06-02 16:13:58 +0200 |
| commit | 9dcf75145c1a25fdb51b52c7be764a8696399c09 (patch) | |
| tree | abf3189566bbeffdc0ed089187507fa65e01ce50 | |
| parent | 56ff8ebbd7022d04f4b6e4bd1c0372c1d9e7235e (diff) | |
| parent | c3a521066d64888475d777241ec1dd04e3578558 (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.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l0/mod.rs | 129 |
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 | ||
| 11 | use crate::interrupt::{CriticalSection, Interrupt, Mutex}; | 11 | use crate::interrupt::{CriticalSection, Interrupt, Mutex}; |
| 12 | use crate::pac::timer::TimGp16; | 12 | use crate::pac::timer::TimGp16; |
| 13 | use crate::rcc::get_freqs; | ||
| 14 | use crate::time::Hertz; | 13 | use 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 @@ | |||
| 1 | use crate::pac; | 1 | use crate::pac; |
| 2 | use crate::peripherals::{self, RCC}; | 2 | use crate::peripherals::{self, CRS, RCC, SYSCFG}; |
| 3 | use crate::rcc::{set_freqs, Clocks}; | 3 | use crate::rcc::{get_freqs, set_freqs, Clocks}; |
| 4 | use crate::time::Hertz; | 4 | use crate::time::Hertz; |
| 5 | use crate::time::U32Ext; | 5 | use crate::time::U32Ext; |
| 6 | use core::marker::PhantomData; | ||
| 6 | use embassy::util::Unborrow; | 7 | use embassy::util::Unborrow; |
| 7 | use pac::rcc::vals; | 8 | use embassy_extras::unborrow; |
| 8 | use vals::{Hpre, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw}; | 9 | use pac::dbg::vals::{DbgSleep, DbgStandby, DbgStop}; |
| 10 | use 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 |
| 230 | pub struct Rcc {} | 234 | pub struct Rcc<'d> { |
| 235 | _rb: peripherals::RCC, | ||
| 236 | phantom: PhantomData<&'d mut peripherals::RCC>, | ||
| 237 | } | ||
| 231 | 238 | ||
| 232 | impl Rcc { | 239 | impl<'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 | } | ||
| 248 | impl 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 | ||
| 281 | impl Rcc { | 328 | impl Rcc { |
| 282 | /// Configure MCO (Microcontroller Clock Output). | 329 | /// Configure MCO (Microcontroller Clock Output). |
| @@ -479,7 +526,7 @@ pub struct LSE(()); | |||
| 479 | 526 | ||
| 480 | pub unsafe fn init(config: Config) { | 527 | pub 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); |
