Merge pull request #217 from lulf/stm32-rcc-improvements
Add a way to enable more features of the STM32L0 RCC
This commit is contained in:
commit
9dcf75145c
@ -10,7 +10,6 @@ use embassy::time::{Clock as EmbassyClock, TICKS_PER_SECOND};
|
|||||||
|
|
||||||
use crate::interrupt::{CriticalSection, Interrupt, Mutex};
|
use crate::interrupt::{CriticalSection, Interrupt, Mutex};
|
||||||
use crate::pac::timer::TimGp16;
|
use crate::pac::timer::TimGp16;
|
||||||
use crate::rcc::get_freqs;
|
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
|
||||||
// Clock timekeeping works with something we call "periods", which are time intervals
|
// Clock timekeeping works with something we call "periods", which are time intervals
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::peripherals::{self, RCC};
|
use crate::peripherals::{self, CRS, RCC, SYSCFG};
|
||||||
use crate::rcc::{set_freqs, Clocks};
|
use crate::rcc::{get_freqs, set_freqs, Clocks};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::time::U32Ext;
|
use crate::time::U32Ext;
|
||||||
|
use core::marker::PhantomData;
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use pac::rcc::vals;
|
use embassy_extras::unborrow;
|
||||||
use vals::{Hpre, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw};
|
use pac::dbg::vals::{DbgSleep, DbgStandby, DbgStop};
|
||||||
|
use pac::rcc::vals::{
|
||||||
|
Crypen, Dbgen, Hpre, Iophen, Lptimen, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw,
|
||||||
|
};
|
||||||
|
|
||||||
/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
|
/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
|
||||||
/// and with the addition of the init function to configure a system clock.
|
/// and with the addition of the init function to configure a system clock.
|
||||||
@ -227,56 +231,99 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// RCC peripheral
|
/// RCC peripheral
|
||||||
pub struct Rcc {}
|
pub struct Rcc<'d> {
|
||||||
|
_rb: peripherals::RCC,
|
||||||
impl Rcc {
|
phantom: PhantomData<&'d mut peripherals::RCC>,
|
||||||
pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'static) -> Self {
|
|
||||||
Self {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
impl<'d> Rcc<'d> {
|
||||||
pub fn enable_lse(&mut self, _: &PWR) -> LSE {
|
pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
|
||||||
self.rb.csr.modify(|_, w| {
|
unborrow!(rcc);
|
||||||
// Enable LSE clock
|
Self {
|
||||||
w.lseon().set_bit()
|
_rb: rcc,
|
||||||
});
|
phantom: PhantomData,
|
||||||
while self.rb.csr.read().lserdy().bit_is_clear() {}
|
}
|
||||||
LSE(())
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
impl Rcc {
|
|
||||||
pub fn enable_hsi48(&mut self, syscfg: &mut SYSCFG, crs: CRS) -> HSI48 {
|
|
||||||
// Reset CRS peripheral
|
|
||||||
self.rb.apb1rstr.modify(|_, w| w.crsrst().set_bit());
|
|
||||||
self.rb.apb1rstr.modify(|_, w| w.crsrst().clear_bit());
|
|
||||||
|
|
||||||
// Enable CRS peripheral
|
// Safety: RCC init must have been called
|
||||||
self.rb.apb1enr.modify(|_, w| w.crsen().set_bit());
|
pub fn clocks(&self) -> &'static Clocks {
|
||||||
|
unsafe { get_freqs() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub fn enable_lse(&mut self, _: &PWR) -> LSE {
|
||||||
|
self.rb.csr.modify(|_, w| {
|
||||||
|
// Enable LSE clock
|
||||||
|
w.lseon().set_bit()
|
||||||
|
});
|
||||||
|
while self.rb.csr.read().lserdy().bit_is_clear() {}
|
||||||
|
LSE(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub fn enable_debug_wfe(&mut self, _dbg: &mut peripherals::DBGMCU, enable_dma: bool) {
|
||||||
|
// NOTE(unsafe) We have exclusive access to the RCC and DBGMCU
|
||||||
|
unsafe {
|
||||||
|
if enable_dma {
|
||||||
|
pac::RCC.ahbenr().modify(|w| w.set_dmaen(Crypen::ENABLED));
|
||||||
|
}
|
||||||
|
|
||||||
|
pac::DBGMCU.cr().modify(|w| {
|
||||||
|
w.set_dbg_sleep(DbgSleep::ENABLED);
|
||||||
|
w.set_dbg_standby(DbgStandby::ENABLED);
|
||||||
|
w.set_dbg_stop(DbgStop::ENABLED);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_hsi48(&mut self, _syscfg: &mut SYSCFG, _crs: CRS) -> HSI48 {
|
||||||
|
let rcc = pac::RCC;
|
||||||
|
unsafe {
|
||||||
|
// Reset SYSCFG peripheral
|
||||||
|
rcc.apb2rstr().modify(|w| w.set_syscfgrst(true));
|
||||||
|
rcc.apb2rstr().modify(|w| w.set_syscfgrst(false));
|
||||||
|
|
||||||
|
// Enable SYSCFG peripheral
|
||||||
|
rcc.apb2enr().modify(|w| w.set_syscfgen(Dbgen::ENABLED));
|
||||||
|
|
||||||
|
// Reset CRS peripheral
|
||||||
|
rcc.apb1rstr().modify(|w| w.set_crsrst(true));
|
||||||
|
rcc.apb1rstr().modify(|w| w.set_crsrst(false));
|
||||||
|
|
||||||
|
// Enable CRS peripheral
|
||||||
|
rcc.apb1enr().modify(|w| w.set_crsen(Lptimen::ENABLED));
|
||||||
|
|
||||||
|
// Initialize CRS
|
||||||
|
let crs = pac::CRS;
|
||||||
|
crs.cfgr().write(|w|
|
||||||
|
|
||||||
// Initialize CRS
|
|
||||||
crs.cfgr.write(|w|
|
|
||||||
// Select LSE as synchronization source
|
// Select LSE as synchronization source
|
||||||
unsafe { w.syncsrc().bits(0b01) });
|
w.set_syncsrc(0b01));
|
||||||
crs.cr
|
crs.cr().modify(|w| {
|
||||||
.modify(|_, w| w.autotrimen().set_bit().cen().set_bit());
|
w.set_autotrimen(true);
|
||||||
|
w.set_cen(true);
|
||||||
|
});
|
||||||
|
|
||||||
// Enable VREFINT reference for HSI48 oscillator
|
// Enable VREFINT reference for HSI48 oscillator
|
||||||
syscfg
|
let syscfg = pac::SYSCFG;
|
||||||
.syscfg
|
syscfg.cfgr3().modify(|w| {
|
||||||
.cfgr3
|
w.set_enref_hsi48(true);
|
||||||
.modify(|_, w| w.enref_hsi48().set_bit().en_vrefint().set_bit());
|
w.set_en_vrefint(true);
|
||||||
|
});
|
||||||
|
|
||||||
// Select HSI48 as USB clock
|
// Select HSI48 as USB clock
|
||||||
self.rb.ccipr.modify(|_, w| w.hsi48msel().set_bit());
|
rcc.ccipr().modify(|w| w.set_hsi48msel(true));
|
||||||
|
|
||||||
// Enable dedicated USB clock
|
// Enable dedicated USB clock
|
||||||
self.rb.crrcr.modify(|_, w| w.hsi48on().set_bit());
|
rcc.crrcr().modify(|w| w.set_hsi48on(true));
|
||||||
while self.rb.crrcr.read().hsi48rdy().bit_is_clear() {}
|
while !rcc.crrcr().read().hsi48rdy() {}
|
||||||
|
}
|
||||||
|
|
||||||
HSI48(())
|
HSI48(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
impl Rcc {
|
impl Rcc {
|
||||||
/// Configure MCO (Microcontroller Clock Output).
|
/// Configure MCO (Microcontroller Clock Output).
|
||||||
@ -479,7 +526,7 @@ pub struct LSE(());
|
|||||||
|
|
||||||
pub unsafe fn init(config: Config) {
|
pub unsafe fn init(config: Config) {
|
||||||
let rcc = pac::RCC;
|
let rcc = pac::RCC;
|
||||||
let enabled = vals::Iophen::ENABLED;
|
let enabled = Iophen::ENABLED;
|
||||||
rcc.iopenr().write(|w| {
|
rcc.iopenr().write(|w| {
|
||||||
w.set_iopaen(enabled);
|
w.set_iopaen(enabled);
|
||||||
w.set_iopben(enabled);
|
w.set_iopben(enabled);
|
||||||
|
Loading…
Reference in New Issue
Block a user