Compare commits

...

30 Commits

Author SHA1 Message Date
8911a4d855 stm32/rcc: switch to modern api for l0, l1. 2023-11-05 03:06:13 +01:00
056c409443 Merge pull request #2140 from xoviat/low-power
stm32: compute stop mode and workaround rtt test bug
2023-11-04 18:57:44 +00:00
3f2abd4fd5 Merge branch 'main' of github.com:embassy-rs/embassy into low-power 2023-11-04 13:51:11 -05:00
dc467e89a0 stm32: compute stop mode and workaround rtt test bug 2023-11-04 13:49:54 -05:00
655ed3aa88 Merge pull request #2122 from bgamari/wip/low-power-docs
stm32: Add some documentation to `low_power`
2023-11-04 16:26:41 +00:00
14ec0d27bf Merge pull request #2138 from kalkyl/pwm-input
rp: Add PWM input example
2023-11-02 23:42:31 +00:00
649f1a122a Cleanup 2023-11-03 00:41:16 +01:00
413b394d31 rp: Add PWM input example 2023-11-03 00:37:58 +01:00
7ea2c3508a Merge pull request #2137 from kalkyl/pio-rotary-encoder
rp: Add PIO rotary encoder example
2023-11-02 21:52:01 +00:00
ec744558b2 Cleanup 2023-11-02 22:37:03 +01:00
1b9292dbcd Merge pull request #2136 from embassy-rs/static-cell-v2
Upgrade static-cell to v2.0
2023-11-02 21:00:21 +00:00
44486c5b39 rp: Add PIO rotary encoder example 2023-11-02 21:54:20 +01:00
1f51367eb9 Upgrade static-cell to v2.0 2023-11-02 21:52:07 +01:00
d6f42eafad Merge pull request #2135 from newAM/update-ehm
embedded-hal-mock: git -> 0.10.0-rc.1
2023-11-02 01:05:56 +00:00
dcce8945af embedded-hal-mock: git -> 0.10.0-rc.1 2023-11-01 16:46:15 -07:00
d98c064bfe Merge pull request #2134 from xoviat/revert-rcc
stm32/rcc: revert part of #2106
2023-11-01 22:31:43 +00:00
a904538555 stm32/rcc: revert part of #2106 2023-11-01 17:27:33 -05:00
4ef3dc5b90 Merge pull request #2099 from xoviat/rtc
stm32/rtc: misc and low-power cleanup
2023-11-01 22:19:03 +00:00
bab61f9665 stm32/rtc: misc. cleanup and move to bps by default 2023-11-01 17:17:14 -05:00
2765f0978f Merge pull request #2133 from Radiator-Labs/main
Reinstate rcc::Config adc_clock_source field
2023-11-01 20:35:03 +00:00
bc07539133 Fix missed field in cfg'd code 2023-11-01 13:30:04 -07:00
b4a82b7ed4 Correct adc_clock_source for all µprocs in l4l5.rs 2023-11-01 13:22:50 -07:00
e2688dda22 Eliminates redefinition of AdcClockSource 2023-11-01 12:06:19 -07:00
d0d8585e4c Reinstate rcc::Config adc_clock_source field 2023-11-01 11:46:17 -07:00
729d69246a Merge pull request #2131 from adamgreig/stm32-exti-high-channels
stm32: Don't try handle EXTI inputs above 16
2023-11-01 04:35:31 +00:00
e78a6db151 stm32: Don't try handle EXTI inputs above 16 2023-11-01 05:23:34 +01:00
f8721c3786 Merge pull request #2132 from embassy-rs/update-nightly
Update Rust nightly.
2023-11-01 04:10:03 +00:00
35bb20abe7 Merge pull request #2130 from andresovela/time-mock-driver-fix
time: fix MockDriver::now()
2023-10-31 23:36:56 +00:00
5f9602d28b time: fix MockDriver::now() 2023-10-31 22:48:52 +01:00
aa97fe7cbd stm32: Add some documentation to low_power
This begins to explain the operation of the low-power executor.
2023-10-30 14:36:08 -04:00
54 changed files with 485 additions and 266 deletions

2
ci.sh
View File

@ -218,8 +218,6 @@ cargo batch \
rm out/tests/stm32wb55rg/wpan_mac
rm out/tests/stm32wb55rg/wpan_ble
# unstable
rm out/tests/stm32f429zi/stop
# unstable, I think it's running out of RAM?
rm out/tests/stm32f207zg/eth

View File

@ -62,7 +62,6 @@ embassy-macros = { version = "0.2.1", path = "../embassy-macros" }
embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true}
atomic-polyfill = "1.0.1"
critical-section = "1.1"
static_cell = "1.1"
# arch-cortex-m dependencies
cortex-m = { version = "0.7.6", optional = true }

View File

@ -47,7 +47,6 @@ pub use spawner::*;
pub mod _export {
#[cfg(feature = "rtos-trace")]
pub use rtos_trace::trace;
pub use static_cell::StaticCell;
/// Expands the given block of code when `embassy-executor` is compiled with
/// the `rtos-trace-interrupt` feature.

View File

@ -53,8 +53,7 @@ pub fn wasm() -> TokenStream {
quote! {
#[wasm_bindgen::prelude::wasm_bindgen(start)]
pub fn main() -> Result<(), wasm_bindgen::JsValue> {
static EXECUTOR: ::embassy_executor::_export::StaticCell<::embassy_executor::Executor> = ::embassy_executor::_export::StaticCell::new();
let executor = EXECUTOR.init(::embassy_executor::Executor::new());
let executor = ::std::boxed::Box::leak(::std::boxed::Box::new(::embassy_executor::Executor::new()));
executor.start(|spawner| {
spawner.spawn(__embassy_main(spawner)).unwrap();

View File

@ -22,9 +22,7 @@ embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
bitfield = "0.14.0"
[dev-dependencies]
# reenable when https://github.com/dbrgn/embedded-hal-mock/pull/86 is merged.
#embedded-hal-mock = { git = "https://github.com/dbrgn/embedded-hal-mock", branch = "1-alpha", features = ["embedded-hal-async", "eh1"] }] }
embedded-hal-mock = { git = "https://github.com/newAM/embedded-hal-mock", branch = "eh1-rc.1", features = ["embedded-hal-async", "eh1"] }
embedded-hal-mock = { version = "=0.10.0-rc.1", features = ["embedded-hal-async", "eh1"] }
crc = "3.0.1"
env_logger = "0.10"
critical-section = { version = "1.1.2", features = ["std"] }

View File

@ -95,4 +95,4 @@ rp2040-boot2 = "0.3"
[dev-dependencies]
embassy-executor = { version = "0.3.1", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] }
static_cell = "1.1"
static_cell = { version = "2" }

View File

@ -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-bcc9b6bf9fa195e91625849efc4ba473d9ace4e9" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-73b8c37ae74fc28b247188c989fd99400611bd6b" }
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-bcc9b6bf9fa195e91625849efc4ba473d9ace4e9", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-73b8c37ae74fc28b247188c989fd99400611bd6b", default-features = false, features = ["metadata"]}
[features]
@ -90,6 +90,7 @@ defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-emb
exti = []
low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ]
low-power-debug-with-sleep = []
embassy-executor = []
## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/)

View File

@ -556,6 +556,32 @@ fn main() {
},
};
/*
If LP and non-LP peripherals share the same RCC enable bit, then a refcount leak will result.
This should be checked in stm32-data-gen.
*/
let stop_refcount = if p.name.starts_with("LP") {
quote! { REFCOUNT_STOP2 }
} else {
quote! { REFCOUNT_STOP1 }
};
let (incr_stop_refcount, decr_stop_refcount) = if p.name != "RTC" {
(
quote! {
#[cfg(feature = "low-power")]
unsafe { crate::rcc::#stop_refcount += 1 };
},
quote! {
#[cfg(feature = "low-power")]
unsafe { crate::rcc::#stop_refcount -= 1 };
},
)
} else {
(quote! {}, quote! {})
};
g.extend(quote! {
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
fn frequency() -> crate::time::Hertz {
@ -563,8 +589,7 @@ fn main() {
}
fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
#before_enable
#[cfg(feature = "low-power")]
unsafe { crate::rcc::REFCOUNT_STOP2 += 1 };
#incr_stop_refcount
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
#after_enable
#rst
@ -572,8 +597,7 @@ fn main() {
fn disable_with_cs(_cs: critical_section::CriticalSection) {
#before_disable
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
#[cfg(feature = "low-power")]
unsafe { crate::rcc::REFCOUNT_STOP2 -= 1 };
#decr_stop_refcount
}
}

View File

@ -47,6 +47,9 @@ pub unsafe fn on_irq() {
#[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))]
let bits = EXTI.rpr(0).read().0 | EXTI.fpr(0).read().0;
// We don't handle or change any EXTI lines above 16.
let bits = bits & 0x0000FFFF;
// Mask all the channels that fired.
cpu_regs().imr(0).modify(|w| w.0 &= !bits);

View File

@ -228,8 +228,9 @@ pub fn init(config: Config) -> Peripherals {
#[cfg(feature = "low-power")]
{
crate::rcc::REFCOUNT_STOP2 = 0
};
crate::rcc::REFCOUNT_STOP2 = 0;
crate::rcc::REFCOUNT_STOP1 = 0;
}
}
p

View File

@ -1,3 +1,50 @@
/// The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
/// to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
/// can use knowledge of which peripherals are currently blocked upon to transparently and safely
/// enter such low-power modes (currently, only `STOP2`) when idle.
///
/// The executor determines which peripherals are active by their RCC state; consequently,
/// low-power states can only be entered if all peripherals have been `drop`'d. There are a few
/// exceptions to this rule:
///
/// * `GPIO`
/// * `RCC`
///
/// Since entering and leaving low-power modes typically incurs a significant latency, the
/// low-power executor will only attempt to enter when the next timer event is at least
/// [`time_driver::MIN_STOP_PAUSE`] in the future.
///
/// Currently there is no macro analogous to `embassy_executor::main` for this executor;
/// consequently one must define their entrypoint manually. Moveover, you must relinquish control
/// of the `RTC` peripheral to the executor. This will typically look like
///
/// ```rust,no_run
/// use embassy_executor::Spawner;
/// use embassy_stm32::low_power::Executor;
/// use embassy_stm32::rtc::{Rtc, RtcConfig};
/// use static_cell::make_static;
///
/// #[cortex_m_rt::entry]
/// fn main() -> ! {
/// Executor::take().run(|spawner| {
/// unwrap!(spawner.spawn(async_main(spawner)));
/// });
/// }
///
/// #[embassy_executor::task]
/// async fn async_main(spawner: Spawner) {
/// // initialize the platform...
/// let mut config = embassy_stm32::Config::default();
/// let p = embassy_stm32::init(config);
///
/// // give the RTC to the executor...
/// let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
/// let rtc = make_static!(rtc);
/// embassy_stm32::low_power::stop_with_rtc(rtc);
///
/// // your application here...
/// }
/// ```
use core::arch::asm;
use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering};
@ -33,11 +80,17 @@ pub fn stop_with_rtc(rtc: &'static Rtc) {
}
pub fn stop_ready(stop_mode: StopMode) -> bool {
unsafe { EXECUTOR.as_mut().unwrap() }.stop_ready(stop_mode)
match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() {
Some(StopMode::Stop2) => true,
Some(StopMode::Stop1) => stop_mode == StopMode::Stop1,
None => false,
}
}
#[non_exhaustive]
#[derive(PartialEq)]
pub enum StopMode {
Stop1,
Stop2,
}
@ -61,7 +114,7 @@ pub struct Executor {
impl Executor {
/// Create a new Executor.
pub fn take() -> &'static mut Self {
unsafe {
critical_section::with(|_| unsafe {
assert!(EXECUTOR.is_none());
EXECUTOR = Some(Self {
@ -72,7 +125,7 @@ impl Executor {
});
EXECUTOR.as_mut().unwrap()
}
})
}
unsafe fn on_wakeup_irq(&mut self) {
@ -88,23 +141,39 @@ impl Executor {
trace!("low power: stop with rtc configured");
}
fn stop_ready(&self, stop_mode: StopMode) -> bool {
match stop_mode {
StopMode::Stop2 => unsafe { crate::rcc::REFCOUNT_STOP2 == 0 },
fn stop_mode(&self) -> Option<StopMode> {
if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 } && unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
Some(StopMode::Stop2)
} else if unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
Some(StopMode::Stop1)
} else {
None
}
}
fn configure_stop(&mut self, _stop_mode: StopMode) {
// TODO: configure chip-specific settings for stop
}
fn configure_pwr(&mut self) {
self.scb.clear_sleepdeep();
compiler_fence(Ordering::SeqCst);
if !self.stop_ready(StopMode::Stop2) {
let stop_mode = self.stop_mode();
if stop_mode.is_none() {
trace!("low power: not ready to stop");
} else if self.time_driver.pause_time().is_err() {
trace!("low power: failed to pause time");
} else {
trace!("low power: stop");
let stop_mode = stop_mode.unwrap();
match stop_mode {
StopMode::Stop1 => trace!("low power: stop 1"),
StopMode::Stop2 => trace!("low power: stop 2"),
}
self.configure_stop(stop_mode);
#[cfg(not(feature = "low-power-debug-with-sleep"))]
self.scb.set_sleepdeep();
}
}

View File

@ -152,9 +152,9 @@ 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(any(stm32f410, stm32f429))), stm32f7))]
#[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
let _plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input);
#[cfg(all(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7), not(stm32f429)))]
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
let _pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input);
// Configure sysclk
@ -197,25 +197,15 @@ pub(crate) unsafe fn init(config: Config) {
pclk2_tim,
rtc,
pll1_q: pll.q,
#[cfg(all(rcc_f4, not(any(stm32f410, stm32f429))))]
#[cfg(all(rcc_f4, not(stm32f410)))]
plli2s1_q: _plli2s.q,
#[cfg(all(rcc_f4, not(any(stm32f410, stm32f429))))]
#[cfg(all(rcc_f4, not(stm32f410)))]
plli2s1_r: _plli2s.r,
#[cfg(stm32f429)]
plli2s1_q: None,
#[cfg(stm32f429)]
plli2s1_r: None,
#[cfg(any(stm32f427, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pllsai1_q: _pllsai.q,
#[cfg(any(stm32f427, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pllsai1_r: _pllsai.r,
#[cfg(stm32f429)]
pllsai1_q: None,
#[cfg(stm32f429)]
pllsai1_r: None,
});
}
@ -233,7 +223,6 @@ struct PllOutput {
r: Option<Hertz>,
}
#[allow(dead_code)]
#[derive(PartialEq, Eq, Clone, Copy)]
enum PllInstance {
Pll,

View File

@ -1,8 +1,8 @@
pub use crate::pac::pwr::vals::Vos as VoltageScale;
pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler,
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::rcc::vals::{Pllsrc, Sw};
#[cfg(crs)]
use crate::pac::{crs, CRS, SYSCFG};
use crate::pac::{FLASH, PWR, RCC};
@ -12,39 +12,50 @@ use crate::time::Hertz;
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
/// System clock mux source
#[derive(Clone, Copy)]
pub enum ClockSrc {
MSI(MSIRange),
PLL(PLLSource, PLLMul, PLLDiv),
HSE(Hertz),
HSI,
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum HseMode {
/// crystal/ceramic oscillator (HSEBYP=0)
Oscillator,
/// external analog clock (low swing) (HSEBYP=1)
Bypass,
}
/// PLL clock input source
#[derive(Clone, Copy)]
pub enum PLLSource {
HSI,
HSE(Hertz),
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Hse {
/// HSE frequency.
pub freq: Hertz,
/// HSE mode.
pub mode: HseMode,
}
impl From<PLLSource> for Pllsrc {
fn from(val: PLLSource) -> Pllsrc {
match val {
PLLSource::HSI => Pllsrc::HSI,
PLLSource::HSE(_) => Pllsrc::HSE,
}
}
#[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: bool,
pub pll: Option<Pll>,
pub mux: ClockSrc,
pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
#[cfg(crs)]
pub enable_hsi48: bool,
pub ls: super::LsConfig,
pub voltage_scale: VoltageScale,
}
@ -53,12 +64,18 @@ impl Default for Config {
#[inline]
fn default() -> Config {
Config {
mux: ClockSrc::MSI(MSIRange::RANGE5),
msi: Some(MSIRange::RANGE5),
hse: None,
hsi: false,
#[cfg(crs)]
hsi48: false,
pll: None,
mux: ClockSrc::MSI,
ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
#[cfg(crs)]
enable_hsi48: false,
voltage_scale: VoltageScale::RANGE1,
ls: Default::default(),
}
@ -71,72 +88,68 @@ pub(crate) unsafe fn init(config: Config) {
PWR.cr().write(|w| w.set_vos(config.voltage_scale));
while PWR.csr().read().vosf() {}
let (sys_clk, sw) = match config.mux {
ClockSrc::MSI(range) => {
// Set MSI range
RCC.icscr().write(|w| w.set_msirange(range));
// Enable MSI
RCC.cr().write(|w| w.set_msion(true));
while !RCC.cr().read().msirdy() {}
let freq = 32_768 * (1 << (range as u8 + 1));
(Hertz(freq), Sw::MSI)
}
ClockSrc::HSI => {
// Enable HSI
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
(HSI_FREQ, Sw::HSI)
}
ClockSrc::HSE(freq) => {
// Enable HSE
RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
(freq, Sw::HSE)
}
ClockSrc::PLL(src, mul, div) => {
let freq = match src {
PLLSource::HSE(freq) => {
// Enable HSE
RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
freq
}
PLLSource::HSI => {
// Enable HSI
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
HSI_FREQ
}
};
// Disable PLL
RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {}
let freq = freq * mul / div;
assert!(freq <= Hertz(32_000_000));
RCC.cfgr().write(move |w| {
w.set_pllmul(mul);
w.set_plldiv(div);
w.set_pllsrc(src.into());
});
// Enable PLL
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
(freq, Sw::PLL1_P)
}
};
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,
@ -150,7 +163,7 @@ pub(crate) unsafe fn init(config: Config) {
FLASH.acr().modify(|w| w.set_latency(wait_states != 0));
RCC.cfgr().modify(|w| {
w.set_sw(sw);
w.set_sw(config.mux);
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
@ -161,7 +174,7 @@ pub(crate) unsafe fn init(config: Config) {
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
#[cfg(crs)]
if config.enable_hsi48 {
if config.hsi48 {
// Reset CRS peripheral
RCC.apb1rstr().modify(|w| w.set_crsrst(true));
RCC.apb1rstr().modify(|w| w.set_crsrst(false));

View File

@ -4,8 +4,8 @@ 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::{
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,
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,
};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
@ -52,7 +52,7 @@ pub struct Pll {
pub divr: Option<PllRDiv>,
}
/// Clocks configutation
/// Clocks configuration
pub struct Config {
// base clock sources
pub msi: Option<MSIRange>,
@ -84,6 +84,8 @@ pub struct Config {
// low speed LSI/LSE/RTC
pub ls: super::LsConfig,
pub adc_clock_source: AdcClockSource,
}
impl Default for Config {
@ -111,6 +113,7 @@ impl Default for Config {
#[cfg(any(stm32l4, stm32l5, stm32wb))]
clk48_src: Clk48Src::HSI48,
ls: Default::default(),
adc_clock_source: AdcClockSource::SYS,
}
}
}
@ -145,6 +148,7 @@ pub const WPAN_DEFAULT: Config = Config {
shared_ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
adc_clock_source: AdcClockSource::SYS,
};
pub(crate) unsafe fn init(config: Config) {
@ -189,9 +193,6 @@ pub(crate) unsafe fn init(config: Config) {
});
while !RCC.cr().read().msirdy() {}
// Enable as clock source for USB, RNG if running at 48 MHz
if range == MSIRange::RANGE48M {}
msirange_to_hertz(range)
});
@ -344,6 +345,11 @@ 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))]
RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
#[cfg(any(stm32wl, stm32wb))]
{
RCC.extcfgr().modify(|w| {

View File

@ -181,6 +181,15 @@ pub struct Clocks {
}
#[cfg(feature = "low-power")]
/// Must be written within a critical section
///
/// May be read without a critical section
pub(crate) static mut REFCOUNT_STOP1: u32 = 0;
#[cfg(feature = "low-power")]
/// Must be written within a critical section
///
/// May be read without a critical section
pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
/// Frozen clock frequencies

View File

@ -18,9 +18,13 @@ pub struct RtcInstant {
}
impl RtcInstant {
#[allow(dead_code)]
pub(super) fn from(second: u8, subsecond: u16) -> Result<Self, super::RtcError> {
Ok(Self { second, subsecond })
#[cfg(not(rtc_v2f2))]
pub(super) const fn from(second: u8, subsecond: u16) -> Result<Self, Error> {
if second > 59 {
Err(Error::InvalidSecond)
} else {
Ok(Self { second, subsecond })
}
}
}
@ -226,7 +230,7 @@ impl From<DayOfWeek> for chrono::Weekday {
}
}
fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> {
pub(super) const fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> {
Ok(match v {
1 => DayOfWeek::Monday,
2 => DayOfWeek::Tuesday,
@ -239,24 +243,6 @@ fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> {
})
}
pub(super) fn day_of_week_to_u8(dotw: DayOfWeek) -> u8 {
pub(super) const fn day_of_week_to_u8(dotw: DayOfWeek) -> u8 {
dotw as u8
}
pub(super) fn validate_datetime(dt: &DateTime) -> Result<(), Error> {
if dt.year > 4095 {
Err(Error::InvalidYear)
} else if dt.month < 1 || dt.month > 12 {
Err(Error::InvalidMonth)
} else if dt.day < 1 || dt.day > 31 {
Err(Error::InvalidDay)
} else if dt.hour > 23 {
Err(Error::InvalidHour)
} else if dt.minute > 59 {
Err(Error::InvalidMinute)
} else if dt.second > 59 {
Err(Error::InvalidSecond)
} else {
Ok(())
}
}

View File

@ -9,8 +9,11 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
#[cfg(feature = "low-power")]
use embassy_sync::blocking_mutex::Mutex;
pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError, RtcInstant};
use crate::rtc::datetime::day_of_week_to_u8;
use self::datetime::day_of_week_to_u8;
#[cfg(not(rtc_v2f2))]
use self::datetime::RtcInstant;
pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
use crate::pac::rtc::regs::{Dr, Tr};
use crate::time::Hertz;
/// refer to AN4759 to compare features of RTC2 and RTC3
@ -31,11 +34,15 @@ use crate::peripherals::RTC;
use crate::rtc::sealed::Instance;
/// Errors that can occur on methods on [RtcClock]
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RtcError {
/// An invalid DateTime was given or stored on the hardware.
InvalidDateTime(DateTimeError),
/// The current time could not be read
ReadFailure,
/// The RTC clock is not running
NotRunning,
}
@ -45,48 +52,25 @@ pub struct RtcTimeProvider {
}
impl RtcTimeProvider {
#[cfg(not(rtc_v2f2))]
pub(crate) fn instant(&self) -> Result<RtcInstant, RtcError> {
self.read(|_, tr, ss| {
let second = bcd2_to_byte((tr.st(), tr.su()));
RtcInstant::from(second, ss).map_err(RtcError::InvalidDateTime)
})
}
/// Return the current datetime.
///
/// # Errors
///
/// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
pub fn now(&self) -> Result<DateTime, RtcError> {
// For RM0433 we use BYPSHAD=1 to work around errata ES0392 2.19.1
#[cfg(rcc_h7rm0433)]
loop {
let r = RTC::regs();
let ss = r.ssr().read().ss();
let dr = r.dr().read();
let tr = r.tr().read();
// If an RTCCLK edge occurs during read we may see inconsistent values
// so read ssr again and see if it has changed. (see RM0433 Rev 7 46.3.9)
let ss_after = r.ssr().read().ss();
if ss == ss_after {
let second = bcd2_to_byte((tr.st(), tr.su()));
let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
let hour = bcd2_to_byte((tr.ht(), tr.hu()));
let weekday = dr.wdu();
let day = bcd2_to_byte((dr.dt(), dr.du()));
let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
return DateTime::from(year, month, day, weekday, hour, minute, second)
.map_err(RtcError::InvalidDateTime);
}
}
#[cfg(not(rcc_h7rm0433))]
{
let r = RTC::regs();
let tr = r.tr().read();
self.read(|dr, tr, _| {
let second = bcd2_to_byte((tr.st(), tr.su()));
let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
let hour = bcd2_to_byte((tr.ht(), tr.hu()));
// Reading either RTC_SSR or RTC_TR locks the values in the higher-order
// calendar shadow registers until RTC_DR is read.
let dr = r.dr().read();
let weekday = dr.wdu();
let day = bcd2_to_byte((dr.dt(), dr.du()));
@ -94,7 +78,33 @@ impl RtcTimeProvider {
let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
})
}
fn read<R>(&self, mut f: impl FnMut(Dr, Tr, u16) -> Result<R, RtcError>) -> Result<R, RtcError> {
let r = RTC::regs();
#[cfg(not(rtc_v2f2))]
let read_ss = || r.ssr().read().ss();
#[cfg(rtc_v2f2)]
let read_ss = || 0;
let mut ss = read_ss();
for _ in 0..5 {
let tr = r.tr().read();
let dr = r.dr().read();
let ss_after = read_ss();
// If an RTCCLK edge occurs during read we may see inconsistent values
// so read ssr again and see if it has changed. (see RM0433 Rev 7 46.3.9)
if ss == ss_after {
return f(dr, tr, ss.try_into().unwrap());
} else {
ss = ss_after
}
}
return Err(RtcError::ReadFailure);
}
}
@ -143,13 +153,7 @@ impl Default for RtcCalibrationCyclePeriod {
impl Rtc {
pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
#[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
critical_section::with(|cs| {
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs);
#[cfg(feature = "low-power")]
unsafe {
crate::rcc::REFCOUNT_STOP2 -= 1
};
});
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
let mut this = Self {
#[cfg(feature = "low-power")]
@ -164,6 +168,14 @@ impl Rtc {
this.configure(async_psc, sync_psc);
// Wait for the clock to update after initialization
#[cfg(not(rtc_v2f2))]
{
let now = this.instant().unwrap();
while this.instant().unwrap().subsecond == now.subsecond {}
}
this
}
@ -183,7 +195,6 @@ impl Rtc {
///
/// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range.
pub fn set_datetime(&mut self, t: DateTime) -> Result<(), RtcError> {
self::datetime::validate_datetime(&t).map_err(RtcError::InvalidDateTime)?;
self.write(true, |rtc| {
let (ht, hu) = byte_to_bcd2(t.hour() as u8);
let (mnt, mnu) = byte_to_bcd2(t.minute() as u8);
@ -223,16 +234,8 @@ impl Rtc {
#[cfg(not(rtc_v2f2))]
/// Return the current instant.
pub fn instant(&self) -> Result<RtcInstant, RtcError> {
let r = RTC::regs();
let tr = r.tr().read();
let subsecond = r.ssr().read().ss();
let second = bcd2_to_byte((tr.st(), tr.su()));
// Unlock the registers
r.dr().read();
RtcInstant::from(second, subsecond.try_into().unwrap())
fn instant(&self) -> Result<RtcInstant, RtcError> {
self.time_provider().instant()
}
/// Return the current datetime.

View File

@ -150,14 +150,14 @@ impl super::Rtc {
pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
self.write(true, |rtc| {
rtc.cr().modify(|w| {
#[cfg(not(rtc_v2f2))]
w.set_bypshad(true);
#[cfg(rtc_v2f2)]
w.set_fmt(false);
#[cfg(not(rtc_v2f2))]
w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR);
w.set_osel(Osel::DISABLED);
w.set_pol(Pol::HIGH);
#[cfg(rcc_h7rm0433)]
w.set_bypshad(true);
});
rtc.prer().modify(|w| {

View File

@ -11,6 +11,7 @@ impl super::Rtc {
pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
self.write(true, |rtc| {
rtc.cr().modify(|w| {
w.set_bypshad(true);
w.set_fmt(Fmt::TWENTYFOURHOUR);
w.set_osel(Osel::DISABLED);
w.set_pol(Pol::HIGH);

View File

@ -345,6 +345,10 @@ impl RtcDriver {
});
}
#[cfg(feature = "low-power")]
/// The minimum pause time beyond which the executor will enter a low-power state.
pub(crate) const MIN_STOP_PAUSE: embassy_time::Duration = embassy_time::Duration::from_millis(250);
#[cfg(feature = "low-power")]
/// Pause the timer if ready; return err if not
pub(crate) fn pause_time(&self) -> Result<(), ()> {
@ -357,7 +361,7 @@ impl RtcDriver {
self.stop_wakeup_alarm(cs);
let time_until_next_alarm = self.time_until_next_alarm(cs);
if time_until_next_alarm < embassy_time::Duration::from_millis(250) {
if time_until_next_alarm < Self::MIN_STOP_PAUSE {
Err(())
} else {
self.rtc

View File

@ -45,4 +45,4 @@ futures-util = { version = "0.3.17", features = [ "channel" ] }
# Enable critical-section implementation for std, for tests
critical-section = { version = "1.1", features = ["std"] }
static_cell = "1.1"
static_cell = { version = "2" }

View File

@ -51,7 +51,7 @@ impl MockDriver {
impl Driver for MockDriver {
fn now(&self) -> u64 {
critical_section::with(|cs| self.now.borrow(cs).get().as_micros() as u64)
critical_section::with(|cs| self.now.borrow(cs).get().as_ticks() as u64)
}
unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {

View File

@ -13,6 +13,6 @@ embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
futures = { version = "0.3", default-features = false }
static_cell = "1"
static_cell = { version = "2" }
usbd-hid = "0.6.0"
log = "0.4"

View File

@ -48,7 +48,7 @@ defmt = "0.3"
defmt-rtt = "0.4"
fixed = "1.10.0"
static_cell = "1.1"
static_cell = { version = "2" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }

View File

@ -42,7 +42,7 @@ embedded-io-async = { version = "0.6.0" }
defmt = "0.3"
defmt-rtt = "0.4"
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }

View File

@ -47,7 +47,8 @@ embedded-hal-async = "1.0.0-rc.1"
embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] }
embedded-io-async = { version = "0.6.0", features = ["defmt-03"] }
embedded-storage = { version = "0.3" }
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
portable-atomic = { version = "1.5", features = ["critical-section"] }
log = "0.4"
pio-proc = "0.2"
pio = "0.2.1"

View File

@ -0,0 +1,81 @@
//! This example shows how to use the PIO module in the RP2040 to read a quadrature rotary encoder.
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use defmt::info;
use embassy_executor::Spawner;
use embassy_rp::gpio::Pull;
use embassy_rp::peripherals::PIO0;
use embassy_rp::{bind_interrupts, pio};
use fixed::traits::ToFixed;
use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine};
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
pub struct PioEncoder<'d, T: Instance, const SM: usize> {
sm: StateMachine<'d, T, SM>,
}
impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> {
pub fn new(
pio: &mut Common<'d, T>,
mut sm: StateMachine<'d, T, SM>,
pin_a: impl PioPin,
pin_b: impl PioPin,
) -> Self {
let mut pin_a = pio.make_pio_pin(pin_a);
let mut pin_b = pio.make_pio_pin(pin_b);
pin_a.set_pull(Pull::Up);
pin_b.set_pull(Pull::Up);
sm.set_pin_dirs(pio::Direction::In, &[&pin_a, &pin_b]);
let prg = pio_proc::pio_asm!("wait 1 pin 1", "wait 0 pin 1", "in pins, 2", "push",);
let mut cfg = Config::default();
cfg.set_in_pins(&[&pin_a, &pin_b]);
cfg.fifo_join = FifoJoin::RxOnly;
cfg.shift_in.direction = ShiftDirection::Left;
cfg.clock_divider = 10_000.to_fixed();
cfg.use_program(&pio.load_program(&prg.program), &[]);
sm.set_config(&cfg);
sm.set_enable(true);
Self { sm }
}
pub async fn read(&mut self) -> Direction {
loop {
match self.sm.rx().wait_pull().await {
0 => return Direction::CounterClockwise,
1 => return Direction::Clockwise,
_ => {}
}
}
}
}
pub enum Direction {
Clockwise,
CounterClockwise,
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs);
let mut encoder = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5);
let mut count = 0;
loop {
info!("Count: {}", count);
count += match encoder.read().await {
Direction::Clockwise => 1,
Direction::CounterClockwise => -1,
};
}
}

View File

@ -0,0 +1,26 @@
//! This example shows how to use the PWM module to measure the frequency of an input signal.
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use defmt::*;
use embassy_executor::Spawner;
use embassy_rp::pwm::{Config, InputMode, Pwm};
use embassy_time::{Duration, Ticker};
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let cfg: Config = Default::default();
let pwm = Pwm::new_input(p.PWM_CH2, p.PIN_5, InputMode::RisingEdge, cfg);
let mut ticker = Ticker::every(Duration::from_secs(1));
loop {
info!("Input frequency: {} Hz", pwm.counter());
pwm.set_counter(0);
ticker.next().await;
}
}

View File

@ -24,7 +24,7 @@ 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 }
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
[profile.release]
debug = 2

View File

@ -17,7 +17,8 @@ panic-probe = "0.3"
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", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
[profile.release]
debug = 2

View File

@ -24,7 +24,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
heapless = { version = "0.7.5", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
[profile.release]
debug = 2

View File

@ -23,4 +23,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
heapless = { version = "0.7.5", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}

View File

@ -27,7 +27,7 @@ heapless = { version = "0.7.5", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
micromath = "2.0.0"
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
chrono = { version = "^0.4", default-features = false}
[profile.release]

View File

@ -27,7 +27,7 @@ nb = "1.0.0"
rand_core = "0.6.3"
critical-section = "1.1"
embedded-storage = "0.3.0"
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
[profile.release]
debug = 2

View File

@ -20,6 +20,7 @@ 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 }
portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
[profile.release]
debug = 2

View File

@ -31,7 +31,7 @@ critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.0"
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
# cargo build/run
[profile.dev]

View File

@ -31,7 +31,7 @@ critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.0"
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
chrono = { version = "^0.4", default-features = false }
# cargo build/run

View File

@ -33,7 +33,8 @@ 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 }
embedded-hal = "0.2.6"
static_cell = "1.1"
static_cell = { version = "2" }
portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
[profile.release]
debug = 2

View File

@ -12,7 +12,7 @@ use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut config = Config::default();
config.rcc.enable_hsi48 = true;
config.rcc.hsi48 = true;
let p = embassy_stm32::init(config);
let button = Input::new(p.PB2, Pull::Up);

View File

@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
config.rcc.enable_hsi48 = true;
config.rcc.hsi48 = true;
let p = embassy_stm32::init(config);
let mut spi_config = spi::Config::default();

View File

@ -34,7 +34,7 @@ const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set th
async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
config.rcc.enable_hsi48 = true;
config.rcc.hsi48 = true;
let p = embassy_stm32::init(config);
let mut spi_config = spi::Config::default();

View File

@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
config.rcc.enable_hsi48 = true;
config.rcc.hsi48 = true;
let p = embassy_stm32::init(config);
let mut spi_config = spi::Config::default();

View File

@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
config.rcc.enable_hsi48 = true;
config.rcc.hsi48 = true;
let p = embassy_stm32::init(config);
let mut spi_config = spi::Config::default();

View File

@ -32,7 +32,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
heapless = { version = "0.7.5", default-features = false }
chrono = { version = "^0.4", default-features = false }
rand = { version = "0.8.5", default-features = false }
static_cell = {version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
micromath = "2.0.0"

View File

@ -26,7 +26,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
heapless = { version = "0.7.5", default-features = false }
rand_core = { version = "0.6.3", default-features = false }
embedded-io-async = { version = "0.6.0" }
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
[profile.release]
debug = 2

View File

@ -22,7 +22,7 @@ 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 }
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
[features]
default = ["ble", "mac"]

View File

@ -20,7 +20,7 @@ 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 }
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
[profile.release]
debug = 2

View File

@ -18,7 +18,7 @@ embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-host
embassy-net-enc28j60 = { version = "0.1.0", path = "../../embassy-net-enc28j60", features = ["defmt"] }
embedded-hal-async = { version = "1.0.0-rc.1" }
embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] }
static_cell = { version = "1.1", features = [ "nightly" ] }
static_cell = { version = "2", features = [ "nightly" ] }
perf-client = { path = "../perf-client" }
defmt = "0.3"

View File

@ -31,7 +31,8 @@ panic-probe = { version = "0.3.0", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
embedded-io-async = { version = "0.6.0" }
embedded-storage = { version = "0.3" }
static_cell = { version = "1.1", features = ["nightly"]}
static_cell = { version = "2", features = ["nightly"]}
portable-atomic = { version = "1.5", features = ["critical-section"] }
pio = "0.2"
pio-proc = "0.2"
rand = { version = "0.8.5", default-features = false }

View File

@ -5,12 +5,12 @@ teleprobe_meta::target!(b"rpi-pico");
use defmt::{info, unwrap};
use embassy_executor::Executor;
use embassy_executor::_export::StaticCell;
use embassy_rp::gpio::{Input, Level, Output, Pull};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals::{PIN_0, PIN_1};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _};
static mut CORE1_STACK: Stack<1024> = Stack::new();

View File

@ -5,12 +5,12 @@ teleprobe_meta::target!(b"rpi-pico");
use defmt::{assert_eq, info, panic, unwrap};
use embassy_executor::Executor;
use embassy_executor::_export::StaticCell;
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals::{I2C0, I2C1};
use embassy_rp::{bind_interrupts, i2c, i2c_slave};
use embedded_hal_1::i2c::Operation;
use embedded_hal_async::i2c::I2c;
use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _, panic_probe as _, panic_probe as _};
static mut CORE1_STACK: Stack<1024> = Stack::new();

View File

@ -5,10 +5,10 @@ teleprobe_meta::target!(b"rpi-pico");
use defmt::{info, unwrap};
use embassy_executor::Executor;
use embassy_executor::_export::StaticCell;
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _};
static mut CORE1_STACK: Stack<1024> = Stack::new();

View File

@ -8,8 +8,8 @@ autobins = false
[features]
stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"]
stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac-adc-pin", "rng"]
stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"]
stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"]
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"]
stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac-adc-pin", "rng"]
stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng"]
@ -19,7 +19,7 @@ stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng"]
stm32u585ai = ["embassy-stm32/stm32u585ai", "chrono", "rng"]
stm32u5a5zj = ["embassy-stm32/stm32u5a5zj", "chrono", "rng"]
stm32wba52cg = ["embassy-stm32/stm32wba52cg", "chrono", "rng"]
stm32l073rz = ["embassy-stm32/stm32l073rz", "not-gpdma", "rng"]
stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"]
stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"]
stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma", "rng"]
stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma", "rng"]
@ -33,7 +33,7 @@ stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"]
eth = []
rng = []
sdmmc = []
stop = ["embassy-stm32/low-power"]
stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"]
chrono = ["embassy-stm32/chrono", "dep:chrono"]
can = []
ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
@ -42,6 +42,8 @@ embassy-stm32-wpan = []
not-gpdma = []
dac-adc-pin = []
cm0 = ["portable-atomic/unsafe-assume-single-core"]
[dependencies]
teleprobe-meta = "1"
@ -66,7 +68,8 @@ micromath = "2.0.0"
panic-probe = { version = "0.3.0", features = ["print-defmt"] }
rand_core = { version = "0.6", default-features = false }
rand_chacha = { version = "0.3", default-features = false }
static_cell = {version = "1.1", features = ["nightly"] }
static_cell = { version = "2", features = ["nightly"] }
portable-atomic = { version = "1.5", features = [] }
chrono = { version = "^0.4", default-features = false, optional = true}

View File

@ -460,23 +460,25 @@ pub fn config() -> Config {
#[cfg(feature = "stm32l073rz")]
{
use embassy_stm32::rcc::*;
config.rcc.mux = ClockSrc::PLL(
// 32Mhz clock (16 * 4 / 2)
PLLSource::HSI,
PLLMul::MUL4,
PLLDiv::DIV2,
);
config.rcc.hsi = true;
config.rcc.pll = Some(Pll {
source: PLLSource::HSI,
mul: PLLMul::MUL4,
div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
});
config.rcc.mux = ClockSrc::PLL1_P;
}
#[cfg(any(feature = "stm32l152re"))]
{
use embassy_stm32::rcc::*;
config.rcc.mux = ClockSrc::PLL(
// 32Mhz clock (16 * 4 / 2)
PLLSource::HSI,
PLLMul::MUL4,
PLLDiv::DIV2,
);
config.rcc.hsi = true;
config.rcc.pll = Some(Pll {
source: PLLSource::HSI,
mul: PLLMul::MUL4,
div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
});
config.rcc.mux = ClockSrc::PLL1_P;
}
config