Compare commits

...

12 Commits

72 changed files with 716 additions and 992 deletions

View File

@ -10,7 +10,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
heapless = "0.7.16"
heapless = "0.8"
defmt = { version = "0.3", optional = true }
log = { version = "0.4", default-features = false, optional = true }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }

View File

@ -15,9 +15,9 @@ embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-
embedded-hal = { version = "1.0.0-rc.1" }
embedded-hal-async = { version = "=1.0.0-rc.1" }
noproto = { git="https://github.com/embassy-rs/noproto", rev = "c90f3a78d7b5642415e0a07af401320b84d8ab6f", default-features = false, features = ["derive"] }
noproto = { git="https://github.com/embassy-rs/noproto", rev = "f5e6d1f325b6ad4e344f60452b09576e24671f62", default-features = false, features = ["derive"] }
#noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] }
heapless = "0.7.16"
heapless = "0.8"
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-esp-hosted-v$VERSION/embassy-net-esp-hosted/src/"

View File

@ -97,8 +97,8 @@ impl<'a> Control<'a> {
pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> {
let req = proto::CtrlMsgReqConnectAp {
ssid: String::from(ssid),
pwd: String::from(password),
ssid: unwrap!(String::try_from(ssid)),
pwd: unwrap!(String::try_from(password)),
bssid: String::new(),
listen_interval: 3,
is_wpa3_supported: false,

View File

@ -46,7 +46,7 @@ igmp = ["smoltcp/proto-igmp"]
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
smoltcp = { version = "0.10.0", default-features = false, features = [
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "9b791ae3057e10f7afcb70c67deb5daf714293a9", default-features = false, features = [
"socket",
"async",
] }
@ -57,10 +57,10 @@ embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embedded-io-async = { version = "0.6.0", optional = true }
managed = { version = "0.8.0", default-features = false, features = [ "map" ] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
as-slice = "0.2.1"
generic-array = { version = "0.14.4", default-features = false }
stable_deref_trait = { version = "1.2.0", default-features = false }
futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
atomic-pool = "1.0"
embedded-nal-async = { version = "0.6.0", optional = true }
embedded-nal-async = { version = "0.7", optional = true }

View File

@ -101,7 +101,8 @@ where
async fn get_host_by_address(
&self,
_addr: embedded_nal_async::IpAddr,
) -> Result<heapless::String<256>, Self::Error> {
_result: &mut [u8],
) -> Result<usize, Self::Error> {
todo!()
}
}

View File

@ -618,10 +618,7 @@ pub mod client {
async fn connect<'a>(
&'a self,
remote: embedded_nal_async::SocketAddr,
) -> Result<Self::Connection<'a>, Self::Error>
where
Self: 'a,
{
) -> Result<Self::Connection<'a>, Self::Error> {
let addr: crate::IpAddress = match remote.ip() {
#[cfg(feature = "proto-ipv4")]
IpAddr::V4(addr) => crate::IpAddress::Ipv4(crate::Ipv4Address::from_bytes(&addr.octets())),

View File

@ -21,7 +21,7 @@ embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", option
defmt = { version = "0.3", optional = true }
cortex-m = "0.7.6"
heapless = "0.7.16"
heapless = "0.8"
aligned = "0.4.1"
bit_field = "0.10.2"

View File

@ -18,7 +18,7 @@ flavors = [
{ regex_feature = "stm32f7.*", target = "thumbv7em-none-eabi" },
{ regex_feature = "stm32c0.*", target = "thumbv6m-none-eabi" },
{ regex_feature = "stm32g0.*", target = "thumbv6m-none-eabi" },
{ regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi" },
{ regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi", features = ["low-power"] },
{ regex_feature = "stm32h5.*", target = "thumbv8m.main-none-eabihf" },
{ regex_feature = "stm32h7.*", target = "thumbv7em-none-eabi" },
{ regex_feature = "stm32l0.*", target = "thumbv6m-none-eabi", features = ["low-power"] },
@ -58,7 +58,7 @@ rand_core = "0.6.3"
sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1374ed622714ef4702826699ca21cc1f741f4133" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-fbb8f77326dd066aa6c0d66b3b46e76a569dda8b" }
vcell = "0.1.3"
bxcan = "0.7.0"
nb = "1.0.0"
@ -76,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] }
[build-dependencies]
proc-macro2 = "1.0.36"
quote = "1.0.15"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1374ed622714ef4702826699ca21cc1f741f4133", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-fbb8f77326dd066aa6c0d66b3b46e76a569dda8b", default-features = false, features = ["metadata"]}
[features]

View File

@ -1,9 +1,12 @@
use crate::pac::pwr::vals::Vos;
use stm32_metapac::flash::vals::Latency;
pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp, Pllq, Pllr, Pllsrc as PllSource,
Ppre as APBPrescaler, Sw as Sysclk,
Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv,
Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk,
};
use crate::pac::{FLASH, PWR, RCC};
#[cfg(any(stm32f4, stm32f7))]
use crate::pac::PWR;
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
@ -49,11 +52,27 @@ pub struct Pll {
pub mul: PllMul,
/// PLL P division factor. If None, PLL P output is disabled.
pub divp: Option<Pllp>,
pub divp: Option<PllPDiv>,
/// PLL Q division factor. If None, PLL Q output is disabled.
pub divq: Option<Pllq>,
pub divq: Option<PllQDiv>,
/// PLL R division factor. If None, PLL R output is disabled.
pub divr: Option<Pllr>,
pub divr: Option<PllRDiv>,
}
/// Voltage range of the power supply used.
///
/// Used to calculate flash waitstates. See
/// RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock frequency
#[cfg(stm32f2)]
pub enum VoltageScale {
/// 2.7 to 3.6 V
Range0,
/// 2.4 to 2.7 V
Range1,
/// 2.1 to 2.4 V
Range2,
/// 1.8 to 2.1 V
Range3,
}
/// Configuration of the core clocks
@ -66,7 +85,7 @@ pub struct Config {
pub pll_src: PllSource,
pub pll: Option<Pll>,
#[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
pub plli2s: Option<Pll>,
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
pub pllsai: Option<Pll>,
@ -76,6 +95,9 @@ pub struct Config {
pub apb2_pre: APBPrescaler,
pub ls: super::LsConfig,
#[cfg(stm32f2)]
pub voltage: VoltageScale,
}
impl Default for Config {
@ -86,7 +108,7 @@ impl Default for Config {
sys: Sysclk::HSI,
pll_src: PllSource::HSI,
pll: None,
#[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
plli2s: None,
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
pllsai: None,
@ -96,6 +118,9 @@ impl Default for Config {
apb2_pre: APBPrescaler::DIV1,
ls: Default::default(),
#[cfg(stm32f2)]
voltage: VoltageScale::Range3,
}
}
}
@ -103,14 +128,13 @@ impl Default for Config {
pub(crate) unsafe fn init(config: Config) {
// set VOS to SCALE1, if use PLL
// TODO: check real clock speed before set VOS
#[cfg(any(stm32f4, stm32f7))]
if config.pll.is_some() {
PWR.cr1().modify(|w| w.set_vos(Vos::SCALE1));
PWR.cr1().modify(|w| w.set_vos(crate::pac::pwr::vals::Vos::SCALE1));
}
// always enable overdrive for now. Make it configurable in the future.
#[cfg(not(any(
stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f405, stm32f407, stm32f415, stm32f417
)))]
#[cfg(any(stm32f446, stm32f4x9, stm32f427, stm32f437, stm32f7))]
{
PWR.cr1().modify(|w| w.set_oden(true));
while !PWR.csr1().read().odrdy() {}
@ -158,7 +182,7 @@ pub(crate) unsafe fn init(config: Config) {
source: config.pll_src,
};
let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
#[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
let _plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input);
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
let _pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input);
@ -182,7 +206,48 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init();
flash_setup(hclk);
#[cfg(stm32f2)]
let latency = match (config.voltage, hclk.0) {
(VoltageScale::Range3, ..=16_000_000) => Latency::WS0,
(VoltageScale::Range3, ..=32_000_000) => Latency::WS1,
(VoltageScale::Range3, ..=48_000_000) => Latency::WS2,
(VoltageScale::Range3, ..=64_000_000) => Latency::WS3,
(VoltageScale::Range3, ..=80_000_000) => Latency::WS4,
(VoltageScale::Range3, ..=96_000_000) => Latency::WS5,
(VoltageScale::Range3, ..=112_000_000) => Latency::WS6,
(VoltageScale::Range3, ..=120_000_000) => Latency::WS7,
(VoltageScale::Range2, ..=18_000_000) => Latency::WS0,
(VoltageScale::Range2, ..=36_000_000) => Latency::WS1,
(VoltageScale::Range2, ..=54_000_000) => Latency::WS2,
(VoltageScale::Range2, ..=72_000_000) => Latency::WS3,
(VoltageScale::Range2, ..=90_000_000) => Latency::WS4,
(VoltageScale::Range2, ..=108_000_000) => Latency::WS5,
(VoltageScale::Range2, ..=120_000_000) => Latency::WS6,
(VoltageScale::Range1, ..=24_000_000) => Latency::WS0,
(VoltageScale::Range1, ..=48_000_000) => Latency::WS1,
(VoltageScale::Range1, ..=72_000_000) => Latency::WS2,
(VoltageScale::Range1, ..=96_000_000) => Latency::WS3,
(VoltageScale::Range1, ..=120_000_000) => Latency::WS4,
(VoltageScale::Range0, ..=30_000_000) => Latency::WS0,
(VoltageScale::Range0, ..=60_000_000) => Latency::WS1,
(VoltageScale::Range0, ..=90_000_000) => Latency::WS2,
(VoltageScale::Range0, ..=120_000_000) => Latency::WS3,
_ => unreachable!(),
};
#[cfg(any(stm32f4, stm32f7))]
let latency = {
// Be conservative with voltage ranges
const FLASH_LATENCY_STEP: u32 = 30_000_000;
let latency = (hclk.0 - 1) / FLASH_LATENCY_STEP;
debug!("flash: latency={}", latency);
Latency::from_bits(latency as u8)
};
FLASH.acr().write(|w| w.set_latency(latency));
while FLASH.acr().read().latency() != latency {}
RCC.cfgr().modify(|w| {
w.set_sw(config.sys);
@ -232,7 +297,7 @@ struct PllOutput {
#[derive(PartialEq, Eq, Clone, Copy)]
enum PllInstance {
Pll,
#[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
Plli2s,
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
Pllsai,
@ -244,7 +309,7 @@ fn pll_enable(instance: PllInstance, enabled: bool) {
RCC.cr().modify(|w| w.set_pllon(enabled));
while RCC.cr().read().pllrdy() != enabled {}
}
#[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
PllInstance::Plli2s => {
RCC.cr().modify(|w| w.set_plli2son(enabled));
while RCC.cr().read().plli2srdy() != enabled {}
@ -275,6 +340,18 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
let vco_freq = in_freq * pll.mul;
assert!(max::PLL_VCO.contains(&vco_freq));
// stm32f2 plls are like swiss cheese
#[cfg(stm32f2)]
match instance {
PllInstance::Pll => {
assert!(pll.divr.is_none());
}
PllInstance::Plli2s => {
assert!(pll.divp.is_none());
assert!(pll.divq.is_none());
}
}
let p = pll.divp.map(|div| vco_freq / div);
let q = pll.divq.map(|div| vco_freq / div);
let r = pll.divr.map(|div| vco_freq / div);
@ -288,6 +365,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
if let Some(divq) = pll.divq {
$w.set_pllq(divq);
}
#[cfg(any(stm32f4, stm32f7))]
if let Some(divr) = pll.divr {
$w.set_pllr(divr);
}
@ -304,6 +382,12 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
PllInstance::Plli2s => RCC.plli2scfgr().write(|w| {
write_fields!(w);
}),
#[cfg(stm32f2)]
PllInstance::Plli2s => RCC.plli2scfgr().write(|w| {
if let Some(divr) = pll.divr {
w.set_pllr(divr);
}
}),
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
PllInstance::Pllsai => RCC.pllsaicfgr().write(|w| {
write_fields!(w);
@ -316,22 +400,6 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
PllOutput { p, q, r }
}
fn flash_setup(clk: Hertz) {
use crate::pac::flash::vals::Latency;
// Be conservative with voltage ranges
const FLASH_LATENCY_STEP: u32 = 30_000_000;
let latency = (clk.0 - 1) / FLASH_LATENCY_STEP;
debug!("flash: latency={}", latency);
let latency = Latency::from_bits(latency as u8);
FLASH.acr().write(|w| {
w.set_latency(latency);
});
while FLASH.acr().read().latency() != latency {}
}
#[cfg(stm32f7)]
mod max {
use core::ops::RangeInclusive;
@ -380,3 +448,22 @@ mod max {
pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(2_100_000);
pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(100_000_000)..=Hertz(432_000_000);
}
#[cfg(stm32f2)]
mod max {
use core::ops::RangeInclusive;
use crate::time::Hertz;
pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(26_000_000);
pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(26_000_000);
pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(120_000_000);
pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(SYSCLK.end().0);
pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(0)..=Hertz(SYSCLK.end().0 / 4);
pub(crate) const PCLK2: RangeInclusive<Hertz> = Hertz(0)..=Hertz(SYSCLK.end().0 / 2);
pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(0_950_000)..=Hertz(2_100_000);
pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(432_000_000);
}

View File

@ -1,320 +0,0 @@
use crate::pac::flash::vals::Latency;
use crate::pac::rcc::vals::Sw;
pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Pllm as PLLPreDiv, Plln as PLLMul, Pllp as PLLPDiv, Pllq as PLLQDiv, Pllsrc as PLLSrc,
Ppre as APBPrescaler,
};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
#[derive(Clone, Copy)]
pub struct HSEConfig {
pub frequency: Hertz,
pub source: HSESrc,
}
/// System clock mux source
#[derive(Clone, Copy)]
pub enum ClockSrc {
HSE,
HSI,
PLL,
}
/// HSE clock source
#[derive(Clone, Copy)]
pub enum HSESrc {
/// Crystal/ceramic resonator
Crystal,
/// External clock source, HSE bypassed
Bypass,
}
#[derive(Clone, Copy)]
pub struct PLLConfig {
pub pre_div: PLLPreDiv,
pub mul: PLLMul,
pub p_div: PLLPDiv,
pub q_div: PLLQDiv,
}
impl Default for PLLConfig {
fn default() -> Self {
PLLConfig {
pre_div: PLLPreDiv::DIV16,
mul: PLLMul::MUL192,
p_div: PLLPDiv::DIV2,
q_div: PLLQDiv::DIV4,
}
}
}
impl PLLConfig {
pub fn clocks(&self, src_freq: Hertz) -> PLLClocks {
let in_freq = src_freq / self.pre_div;
let vco_freq = src_freq / self.pre_div * self.mul;
let main_freq = vco_freq / self.p_div;
let pll48_freq = vco_freq / self.q_div;
PLLClocks {
in_freq,
vco_freq,
main_freq,
pll48_freq,
}
}
}
#[derive(Clone, Copy, PartialEq)]
pub struct PLLClocks {
pub in_freq: Hertz,
pub vco_freq: Hertz,
pub main_freq: Hertz,
pub pll48_freq: Hertz,
}
/// Voltage range of the power supply used.
///
/// Used to calculate flash waitstates. See
/// RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock frequency
pub enum VoltageScale {
/// 2.7 to 3.6 V
Range0,
/// 2.4 to 2.7 V
Range1,
/// 2.1 to 2.4 V
Range2,
/// 1.8 to 2.1 V
Range3,
}
impl VoltageScale {
const fn wait_states(&self, ahb_freq: Hertz) -> Option<Latency> {
let ahb_freq = ahb_freq.0;
// Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock
// frequency
match self {
VoltageScale::Range3 => {
if ahb_freq <= 16_000_000 {
Some(Latency::WS0)
} else if ahb_freq <= 32_000_000 {
Some(Latency::WS1)
} else if ahb_freq <= 48_000_000 {
Some(Latency::WS2)
} else if ahb_freq <= 64_000_000 {
Some(Latency::WS3)
} else if ahb_freq <= 80_000_000 {
Some(Latency::WS4)
} else if ahb_freq <= 96_000_000 {
Some(Latency::WS5)
} else if ahb_freq <= 112_000_000 {
Some(Latency::WS6)
} else if ahb_freq <= 120_000_000 {
Some(Latency::WS7)
} else {
None
}
}
VoltageScale::Range2 => {
if ahb_freq <= 18_000_000 {
Some(Latency::WS0)
} else if ahb_freq <= 36_000_000 {
Some(Latency::WS1)
} else if ahb_freq <= 54_000_000 {
Some(Latency::WS2)
} else if ahb_freq <= 72_000_000 {
Some(Latency::WS3)
} else if ahb_freq <= 90_000_000 {
Some(Latency::WS4)
} else if ahb_freq <= 108_000_000 {
Some(Latency::WS5)
} else if ahb_freq <= 120_000_000 {
Some(Latency::WS6)
} else {
None
}
}
VoltageScale::Range1 => {
if ahb_freq <= 24_000_000 {
Some(Latency::WS0)
} else if ahb_freq <= 48_000_000 {
Some(Latency::WS1)
} else if ahb_freq <= 72_000_000 {
Some(Latency::WS2)
} else if ahb_freq <= 96_000_000 {
Some(Latency::WS3)
} else if ahb_freq <= 120_000_000 {
Some(Latency::WS4)
} else {
None
}
}
VoltageScale::Range0 => {
if ahb_freq <= 30_000_000 {
Some(Latency::WS0)
} else if ahb_freq <= 60_000_000 {
Some(Latency::WS1)
} else if ahb_freq <= 90_000_000 {
Some(Latency::WS2)
} else if ahb_freq <= 120_000_000 {
Some(Latency::WS3)
} else {
None
}
}
}
}
}
/// Clocks configuration
pub struct Config {
pub hse: Option<HSEConfig>,
pub hsi: bool,
pub pll_mux: PLLSrc,
pub pll: PLLConfig,
pub mux: ClockSrc,
pub voltage: VoltageScale,
pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
pub ls: super::LsConfig,
}
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
hse: None,
hsi: true,
pll_mux: PLLSrc::HSI,
pll: PLLConfig::default(),
voltage: VoltageScale::Range3,
mux: ClockSrc::HSI,
ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
ls: Default::default(),
}
}
}
pub(crate) unsafe fn init(config: Config) {
// Make sure HSI is enabled
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
if let Some(hse_config) = config.hse {
RCC.cr().modify(|w| {
w.set_hsebyp(match hse_config.source {
HSESrc::Bypass => true,
HSESrc::Crystal => false,
});
w.set_hseon(true)
});
while !RCC.cr().read().hserdy() {}
}
let pll_src_freq = match config.pll_mux {
PLLSrc::HSE => {
let hse_config = config
.hse
.unwrap_or_else(|| panic!("HSE must be configured to be used as PLL input"));
hse_config.frequency
}
PLLSrc::HSI => HSI_FREQ,
};
// Reference: STM32F215xx/217xx datasheet Table 33. Main PLL characteristics
let pll_clocks = config.pll.clocks(pll_src_freq);
assert!(Hertz(950_000) <= pll_clocks.in_freq && pll_clocks.in_freq <= Hertz(2_100_000));
assert!(Hertz(192_000_000) <= pll_clocks.vco_freq && pll_clocks.vco_freq <= Hertz(432_000_000));
assert!(Hertz(24_000_000) <= pll_clocks.main_freq && pll_clocks.main_freq <= Hertz(120_000_000));
// USB actually requires == 48 MHz, but other PLL48 peripherals are fine with <= 48MHz
assert!(pll_clocks.pll48_freq <= Hertz(48_000_000));
RCC.pllcfgr().write(|w| {
w.set_pllsrc(config.pll_mux);
w.set_pllm(config.pll.pre_div);
w.set_plln(config.pll.mul);
w.set_pllp(config.pll.p_div);
w.set_pllq(config.pll.q_div);
});
let (sys_clk, sw) = match config.mux {
ClockSrc::HSI => {
assert!(config.hsi, "HSI must be enabled to be used as system clock");
(HSI_FREQ, Sw::HSI)
}
ClockSrc::HSE => {
let hse_config = config
.hse
.unwrap_or_else(|| panic!("HSE must be configured to be used as PLL input"));
(hse_config.frequency, Sw::HSE)
}
ClockSrc::PLL => {
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
(pll_clocks.main_freq, Sw::PLL1_P)
}
};
// RM0033 Figure 9. Clock tree suggests max SYSCLK/HCLK is 168 MHz, but datasheet specifies PLL
// max output to be 120 MHz, so there's no way to get higher frequencies
assert!(sys_clk <= Hertz(120_000_000));
let ahb_freq = sys_clk / config.ahb_pre;
// Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
assert!(ahb_freq <= Hertz(120_000_000));
let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
pre => {
let freq = ahb_freq / pre;
(freq, Hertz(freq.0 * 2))
}
};
// Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
assert!(apb1_freq <= Hertz(30_000_000));
let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
pre => {
let freq = ahb_freq / pre;
(freq, Hertz(freq.0 * 2))
}
};
// Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
assert!(apb2_freq <= Hertz(60_000_000));
let flash_ws = unwrap!(config.voltage.wait_states(ahb_freq));
FLASH.acr().modify(|w| w.set_latency(flash_ws));
RCC.cfgr().modify(|w| {
w.set_sw(sw.into());
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {}
// Turn off HSI to save power if we don't need it
if !config.hsi {
RCC.cr().modify(|w| w.set_hsion(false));
}
let rtc = config.ls.init();
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb_freq,
hclk2: ahb_freq,
hclk3: ahb_freq,
pclk1: apb1_freq,
pclk1_tim: apb1_tim_freq,
pclk2: apb2_freq,
pclk2_tim: apb2_tim_freq,
pll1_q: Some(pll_clocks.pll48_freq),
rtc,
});
}

View File

@ -28,7 +28,7 @@ pub enum ClockSrc {
#[derive(Clone, Copy)]
pub struct PllConfig {
/// The source from which the PLL receives a clock signal
pub source: PllSrc,
pub source: PllSource,
/// The initial divisor of that clock signal
pub m: Pllm,
/// The PLL VCO multiplier, which must be in the range `8..=86`.
@ -48,7 +48,7 @@ impl Default for PllConfig {
fn default() -> PllConfig {
// HSI / 1 * 8 / 2 = 64 MHz
PllConfig {
source: PllSrc::HSI,
source: PllSource::HSI,
m: Pllm::DIV1,
n: Plln::MUL8,
r: Pllr::DIV2,
@ -59,7 +59,7 @@ impl Default for PllConfig {
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum PllSrc {
pub enum PllSource {
HSI,
HSE(Hertz),
}
@ -89,8 +89,8 @@ impl Default for Config {
impl PllConfig {
pub(crate) fn init(self) -> Hertz {
let (src, input_freq) = match self.source {
PllSrc::HSI => (vals::Pllsrc::HSI, HSI_FREQ),
PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq),
PllSource::HSI => (vals::Pllsrc::HSI, HSI_FREQ),
PllSource::HSE(freq) => (vals::Pllsrc::HSE, freq),
};
let m_freq = input_freq / self.m;
@ -121,11 +121,11 @@ impl PllConfig {
// > 3. Change the desired parameter.
// Enable whichever clock source we're using, and wait for it to become ready
match self.source {
PllSrc::HSI => {
PllSource::HSI => {
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
}
PllSrc::HSE(_) => {
PllSource::HSE(_) => {
RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
}

View File

@ -23,16 +23,16 @@ pub enum ClockSrc {
/// PLL clock input source
#[derive(Clone, Copy, Debug)]
pub enum PllSrc {
pub enum PllSource {
HSI,
HSE(Hertz),
}
impl Into<Pllsrc> for PllSrc {
impl Into<Pllsrc> for PllSource {
fn into(self) -> Pllsrc {
match self {
PllSrc::HSE(..) => Pllsrc::HSE,
PllSrc::HSI => Pllsrc::HSI,
PllSource::HSE(..) => Pllsrc::HSE,
PllSource::HSI => Pllsrc::HSI,
}
}
}
@ -44,7 +44,7 @@ impl Into<Pllsrc> for PllSrc {
/// frequency ranges for each of these settings.
pub struct Pll {
/// PLL Source clock selection.
pub source: PllSrc,
pub source: PllSource,
/// PLL pre-divider
pub prediv_m: PllM,
@ -118,13 +118,13 @@ pub struct PllFreq {
pub(crate) unsafe fn init(config: Config) {
let pll_freq = config.pll.map(|pll_config| {
let src_freq = match pll_config.source {
PllSrc::HSI => {
PllSource::HSI => {
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
HSI_FREQ
}
PllSrc::HSE(freq) => {
PllSource::HSE(freq) => {
RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
freq

View File

@ -1,12 +1,13 @@
#[cfg(any(stm32l0, stm32l1))]
pub use crate::pac::pwr::vals::Vos as VoltageScale;
use crate::pac::rcc::regs::Cfgr;
#[cfg(any(stm32l4, stm32l5, stm32wb))]
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
#[cfg(any(stm32wb, stm32wl))]
pub use crate::pac::rcc::vals::Hsepre as HsePrescaler;
pub use crate::pac::rcc::vals::{
Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul,
Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
};
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange as MSIRange, Ppre as APBPrescaler, Sw as ClockSrc};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
@ -33,25 +34,6 @@ pub struct Hse {
pub prescaler: HsePrescaler,
}
#[derive(Clone, Copy)]
pub struct Pll {
/// PLL source
pub source: PLLSource,
/// PLL pre-divider (DIVM).
pub prediv: PllPreDiv,
/// PLL multiplication factor.
pub mul: PllMul,
/// PLL P division factor. If None, PLL P output is disabled.
pub divp: Option<PllPDiv>,
/// PLL Q division factor. If None, PLL Q output is disabled.
pub divq: Option<PllQDiv>,
/// PLL R division factor. If None, PLL R output is disabled.
pub divr: Option<PllRDiv>,
}
/// Clocks configuration
pub struct Config {
// base clock sources
@ -79,13 +61,17 @@ pub struct Config {
pub shared_ahb_pre: AHBPrescaler,
// muxes
#[cfg(any(stm32l4, stm32l5, stm32wb))]
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
pub clk48_src: Clk48Src,
// low speed LSI/LSE/RTC
pub ls: super::LsConfig,
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
pub adc_clock_source: AdcClockSource,
#[cfg(any(stm32l0, stm32l1))]
pub voltage_scale: VoltageScale,
}
impl Default for Config {
@ -110,10 +96,13 @@ impl Default for Config {
pllsai2: None,
#[cfg(crs)]
hsi48: Some(Default::default()),
#[cfg(any(stm32l4, stm32l5, stm32wb))]
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
clk48_src: Clk48Src::HSI48,
ls: Default::default(),
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
adc_clock_source: AdcClockSource::SYS,
#[cfg(any(stm32l0, stm32l1))]
voltage_scale: VoltageScale::RANGE1,
}
}
}
@ -135,7 +124,7 @@ pub const WPAN_DEFAULT: Config = Config {
ls: super::LsConfig::default_lse(),
pll: Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL12,
divp: Some(PllPDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz
@ -152,20 +141,26 @@ pub const WPAN_DEFAULT: Config = Config {
adc_clock_source: AdcClockSource::SYS,
};
fn msi_enable(range: MSIRange) {
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
RCC.cr().modify(|w| {
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(range);
w.set_msipllen(false);
});
#[cfg(any(stm32l0, stm32l1))]
RCC.icscr().modify(|w| w.set_msirange(range));
RCC.cr().modify(|w| w.set_msion(true));
while !RCC.cr().read().msirdy() {}
}
pub(crate) unsafe fn init(config: Config) {
// Switch to MSI to prevent problems with PLL configuration.
if !RCC.cr().read().msion() {
// Turn on MSI and configure it to 4MHz.
RCC.cr().modify(|w| {
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(MSIRange::RANGE4M);
w.set_msipllen(false);
w.set_msion(true)
});
// Wait until MSI is running
while !RCC.cr().read().msirdy() {}
msi_enable(MSIRange::RANGE4M)
}
if RCC.cfgr().read().sws() != ClockSrc::MSI {
// Set MSI as a clock source, reset prescalers.
@ -174,6 +169,14 @@ pub(crate) unsafe fn init(config: Config) {
while RCC.cfgr().read().sws() != ClockSrc::MSI {}
}
// Set voltage scale
#[cfg(any(stm32l0, stm32l1))]
{
while crate::pac::PWR.csr().read().vosf() {}
crate::pac::PWR.cr().write(|w| w.set_vos(config.voltage_scale));
while crate::pac::PWR.csr().read().vosf() {}
}
#[cfg(stm32l5)]
crate::pac::PWR.cr1().modify(|w| {
w.set_vos(crate::pac::pwr::vals::Vos::RANGE0);
@ -182,21 +185,16 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init();
let msi = config.msi.map(|range| {
// Enable MSI
RCC.cr().modify(|w| {
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(range);
w.set_msion(true);
// If LSE is enabled, enable calibration of MSI
w.set_msipllen(config.ls.lse.is_some());
});
while !RCC.cr().read().msirdy() {}
msi_enable(range);
msirange_to_hertz(range)
});
// If LSE is enabled and the right freq, enable calibration of MSI
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
if config.ls.lse.map(|x| x.frequency) == Some(Hertz(32_768)) {
RCC.cr().modify(|w| w.set_msipllen(true));
}
let hsi = config.hsi.then(|| {
RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
@ -218,7 +216,10 @@ pub(crate) unsafe fn init(config: Config) {
});
#[cfg(crs)]
let _hsi48 = config.hsi48.map(super::init_hsi48);
let _hsi48 = config.hsi48.map(|config| {
//
super::init_hsi48(config)
});
#[cfg(not(crs))]
let _hsi48: Option<Hertz> = None;
@ -251,7 +252,12 @@ pub(crate) unsafe fn init(config: Config) {
}),
};
let pll_input = PllInput { hse, hsi, msi };
let pll_input = PllInput {
hse,
hsi,
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
msi,
};
let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
#[cfg(any(stm32l4, stm32l5, stm32wb))]
let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
@ -265,10 +271,13 @@ pub(crate) unsafe fn init(config: Config) {
ClockSrc::PLL1_R => pll.r.unwrap(),
};
#[cfg(stm32l4)]
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
#[cfg(stm32l5)]
RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src));
#[cfg(any(rcc_l0_v2))]
let _clk48 = match config.clk48_src {
Clk48Src::HSI48 => _hsi48,
Clk48Src::PLL1_VCO_DIV_2 => pll.clk48,
};
#[cfg(any(stm32l4, stm32l5, stm32wb))]
let _clk48 = match config.clk48_src {
Clk48Src::HSI48 => _hsi48,
@ -285,16 +294,23 @@ pub(crate) unsafe fn init(config: Config) {
let hclk1 = sys_clk / config.ahb_pre;
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
#[cfg(not(any(stm32wl5x, stm32wb)))]
#[cfg(any(stm32l4, stm32l5, stm32wlex))]
let hclk2 = hclk1;
#[cfg(any(stm32wl5x, stm32wb))]
let hclk2 = sys_clk / config.core2_ahb_pre;
#[cfg(not(any(stm32wl, stm32wb)))]
#[cfg(any(stm32l4, stm32l5, stm32wlex))]
let hclk3 = hclk1;
#[cfg(any(stm32wl, stm32wb))]
#[cfg(any(stm32wl5x, stm32wb))]
let hclk3 = sys_clk / config.shared_ahb_pre;
// Set flash wait states
#[cfg(any(stm32l0, stm32l1))]
let latency = match (config.voltage_scale, sys_clk.0) {
(VoltageScale::RANGE1, ..=16_000_000) => false,
(VoltageScale::RANGE2, ..=8_000_000) => false,
(VoltageScale::RANGE3, ..=4_200_000) => false,
_ => true,
};
#[cfg(stm32l4)]
let latency = match hclk1.0 {
0..=16_000_000 => 0,
@ -330,6 +346,10 @@ pub(crate) unsafe fn init(config: Config) {
_ => 4,
};
#[cfg(stm32l1)]
FLASH.acr().write(|w| w.set_acc64(true));
#[cfg(not(stm32l5))]
FLASH.acr().modify(|w| w.set_prften(true));
FLASH.acr().modify(|w| w.set_latency(latency));
while FLASH.acr().read().latency() != latency {}
@ -341,9 +361,7 @@ pub(crate) unsafe fn init(config: Config) {
});
while RCC.cfgr().read().sws() != config.mux {}
#[cfg(stm32l5)]
RCC.ccipr1().modify(|w| w.set_adcsel(config.adc_clock_source));
#[cfg(not(stm32l5))]
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
#[cfg(any(stm32wl, stm32wb))]
@ -361,7 +379,9 @@ pub(crate) unsafe fn init(config: Config) {
set_freqs(Clocks {
sys: sys_clk,
hclk1,
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
hclk2,
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
hclk3,
pclk1,
pclk2,
@ -389,6 +409,12 @@ pub(crate) unsafe fn init(config: Config) {
});
}
#[cfg(any(stm32l0, stm32l1))]
fn msirange_to_hertz(range: MSIRange) -> Hertz {
Hertz(32_768 * (1 << (range as u8 + 1)))
}
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
fn msirange_to_hertz(range: MSIRange) -> Hertz {
match range {
MSIRange::RANGE100K => Hertz(100_000),
@ -407,20 +433,6 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz {
}
}
struct PllInput {
hsi: Option<Hertz>,
hse: Option<Hertz>,
msi: Option<Hertz>,
}
#[allow(unused)]
#[derive(Default)]
struct PllOutput {
p: Option<Hertz>,
q: Option<Hertz>,
r: Option<Hertz>,
}
#[derive(PartialEq, Eq, Clone, Copy)]
enum PllInstance {
Pll,
@ -449,77 +461,182 @@ fn pll_enable(instance: PllInstance, enabled: bool) {
}
}
fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
// Disable PLL
pll_enable(instance, false);
pub use pll::*;
let Some(pll) = config else { return PllOutput::default() };
#[cfg(any(stm32l0, stm32l1))]
mod pll {
use super::{pll_enable, PllInstance};
pub use crate::pac::rcc::vals::{Plldiv as PllDiv, Pllmul as PllMul, Pllsrc as PllSource};
use crate::pac::RCC;
use crate::time::Hertz;
let pll_src = match pll.source {
PLLSource::DISABLE => panic!("must not select PLL source as DISABLE"),
PLLSource::HSE => input.hse,
PLLSource::HSI => input.hsi,
PLLSource::MSI => input.msi,
};
#[derive(Clone, Copy)]
pub struct Pll {
/// PLL source
pub source: PllSource,
let pll_src = pll_src.unwrap();
/// PLL multiplication factor.
pub mul: PllMul,
let vco_freq = pll_src / pll.prediv * pll.mul;
let p = pll.divp.map(|div| vco_freq / div);
let q = pll.divq.map(|div| vco_freq / div);
let r = pll.divr.map(|div| vco_freq / div);
#[cfg(stm32l5)]
if instance == PllInstance::Pllsai2 {
assert!(q.is_none(), "PLLSAI2_Q is not available on L5");
assert!(r.is_none(), "PLLSAI2_R is not available on L5");
/// PLL main output division factor.
pub div: PllDiv,
}
macro_rules! write_fields {
($w:ident) => {
$w.set_plln(pll.mul);
if let Some(divp) = pll.divp {
$w.set_pllp(divp);
$w.set_pllpen(true);
}
if let Some(divq) = pll.divq {
$w.set_pllq(divq);
$w.set_pllqen(true);
}
if let Some(divr) = pll.divr {
$w.set_pllr(divr);
$w.set_pllren(true);
}
pub(super) struct PllInput {
pub hsi: Option<Hertz>,
pub hse: Option<Hertz>,
}
#[allow(unused)]
#[derive(Default)]
pub(super) struct PllOutput {
pub r: Option<Hertz>,
pub clk48: Option<Hertz>,
}
pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
// Disable PLL
pll_enable(instance, false);
let Some(pll) = config else { return PllOutput::default() };
let pll_src = match pll.source {
PllSource::HSE => unwrap!(input.hse),
PllSource::HSI => unwrap!(input.hsi),
};
let vco_freq = pll_src * pll.mul;
let r = vco_freq / pll.div;
let clk48 = (vco_freq == Hertz(96_000_000)).then_some(Hertz(48_000_000));
assert!(r <= Hertz(32_000_000));
RCC.cfgr().write(move |w| {
w.set_pllmul(pll.mul);
w.set_plldiv(pll.div);
w.set_pllsrc(pll.source);
});
// Enable PLL
pll_enable(instance, true);
PllOutput { r: Some(r), clk48 }
}
}
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
mod pll {
use super::{pll_enable, PllInstance};
pub use crate::pac::rcc::vals::{
Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PllSource,
};
use crate::pac::RCC;
use crate::time::Hertz;
#[derive(Clone, Copy)]
pub struct Pll {
/// PLL source
pub source: PllSource,
/// PLL pre-divider (DIVM).
pub prediv: PllPreDiv,
/// PLL multiplication factor.
pub mul: PllMul,
/// PLL P division factor. If None, PLL P output is disabled.
pub divp: Option<PllPDiv>,
/// PLL Q division factor. If None, PLL Q output is disabled.
pub divq: Option<PllQDiv>,
/// PLL R division factor. If None, PLL R output is disabled.
pub divr: Option<PllRDiv>,
}
pub(super) struct PllInput {
pub hsi: Option<Hertz>,
pub hse: Option<Hertz>,
pub msi: Option<Hertz>,
}
#[allow(unused)]
#[derive(Default)]
pub(super) struct PllOutput {
pub p: Option<Hertz>,
pub q: Option<Hertz>,
pub r: Option<Hertz>,
}
pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
// Disable PLL
pll_enable(instance, false);
let Some(pll) = config else { return PllOutput::default() };
let pll_src = match pll.source {
PllSource::DISABLE => panic!("must not select PLL source as DISABLE"),
PllSource::HSE => unwrap!(input.hse),
PllSource::HSI => unwrap!(input.hsi),
PllSource::MSI => unwrap!(input.msi),
};
let vco_freq = pll_src / pll.prediv * pll.mul;
let p = pll.divp.map(|div| vco_freq / div);
let q = pll.divq.map(|div| vco_freq / div);
let r = pll.divr.map(|div| vco_freq / div);
#[cfg(stm32l5)]
if instance == PllInstance::Pllsai2 {
assert!(q.is_none(), "PLLSAI2_Q is not available on L5");
assert!(r.is_none(), "PLLSAI2_R is not available on L5");
}
macro_rules! write_fields {
($w:ident) => {
$w.set_plln(pll.mul);
if let Some(divp) = pll.divp {
$w.set_pllp(divp);
$w.set_pllpen(true);
}
if let Some(divq) = pll.divq {
$w.set_pllq(divq);
$w.set_pllqen(true);
}
if let Some(divr) = pll.divr {
$w.set_pllr(divr);
$w.set_pllren(true);
}
};
}
match instance {
PllInstance::Pll => RCC.pllcfgr().write(|w| {
w.set_pllm(pll.prediv);
w.set_pllsrc(pll.source);
write_fields!(w);
}),
#[cfg(any(stm32l4, stm32l5, stm32wb))]
PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
#[cfg(any(rcc_l4plus, stm32l5))]
w.set_pllm(pll.prediv);
#[cfg(stm32l5)]
w.set_pllsrc(pll.source);
write_fields!(w);
}),
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
PllInstance::Pllsai2 => RCC.pllsai2cfgr().write(|w| {
#[cfg(any(rcc_l4plus, stm32l5))]
w.set_pllm(pll.prediv);
#[cfg(stm32l5)]
w.set_pllsrc(pll.source);
write_fields!(w);
}),
}
// Enable PLL
pll_enable(instance, true);
PllOutput { p, q, r }
}
match instance {
PllInstance::Pll => RCC.pllcfgr().write(|w| {
w.set_pllm(pll.prediv);
w.set_pllsrc(pll.source);
write_fields!(w);
}),
#[cfg(any(stm32l4, stm32l5, stm32wb))]
PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
#[cfg(any(rcc_l4plus, stm32l5))]
w.set_pllm(pll.prediv);
#[cfg(stm32l5)]
w.set_pllsrc(pll.source);
write_fields!(w);
}),
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
PllInstance::Pllsai2 => RCC.pllsai2cfgr().write(|w| {
#[cfg(any(rcc_l4plus, stm32l5))]
w.set_pllm(pll.prediv);
#[cfg(stm32l5)]
w.set_pllsrc(pll.source);
write_fields!(w);
}),
}
// Enable PLL
pll_enable(instance, true);
PllOutput { p, q, r }
}

View File

@ -1,190 +0,0 @@
pub use crate::pac::pwr::vals::Vos as VoltageScale;
pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Plldiv as PllDiv, Pllmul as PLLMul, Pllmul as PllMul,
Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
};
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum HseMode {
/// crystal/ceramic oscillator (HSEBYP=0)
Oscillator,
/// external analog clock (low swing) (HSEBYP=1)
Bypass,
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Hse {
/// HSE frequency.
pub freq: Hertz,
/// HSE mode.
pub mode: HseMode,
}
#[derive(Clone, Copy)]
pub struct Pll {
/// PLL source
pub source: PLLSource,
/// PLL multiplication factor.
pub mul: PllMul,
/// PLL main output division factor.
pub div: PllDiv,
}
/// Clocks configutation
pub struct Config {
// base clock sources
pub msi: Option<MSIRange>,
pub hsi: bool,
pub hse: Option<Hse>,
#[cfg(crs)]
pub hsi48: Option<super::Hsi48Config>,
pub pll: Option<Pll>,
pub mux: ClockSrc,
pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
pub ls: super::LsConfig,
pub voltage_scale: VoltageScale,
}
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
msi: Some(MSIRange::RANGE5),
hse: None,
hsi: false,
#[cfg(crs)]
hsi48: Some(Default::default()),
pll: None,
mux: ClockSrc::MSI,
ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
voltage_scale: VoltageScale::RANGE1,
ls: Default::default(),
}
}
}
pub(crate) unsafe fn init(config: Config) {
// Set voltage scale
while PWR.csr().read().vosf() {}
PWR.cr().write(|w| w.set_vos(config.voltage_scale));
while PWR.csr().read().vosf() {}
let rtc = config.ls.init();
let msi = config.msi.map(|range| {
RCC.icscr().modify(|w| w.set_msirange(range));
RCC.cr().modify(|w| w.set_msion(true));
while !RCC.cr().read().msirdy() {}
Hertz(32_768 * (1 << (range as u8 + 1)))
});
let hsi = config.hsi.then(|| {
RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
HSI_FREQ
});
let hse = config.hse.map(|hse| {
RCC.cr().modify(|w| {
w.set_hsebyp(hse.mode == HseMode::Bypass);
w.set_hseon(true);
});
while !RCC.cr().read().hserdy() {}
hse.freq
});
let pll = config.pll.map(|pll| {
let freq = match pll.source {
PLLSource::HSE => hse.unwrap(),
PLLSource::HSI => hsi.unwrap(),
};
// Disable PLL
RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {}
let freq = freq * pll.mul / pll.div;
assert!(freq <= Hertz(32_000_000));
RCC.cfgr().write(move |w| {
w.set_pllmul(pll.mul);
w.set_plldiv(pll.div);
w.set_pllsrc(pll.source);
});
// Enable PLL
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
freq
});
let sys_clk = match config.mux {
ClockSrc::HSE => hse.unwrap(),
ClockSrc::HSI => hsi.unwrap(),
ClockSrc::MSI => msi.unwrap(),
ClockSrc::PLL1_P => pll.unwrap(),
};
let wait_states = match (config.voltage_scale, sys_clk.0) {
(VoltageScale::RANGE1, ..=16_000_000) => 0,
(VoltageScale::RANGE2, ..=8_000_000) => 0,
(VoltageScale::RANGE3, ..=4_200_000) => 0,
_ => 1,
};
#[cfg(stm32l1)]
FLASH.acr().write(|w| w.set_acc64(true));
FLASH.acr().modify(|w| w.set_prften(true));
FLASH.acr().modify(|w| w.set_latency(wait_states != 0));
RCC.cfgr().modify(|w| {
w.set_sw(config.mux);
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
let hclk1 = sys_clk / config.ahb_pre;
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
#[cfg(crs)]
let _hsi48 = config.hsi48.map(|config| {
// Select HSI48 as USB clock
RCC.ccipr().modify(|w| w.set_hsi48msel(true));
super::init_hsi48(config)
});
set_freqs(Clocks {
sys: sys_clk,
hclk1,
pclk1,
pclk2,
pclk1_tim,
pclk2_tim,
rtc,
});
}

View File

@ -15,16 +15,14 @@ mod hsi48;
pub use hsi48::*;
#[cfg_attr(rcc_f0, path = "f0.rs")]
#[cfg_attr(any(rcc_f1, rcc_f100, rcc_f1cl), path = "f1.rs")]
#[cfg_attr(rcc_f2, path = "f2.rs")]
#[cfg_attr(any(rcc_f3, rcc_f3_v2), path = "f3.rs")]
#[cfg_attr(any(rcc_f4, rcc_f410, rcc_f7), path = "f4f7.rs")]
#[cfg_attr(any(stm32f1), path = "f1.rs")]
#[cfg_attr(any(stm32f3), path = "f3.rs")]
#[cfg_attr(any(stm32f2, stm32f4, stm32f7), path = "f.rs")]
#[cfg_attr(rcc_c0, path = "c0.rs")]
#[cfg_attr(rcc_g0, path = "g0.rs")]
#[cfg_attr(rcc_g4, path = "g4.rs")]
#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")]
#[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")]
#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle, rcc_wb), path = "l4l5.rs")]
#[cfg_attr(any(stm32h5, stm32h7), path = "h.rs")]
#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl), path = "l.rs")]
#[cfg_attr(rcc_u5, path = "u5.rs")]
#[cfg_attr(rcc_wba, path = "wba.rs")]
mod _version;

View File

@ -35,7 +35,7 @@ impl Default for ClockSrc {
#[derive(Clone, Copy)]
pub struct PllConfig {
/// The clock source for the PLL.
pub source: PllSrc,
pub source: PllSource,
/// The PLL prescaler.
///
/// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz.
@ -57,7 +57,7 @@ impl PllConfig {
/// A configuration for HSI / 1 * 10 / 1 = 160 MHz
pub const fn hsi_160mhz() -> Self {
PllConfig {
source: PllSrc::HSI,
source: PllSource::HSI,
m: Pllm::DIV1,
n: Plln::MUL10,
r: Plldiv::DIV1,
@ -67,7 +67,7 @@ impl PllConfig {
/// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz
pub const fn msis_160mhz() -> Self {
PllConfig {
source: PllSrc::MSIS(Msirange::RANGE_48MHZ),
source: PllSource::MSIS(Msirange::RANGE_48MHZ),
m: Pllm::DIV3,
n: Plln::MUL10,
r: Plldiv::DIV1,
@ -76,7 +76,7 @@ impl PllConfig {
}
#[derive(Clone, Copy)]
pub enum PllSrc {
pub enum PllSource {
/// Use an internal medium speed oscillator as the PLL source.
MSIS(Msirange),
/// Use the external high speed clock as the system PLL source.
@ -88,12 +88,12 @@ pub enum PllSrc {
HSI,
}
impl Into<Pllsrc> for PllSrc {
impl Into<Pllsrc> for PllSource {
fn into(self) -> Pllsrc {
match self {
PllSrc::MSIS(..) => Pllsrc::MSIS,
PllSrc::HSE(..) => Pllsrc::HSE,
PllSrc::HSI => Pllsrc::HSI,
PllSource::MSIS(..) => Pllsrc::MSIS,
PllSource::HSE(..) => Pllsrc::HSE,
PllSource::HSI => Pllsrc::HSI,
}
}
}
@ -216,9 +216,9 @@ pub(crate) unsafe fn init(config: Config) {
ClockSrc::PLL1_R(pll) => {
// Configure the PLL source
let source_clk = match pll.source {
PllSrc::MSIS(range) => config.init_msis(range),
PllSrc::HSE(hertz) => config.init_hse(hertz),
PllSrc::HSI => config.init_hsi(),
PllSource::MSIS(range) => config.init_msis(range),
PllSource::HSE(hertz) => config.init_hse(hertz),
PllSource::HSI => config.init_hsi(),
};
// Calculate the reference clock, which is the source divided by m

View File

@ -17,16 +17,16 @@ pub enum ClockSrc {
}
#[derive(Clone, Copy, Debug)]
pub enum PllSrc {
pub enum PllSource {
HSE(Hertz),
HSI,
}
impl Into<Pllsrc> for PllSrc {
impl Into<Pllsrc> for PllSource {
fn into(self) -> Pllsrc {
match self {
PllSrc::HSE(..) => Pllsrc::HSE,
PllSrc::HSI => Pllsrc::HSI,
PllSource::HSE(..) => Pllsrc::HSE,
PllSource::HSI => Pllsrc::HSI,
}
}
}

View File

@ -33,6 +33,61 @@ use embassy_hal_internal::Peripheral;
use crate::peripherals::RTC;
use crate::rtc::sealed::Instance;
#[allow(dead_code)]
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub(crate) enum WakeupPrescaler {
Div2 = 2,
Div4 = 4,
Div8 = 8,
Div16 = 16,
}
#[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4))]
impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
fn from(val: WakeupPrescaler) -> Self {
use crate::pac::rtc::vals::Wucksel;
match val {
WakeupPrescaler::Div2 => Wucksel::DIV2,
WakeupPrescaler::Div4 => Wucksel::DIV4,
WakeupPrescaler::Div8 => Wucksel::DIV8,
WakeupPrescaler::Div16 => Wucksel::DIV16,
}
}
}
#[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4))]
impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
use crate::pac::rtc::vals::Wucksel;
match val {
Wucksel::DIV2 => WakeupPrescaler::Div2,
Wucksel::DIV4 => WakeupPrescaler::Div4,
Wucksel::DIV8 => WakeupPrescaler::Div8,
Wucksel::DIV16 => WakeupPrescaler::Div16,
_ => unreachable!(),
}
}
}
#[cfg(feature = "low-power")]
impl WakeupPrescaler {
pub fn compute_min(val: u32) -> Self {
*[
WakeupPrescaler::Div2,
WakeupPrescaler::Div4,
WakeupPrescaler::Div8,
WakeupPrescaler::Div16,
]
.iter()
.skip_while(|psc| **psc as u32 <= val)
.next()
.unwrap_or(&WakeupPrescaler::Div16)
}
}
/// Errors that can occur on methods on [RtcClock]
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq, Eq)]
@ -277,6 +332,114 @@ impl Rtc {
pub fn write_backup_register(&self, register: usize, value: u32) {
RTC::write_backup_register(&RTC::regs(), register, value)
}
#[cfg(feature = "low-power")]
/// start the wakeup alarm and wtih a duration that is as close to but less than
/// the requested duration, and record the instant the wakeup alarm was started
pub(crate) fn start_wakeup_alarm(
&self,
requested_duration: embassy_time::Duration,
cs: critical_section::CriticalSection,
) {
use embassy_time::{Duration, TICK_HZ};
#[cfg(any(rtc_v3, rtc_v3u5))]
use crate::pac::rtc::vals::Calrf;
// Panic if the rcc mod knows we're not using low-power rtc
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
unsafe { crate::rcc::get_freqs() }.rtc.unwrap();
let requested_duration = requested_duration.as_ticks().clamp(0, u32::MAX as u64);
let rtc_hz = Self::frequency().0 as u64;
let rtc_ticks = requested_duration * rtc_hz / TICK_HZ;
let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32);
// adjust the rtc ticks to the prescaler and subtract one rtc tick
let rtc_ticks = rtc_ticks / prescaler as u64;
let rtc_ticks = rtc_ticks.clamp(0, (u16::MAX - 1) as u64).saturating_sub(1) as u16;
self.write(false, |regs| {
regs.cr().modify(|w| w.set_wute(false));
#[cfg(any(
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
))]
{
regs.isr().modify(|w| w.set_wutf(false));
while !regs.isr().read().wutwf() {}
}
#[cfg(any(rtc_v3, rtc_v3u5))]
{
regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
while !regs.icsr().read().wutwf() {}
}
regs.cr().modify(|w| w.set_wucksel(prescaler.into()));
regs.wutr().write(|w| w.set_wut(rtc_ticks));
regs.cr().modify(|w| w.set_wute(true));
regs.cr().modify(|w| w.set_wutie(true));
});
let instant = self.instant().unwrap();
trace!(
"rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}",
Duration::from_ticks(rtc_ticks as u64 * TICK_HZ * prescaler as u64 / rtc_hz).as_millis(),
prescaler as u32,
rtc_ticks,
instant,
);
assert!(self.stop_time.borrow(cs).replace(Some(instant)).is_none())
}
#[cfg(feature = "low-power")]
/// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
/// was called, otherwise none
pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> {
use crate::interrupt::typelevel::Interrupt;
#[cfg(any(rtc_v3, rtc_v3u5))]
use crate::pac::rtc::vals::Calrf;
let instant = self.instant().unwrap();
if RTC::regs().cr().read().wute() {
trace!("rtc: stop wakeup alarm at {}", instant);
self.write(false, |regs| {
regs.cr().modify(|w| w.set_wutie(false));
regs.cr().modify(|w| w.set_wute(false));
#[cfg(any(
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
))]
regs.isr().modify(|w| w.set_wutf(false));
#[cfg(any(rtc_v3, rtc_v3u5))]
regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
crate::pac::EXTI
.pr(0)
.modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
<RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
});
}
self.stop_time.borrow(cs).take().map(|stop_time| instant - stop_time)
}
#[cfg(feature = "low-power")]
pub(crate) fn enable_wakeup_line(&self) {
use crate::interrupt::typelevel::Interrupt;
use crate::pac::EXTI;
<RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
unsafe { <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::enable() };
EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
}
}
pub(crate) fn byte_to_bcd2(byte: u8) -> (u8, u8) {

View File

@ -6,145 +6,7 @@ use crate::peripherals::RTC;
use crate::rtc::sealed::Instance;
#[allow(dead_code)]
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub(crate) enum WakeupPrescaler {
Div2 = 2,
Div4 = 4,
Div8 = 8,
Div16 = 16,
}
#[cfg(any(stm32wb, stm32f4, stm32l0))]
impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
fn from(val: WakeupPrescaler) -> Self {
use crate::pac::rtc::vals::Wucksel;
match val {
WakeupPrescaler::Div2 => Wucksel::DIV2,
WakeupPrescaler::Div4 => Wucksel::DIV4,
WakeupPrescaler::Div8 => Wucksel::DIV8,
WakeupPrescaler::Div16 => Wucksel::DIV16,
}
}
}
#[cfg(any(stm32wb, stm32f4, stm32l0))]
impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
use crate::pac::rtc::vals::Wucksel;
match val {
Wucksel::DIV2 => WakeupPrescaler::Div2,
Wucksel::DIV4 => WakeupPrescaler::Div4,
Wucksel::DIV8 => WakeupPrescaler::Div8,
Wucksel::DIV16 => WakeupPrescaler::Div16,
_ => unreachable!(),
}
}
}
#[allow(dead_code)]
impl WakeupPrescaler {
pub fn compute_min(val: u32) -> Self {
*[
WakeupPrescaler::Div2,
WakeupPrescaler::Div4,
WakeupPrescaler::Div8,
WakeupPrescaler::Div16,
]
.iter()
.skip_while(|psc| **psc as u32 <= val)
.next()
.unwrap_or(&WakeupPrescaler::Div16)
}
}
impl super::Rtc {
#[cfg(feature = "low-power")]
/// start the wakeup alarm and wtih a duration that is as close to but less than
/// the requested duration, and record the instant the wakeup alarm was started
pub(crate) fn start_wakeup_alarm(
&self,
requested_duration: embassy_time::Duration,
cs: critical_section::CriticalSection,
) {
use embassy_time::{Duration, TICK_HZ};
// Panic if the rcc mod knows we're not using low-power rtc
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
unsafe { crate::rcc::get_freqs() }.rtc.unwrap();
let requested_duration = requested_duration.as_ticks().clamp(0, u32::MAX as u64);
let rtc_hz = Self::frequency().0 as u64;
let rtc_ticks = requested_duration * rtc_hz / TICK_HZ;
let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32);
// adjust the rtc ticks to the prescaler and subtract one rtc tick
let rtc_ticks = rtc_ticks / prescaler as u64;
let rtc_ticks = rtc_ticks.clamp(0, (u16::MAX - 1) as u64).saturating_sub(1) as u16;
self.write(false, |regs| {
regs.cr().modify(|w| w.set_wute(false));
regs.isr().modify(|w| w.set_wutf(false));
while !regs.isr().read().wutwf() {}
regs.cr().modify(|w| w.set_wucksel(prescaler.into()));
regs.wutr().write(|w| w.set_wut(rtc_ticks));
regs.cr().modify(|w| w.set_wute(true));
regs.cr().modify(|w| w.set_wutie(true));
});
let instant = self.instant().unwrap();
trace!(
"rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}",
Duration::from_ticks(rtc_ticks as u64 * TICK_HZ * prescaler as u64 / rtc_hz).as_millis(),
prescaler as u32,
rtc_ticks,
instant,
);
assert!(self.stop_time.borrow(cs).replace(Some(instant)).is_none())
}
#[cfg(feature = "low-power")]
/// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
/// was called, otherwise none
pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> {
use crate::interrupt::typelevel::Interrupt;
let instant = self.instant().unwrap();
if RTC::regs().cr().read().wute() {
trace!("rtc: stop wakeup alarm at {}", instant);
self.write(false, |regs| {
regs.cr().modify(|w| w.set_wutie(false));
regs.cr().modify(|w| w.set_wute(false));
regs.isr().modify(|w| w.set_wutf(false));
crate::pac::EXTI
.pr(0)
.modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
<RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
});
}
self.stop_time.borrow(cs).take().map(|stop_time| instant - stop_time)
}
#[cfg(feature = "low-power")]
pub(crate) fn enable_wakeup_line(&self) {
use crate::interrupt::typelevel::Interrupt;
use crate::pac::EXTI;
<RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
unsafe { <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::enable() };
EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
}
/// Applies the RTC config
/// It this changes the RTC clock source the time will be reset
pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {

View File

@ -95,7 +95,7 @@ impl super::Rtc {
})
}
pub(super) fn write<F, R>(&mut self, init_mode: bool, f: F) -> R
pub(super) fn write<F, R>(&self, init_mode: bool, f: F) -> R
where
F: FnOnce(&crate::pac::rtc::Rtc) -> R,
{
@ -129,6 +129,12 @@ impl super::Rtc {
impl sealed::Instance for crate::peripherals::RTC {
const BACKUP_REGISTER_COUNT: usize = 32;
#[cfg(all(feature = "low-power", stm32g4))]
const EXTI_WAKEUP_LINE: usize = 20;
#[cfg(all(feature = "low-power", stm32g4))]
type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP;
fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> {
#[allow(clippy::if_same_then_else)]
if register < Self::BACKUP_REGISTER_COUNT {

View File

@ -33,7 +33,7 @@ log = { version = "0.4.14", optional = true }
futures-util = { version = "0.3.17", default-features = false }
critical-section = "1.1"
heapless = "0.7.5"
heapless = "0.8"
cfg-if = "1.0.0"
embedded-io-async = { version = "0.6.0", optional = true }

View File

@ -248,7 +248,7 @@ embedded-hal-async = { version = "=1.0.0-rc.1", optional = true}
futures-util = { version = "0.3.17", default-features = false }
critical-section = "1.1"
cfg-if = "1.0.0"
heapless = "0.7"
heapless = "0.8"
# WASM dependencies
wasm-bindgen = { version = "0.2.81", optional = true }

View File

@ -45,7 +45,7 @@ embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
heapless = "0.7.10"
heapless = "0.8"
# for HID
usbd-hid = { version = "0.6.0", optional = true }

View File

@ -39,7 +39,7 @@ st7789 = "0.6.1"
display-interface = "0.4.1"
byte-slice-cast = { version = "1.2.0", default-features = false }
smart-leds = "0.3.0"
heapless = "0.7.15"
heapless = "0.8"
usbd-hid = "0.6.1"
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }

View File

@ -14,7 +14,6 @@ embassy-net-ppp = { version = "0.1.0", path = "../../embassy-net-ppp", features
embedded-io-async = { version = "0.6.0" }
embedded-io-adapters = { version = "0.6.0", features = ["futures-03"] }
critical-section = { version = "1.1", features = ["std"] }
smoltcp = { version = "0.10.0", features = ["dns-max-server-count-4"] }
async-io = "1.6.0"
env_logger = "0.9.0"
@ -23,7 +22,7 @@ log = "0.4.14"
nix = "0.26.2"
clap = { version = "3.0.0-beta.5", features = ["derive"] }
rand_core = { version = "0.6.3", features = ["std"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
static_cell = { version = "2", features = ["nightly"]}
[profile.release]

View File

@ -19,7 +19,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
[profile.release]
debug = 2

View File

@ -21,7 +21,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
[profile.dev]

View File

@ -19,7 +19,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
[profile.release]

View File

@ -6,9 +6,6 @@ use core::convert::TryFrom;
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::rcc::{
APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLLConfig, PLLMul, PLLPDiv, PLLPreDiv, PLLQDiv, PLLSrc,
};
use embassy_stm32::time::Hertz;
use embassy_stm32::Config;
use embassy_time::Timer;
@ -19,29 +16,35 @@ async fn main(_spawner: Spawner) {
// Example config for maximum performance on a NUCLEO-F207ZG board
let mut config = Config::default();
// By default, HSE on the board comes from a 8 MHz clock signal (not a crystal)
config.rcc.hse = Some(HSEConfig {
frequency: Hertz(8_000_000),
source: HSESrc::Bypass,
});
// PLL uses HSE as the clock source
config.rcc.pll_mux = PLLSrc::HSE;
config.rcc.pll = PLLConfig {
// 8 MHz clock source / 8 = 1 MHz PLL input
pre_div: unwrap!(PLLPreDiv::try_from(8)),
// 1 MHz PLL input * 240 = 240 MHz PLL VCO
mul: unwrap!(PLLMul::try_from(240)),
// 240 MHz PLL VCO / 2 = 120 MHz main PLL output
p_div: PLLPDiv::DIV2,
// 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
q_div: PLLQDiv::DIV5,
};
// System clock comes from PLL (= the 120 MHz main PLL output)
config.rcc.mux = ClockSrc::PLL;
// 120 MHz / 4 = 30 MHz APB1 frequency
config.rcc.apb1_pre = APBPrescaler::DIV4;
// 120 MHz / 2 = 60 MHz APB2 frequency
config.rcc.apb2_pre = APBPrescaler::DIV2;
{
use embassy_stm32::rcc::*;
// By default, HSE on the board comes from a 8 MHz clock signal (not a crystal)
config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000),
mode: HseMode::Bypass,
});
// PLL uses HSE as the clock source
config.rcc.pll_src = PllSource::HSE;
config.rcc.pll = Some(Pll {
// 8 MHz clock source / 8 = 1 MHz PLL input
prediv: unwrap!(PllPreDiv::try_from(8)),
// 1 MHz PLL input * 240 = 240 MHz PLL VCO
mul: unwrap!(PllMul::try_from(240)),
// 240 MHz PLL VCO / 2 = 120 MHz main PLL output
divp: Some(PllPDiv::DIV2),
// 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
divq: Some(PllQDiv::DIV5),
divr: None,
});
// System clock comes from PLL (= the 120 MHz main PLL output)
config.rcc.sys = Sysclk::PLL1_P;
// 120 MHz / 4 = 30 MHz APB1 frequency
config.rcc.apb1_pre = APBPrescaler::DIV4;
// 120 MHz / 2 = 60 MHz APB2 frequency
config.rcc.apb2_pre = APBPrescaler::DIV2;
}
let _p = embassy_stm32::init(config);

View File

@ -21,7 +21,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
static_cell = { version = "2", features = ["nightly"]}

View File

@ -20,7 +20,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
static_cell = { version = "2", features = ["nightly"]}

View File

@ -23,7 +23,7 @@ embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.0" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
micromath = "2.0.0"

View File

@ -42,7 +42,7 @@ async fn main(spawner: Spawner) -> ! {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL180,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz.
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz.
divq: None,
divr: None,
});

View File

@ -30,8 +30,8 @@ async fn main(_spawner: Spawner) {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL168,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
divq: Some(Pllq::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
divq: Some(PllQDiv::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
divr: None,
});
config.rcc.ahb_pre = AHBPrescaler::DIV1;

View File

@ -56,8 +56,8 @@ async fn main(spawner: Spawner) {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL168,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
divq: Some(Pllq::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
divq: Some(PllQDiv::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
divr: None,
});
config.rcc.ahb_pre = AHBPrescaler::DIV1;

View File

@ -85,8 +85,8 @@ async fn main(_spawner: Spawner) {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL168,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
divq: Some(Pllq::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
divq: Some(PllQDiv::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
divr: None,
});
config.rcc.ahb_pre = AHBPrescaler::DIV1;

View File

@ -32,8 +32,8 @@ async fn main(_spawner: Spawner) {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL168,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
divq: Some(Pllq::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
divq: Some(PllQDiv::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
divr: None,
});
config.rcc.ahb_pre = AHBPrescaler::DIV1;

View File

@ -22,7 +22,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
rand_core = "0.6.3"
critical-section = "1.1"

View File

@ -43,7 +43,7 @@ async fn main(spawner: Spawner) -> ! {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL216,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
divq: None,
divr: None,
});

View File

@ -26,8 +26,8 @@ async fn main(_spawner: Spawner) {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL216,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
divq: Some(Pllq::DIV9), // 8mhz / 4 * 216 / 9 = 48Mhz
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
divq: Some(PllQDiv::DIV9), // 8mhz / 4 * 216 / 9 = 48Mhz
divr: None,
});
config.rcc.ahb_pre = AHBPrescaler::DIV1;

View File

@ -32,8 +32,8 @@ async fn main(_spawner: Spawner) {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL216,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
divq: Some(Pllq::DIV9), // 8mhz / 4 * 216 / 9 = 48Mhz
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
divq: Some(PllQDiv::DIV9), // 8mhz / 4 * 216 / 9 = 48Mhz
divr: None,
});
config.rcc.ahb_pre = AHBPrescaler::DIV1;

View File

@ -19,7 +19,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
[profile.release]

View File

@ -22,7 +22,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
[profile.release]
debug = 2

View File

@ -5,7 +5,7 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::adc::{Adc, SampleTime};
use embassy_stm32::rcc::{AdcClockSource, ClockSrc, Pll, PllM, PllN, PllR, PllSrc};
use embassy_stm32::rcc::{AdcClockSource, ClockSrc, Pll, PllM, PllN, PllR, PllSource};
use embassy_stm32::Config;
use embassy_time::{Delay, Timer};
use {defmt_rtt as _, panic_probe as _};
@ -15,7 +15,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
config.rcc.pll = Some(Pll {
source: PllSrc::HSI,
source: PllSource::HSI,
prediv_m: PllM::DIV4,
mul_n: PllN::MUL85,
div_p: None,

View File

@ -4,7 +4,7 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllR, PllSrc};
use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllR, PllSource};
use embassy_stm32::Config;
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
config.rcc.pll = Some(Pll {
source: PllSrc::HSI,
source: PllSource::HSI,
prediv_m: PllM::DIV4,
mul_n: PllN::MUL85,
div_p: None,

View File

@ -4,7 +4,7 @@
use defmt::{panic, *};
use embassy_executor::Spawner;
use embassy_stm32::rcc::{Clock48MhzSrc, ClockSrc, Hsi48Config, Pll, PllM, PllN, PllQ, PllR, PllSrc};
use embassy_stm32::rcc::{Clock48MhzSrc, ClockSrc, Hsi48Config, Pll, PllM, PllN, PllQ, PllR, PllSource};
use embassy_stm32::time::Hertz;
use embassy_stm32::usb::{self, Driver, Instance};
use embassy_stm32::{bind_interrupts, peripherals, Config};
@ -25,14 +25,14 @@ async fn main(_spawner: Spawner) {
// Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE.
const USE_HSI48: bool = true;
let pllq_div = if USE_HSI48 { None } else { Some(PllQ::DIV6) };
let plldivq = if USE_HSI48 { None } else { Some(PllQ::DIV6) };
config.rcc.pll = Some(Pll {
source: PllSrc::HSE(Hertz(8_000_000)),
source: PllSource::HSE(Hertz(8_000_000)),
prediv_m: PllM::DIV2,
mul_n: PllN::MUL72,
div_p: None,
div_q: pllq_div,
div_q: plldivq,
// Main system clock at 144 MHz
div_r: Some(PllR::DIV2),
});

View File

@ -22,10 +22,10 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }
embedded-hal-async = { version = "=1.0.0-rc.1" }
embedded-nal-async = { version = "0.6.0" }
embedded-nal-async = { version = "0.7" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"

View File

@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["
embassy-sync = { version = "0.4.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.3.1", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] }
embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
embedded-io-async = { version = "0.6.0" }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
@ -22,10 +22,10 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }
embedded-hal-async = { version = "=1.0.0-rc.1" }
embedded-nal-async = { version = "0.6.0" }
embedded-nal-async = { version = "0.7" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"

View File

@ -31,7 +31,7 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
embedded-hal = "0.2.6"
static_cell = { version = "2" }
portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }

View File

@ -18,7 +18,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
embedded-storage = "0.3.0"
[profile.release]

View File

@ -29,7 +29,7 @@ embedded-hal-async = { version = "=1.0.0-rc.1" }
embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
chrono = { version = "^0.4", default-features = false }
rand = { version = "0.8.5", default-features = false }
static_cell = { version = "2", features = ["nightly"]}

View File

@ -4,7 +4,7 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv};
use embassy_stm32::rcc::{ClockSrc, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv, PllSource};
use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
use {defmt_rtt as _, panic_probe as _};
@ -19,7 +19,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hsi = true;
config.rcc.pll = Some(Pll {
source: PLLSource::HSI,
source: PllSource::HSI,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL18,
divp: None,

View File

@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) {
mode: HseMode::Oscillator,
});
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL20,
divp: None,

View File

@ -75,7 +75,7 @@ async fn main(spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
{
use embassy_stm32::rcc::*;
// 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
// 80Mhz clock (Source: 8 / SrcDiv: 1 * PllMul 20 / ClkDiv 2)
// 80MHz highest frequency for flash 0 wait.
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hse = Some(Hse {
@ -83,7 +83,7 @@ async fn main(spawner: Spawner) {
mode: HseMode::Oscillator,
});
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL20,
divp: None,

View File

@ -27,7 +27,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hsi = true;
config.rcc.pll = Some(Pll {
source: PLLSource::HSI,
source: PllSource::HSI,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10,
divp: None,

View File

@ -23,7 +23,7 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
rand_core = { version = "0.6.3", default-features = false }
embedded-io-async = { version = "0.6.0" }
static_cell = { version = "2", features = ["nightly"]}

View File

@ -4,7 +4,7 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
use embassy_stm32::rcc::{ClockSrc, Pll, PllMul, PllPreDiv, PllRDiv, PllSource};
use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
use {defmt_rtt as _, panic_probe as _};
@ -20,7 +20,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
// 64Mhz clock (16 / 1 * 8 / 2)
source: PLLSource::HSI,
source: PllSource::HSI,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL8,
divp: None,

View File

@ -49,7 +49,7 @@ async fn main(spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
// 80Mhz clock (16 / 1 * 10 / 2)
source: PLLSource::HSI,
source: PllSource::HSI,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10,
divp: None,

View File

@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
// 80Mhz clock (16 / 1 * 10 / 2)
source: PLLSource::HSI,
source: PllSource::HSI,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10,
divp: None,

View File

@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
// 80Mhz clock (16 / 1 * 10 / 2)
source: PLLSource::HSI,
source: PllSource::HSI,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10,
divp: None,

View File

@ -20,7 +20,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
micromath = "2.0.0"

View File

@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
config.rcc.mux = ClockSrc::PLL1_R(PllConfig {
source: PllSrc::HSI,
source: PllSource::HSI,
m: Pllm::DIV2,
n: Plln::MUL10,
r: Plldiv::DIV1,

View File

@ -21,7 +21,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
static_cell = { version = "2", features = ["nightly"]}
[features]

View File

@ -19,7 +19,7 @@ cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
static_cell = { version = "2", features = ["nightly"]}
[profile.release]

View File

@ -25,7 +25,7 @@ embedded-hal = "0.2.6"
embedded-storage = "0.3.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
chrono = { version = "^0.4", default-features = false }
[profile.release]

View File

@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) {
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,

View File

@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) {
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,

View File

@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) {
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,

View File

@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) {
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,

View File

@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,

View File

@ -10,7 +10,7 @@ stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"]
stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac-adc-pin", "rng"]
stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac-adc-pin"]
stm32c031c6 = ["embassy-stm32/stm32c031c6", "cm0", "not-gpdma"]
stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "not-gpdma", "rng"]
stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng"]
stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac-adc-pin", "rng"]
stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng"]
stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng"]

View File

@ -236,24 +236,25 @@ pub fn config() -> Config {
{
use embassy_stm32::rcc::*;
// By default, HSE on the board comes from a 8 MHz clock signal (not a crystal)
config.rcc.hse = Some(HSEConfig {
frequency: Hertz(8_000_000),
source: HSESrc::Bypass,
config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000),
mode: HseMode::Bypass,
});
// PLL uses HSE as the clock source
config.rcc.pll_mux = PLLSrc::HSE;
config.rcc.pll = PLLConfig {
config.rcc.pll_src = PllSource::HSE;
config.rcc.pll = Some(Pll {
// 8 MHz clock source / 8 = 1 MHz PLL input
pre_div: unwrap!(PLLPreDiv::try_from(8)),
prediv: unwrap!(PllPreDiv::try_from(8)),
// 1 MHz PLL input * 240 = 240 MHz PLL VCO
mul: unwrap!(PLLMul::try_from(240)),
mul: unwrap!(PllMul::try_from(240)),
// 240 MHz PLL VCO / 2 = 120 MHz main PLL output
p_div: PLLPDiv::DIV2,
divp: Some(PllPDiv::DIV2),
// 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
q_div: PLLQDiv::DIV5,
};
divq: Some(PllQDiv::DIV5),
divr: None,
});
// System clock comes from PLL (= the 120 MHz main PLL output)
config.rcc.mux = ClockSrc::PLL;
config.rcc.sys = Sysclk::PLL1_P;
// 120 MHz / 4 = 30 MHz APB1 frequency
config.rcc.apb1_pre = APBPrescaler::DIV4;
// 120 MHz / 2 = 60 MHz APB2 frequency
@ -271,7 +272,7 @@ pub fn config() -> Config {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL180,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz.
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz.
divq: None,
divr: None,
});
@ -292,7 +293,7 @@ pub fn config() -> Config {
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL216,
divp: Some(Pllp::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz.
divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz.
divq: None,
divr: None,
});
@ -397,7 +398,7 @@ pub fn config() -> Config {
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hsi = true;
config.rcc.pll = Some(Pll {
source: PLLSource::HSI,
source: PllSource::HSI,
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL18,
divp: None,
@ -416,7 +417,7 @@ pub fn config() -> Config {
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,
@ -432,7 +433,7 @@ pub fn config() -> Config {
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
// 110Mhz clock (16 / 4 * 55 / 2)
source: PLLSource::HSI,
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL55,
divp: None,
@ -462,11 +463,11 @@ pub fn config() -> Config {
use embassy_stm32::rcc::*;
config.rcc.hsi = true;
config.rcc.pll = Some(Pll {
source: PLLSource::HSI,
mul: PLLMul::MUL4,
div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
source: PllSource::HSI,
mul: PllMul::MUL4,
div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
});
config.rcc.mux = ClockSrc::PLL1_P;
config.rcc.mux = ClockSrc::PLL1_R;
}
#[cfg(any(feature = "stm32l152re"))]
@ -474,11 +475,11 @@ pub fn config() -> Config {
use embassy_stm32::rcc::*;
config.rcc.hsi = true;
config.rcc.pll = Some(Pll {
source: PLLSource::HSI,
mul: PLLMul::MUL4,
div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
source: PllSource::HSI,
mul: PllMul::MUL4,
div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
});
config.rcc.mux = ClockSrc::PLL1_P;
config.rcc.mux = ClockSrc::PLL1_R;
}
config