aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/lib.rs')
-rw-r--r--embassy-stm32/src/lib.rs65
1 files changed, 58 insertions, 7 deletions
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 7e0f7884e..2f783bf64 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -1,5 +1,6 @@
1#![cfg_attr(not(test), no_std)] 1#![cfg_attr(not(test), no_std)]
2#![allow(async_fn_in_trait)] 2#![allow(async_fn_in_trait)]
3#![allow(unsafe_op_in_unsafe_fn)]
3#![cfg_attr( 4#![cfg_attr(
4 docsrs, 5 docsrs,
5 doc = "<div style='padding:30px;background:#810;color:#fff;text-align:center;'><p>You might want to <a href='https://docs.embassy.dev/embassy-stm32'>browse the `embassy-stm32` documentation on the Embassy website</a> instead.</p><p>The documentation here on `docs.rs` is built for a single chip only (stm32h7, stm32h7rs55 in particular), while on the Embassy website you can pick your exact chip from the top menu. Available peripherals and their APIs change depending on the chip.</p></div>\n\n" 6 doc = "<div style='padding:30px;background:#810;color:#fff;text-align:center;'><p>You might want to <a href='https://docs.embassy.dev/embassy-stm32'>browse the `embassy-stm32` documentation on the Embassy website</a> instead.</p><p>The documentation here on `docs.rs` is built for a single chip only (stm32h7, stm32h7rs55 in particular), while on the Embassy website you can pick your exact chip from the top menu. Available peripherals and their APIs change depending on the chip.</p></div>\n\n"
@@ -53,6 +54,8 @@ pub mod timer;
53 54
54#[cfg(adc)] 55#[cfg(adc)]
55pub mod adc; 56pub mod adc;
57#[cfg(backup_sram)]
58pub mod backup_sram;
56#[cfg(can)] 59#[cfg(can)]
57pub mod can; 60pub mod can;
58// FIXME: Cordic driver cause stm32u5a5zj crash 61// FIXME: Cordic driver cause stm32u5a5zj crash
@@ -74,6 +77,7 @@ pub mod dts;
74pub mod eth; 77pub mod eth;
75#[cfg(feature = "exti")] 78#[cfg(feature = "exti")]
76pub mod exti; 79pub mod exti;
80#[cfg(flash)]
77pub mod flash; 81pub mod flash;
78#[cfg(fmc)] 82#[cfg(fmc)]
79pub mod fmc; 83pub mod fmc;
@@ -91,6 +95,8 @@ pub mod i2c;
91pub mod i2s; 95pub mod i2s;
92#[cfg(stm32wb)] 96#[cfg(stm32wb)]
93pub mod ipcc; 97pub mod ipcc;
98#[cfg(lcd)]
99pub mod lcd;
94#[cfg(feature = "low-power")] 100#[cfg(feature = "low-power")]
95pub mod low_power; 101pub mod low_power;
96#[cfg(lptim)] 102#[cfg(lptim)]
@@ -147,7 +153,7 @@ pub use crate::_generated::interrupt;
147/// Macro to bind interrupts to handlers. 153/// Macro to bind interrupts to handlers.
148/// 154///
149/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) 155/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
150/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to 156/// and implements the right [`Binding`](crate::interrupt::typelevel::Binding)s for it. You can pass this struct to drivers to
151/// prove at compile-time that the right interrupts have been bound. 157/// prove at compile-time that the right interrupts have been bound.
152/// 158///
153/// Example of how to bind one interrupt: 159/// Example of how to bind one interrupt:
@@ -174,7 +180,10 @@ pub use crate::_generated::interrupt;
174/// } 180/// }
175/// ); 181/// );
176/// ``` 182/// ```
177 183///
184/// Some chips collate multiple interrupt signals into a single interrupt vector. In the above example, I2C2_3 is a
185/// single vector which is activated by events and errors on both peripherals I2C2 and I2C3. Check your chip's list
186/// of interrupt vectors if you get an unexpected compile error trying to bind the standard name.
178// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. 187// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
179#[macro_export] 188#[macro_export]
180macro_rules! bind_interrupts { 189macro_rules! bind_interrupts {
@@ -194,7 +203,7 @@ macro_rules! bind_interrupts {
194 203
195 $( 204 $(
196 #[allow(non_snake_case)] 205 #[allow(non_snake_case)]
197 #[no_mangle] 206 #[unsafe(no_mangle)]
198 $(#[cfg($cond_irq)])? 207 $(#[cfg($cond_irq)])?
199 $(#[doc = $doc])* 208 $(#[doc = $doc])*
200 unsafe extern "C" fn $irq() { 209 unsafe extern "C" fn $irq() {
@@ -222,7 +231,7 @@ macro_rules! bind_interrupts {
222} 231}
223 232
224// Reexports 233// Reexports
225pub use _generated::{peripherals, Peripherals}; 234pub use _generated::{Peripherals, peripherals};
226pub use embassy_hal_internal::{Peri, PeripheralType}; 235pub use embassy_hal_internal::{Peri, PeripheralType};
227#[cfg(feature = "unstable-pac")] 236#[cfg(feature = "unstable-pac")]
228pub use stm32_metapac as pac; 237pub use stm32_metapac as pac;
@@ -240,6 +249,14 @@ pub struct Config {
240 /// RCC config. 249 /// RCC config.
241 pub rcc: rcc::Config, 250 pub rcc: rcc::Config,
242 251
252 #[cfg(feature = "low-power")]
253 /// RTC config
254 pub rtc: rtc::RtcConfig,
255
256 #[cfg(feature = "low-power")]
257 /// Minimum time to stop
258 pub min_stop_pause: embassy_time::Duration,
259
243 /// Enable debug during sleep and stop. 260 /// Enable debug during sleep and stop.
244 /// 261 ///
245 /// May increase power consumption. Defaults to true. 262 /// May increase power consumption. Defaults to true.
@@ -293,6 +310,10 @@ impl Default for Config {
293 fn default() -> Self { 310 fn default() -> Self {
294 Self { 311 Self {
295 rcc: Default::default(), 312 rcc: Default::default(),
313 #[cfg(feature = "low-power")]
314 rtc: Default::default(),
315 #[cfg(feature = "low-power")]
316 min_stop_pause: embassy_time::Duration::from_millis(250),
296 #[cfg(dbgmcu)] 317 #[cfg(dbgmcu)]
297 enable_debug_during_sleep: true, 318 enable_debug_during_sleep: true,
298 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] 319 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))]
@@ -495,6 +516,16 @@ fn init_hw(config: Config) -> Peripherals {
495 critical_section::with(|cs| { 516 critical_section::with(|cs| {
496 let p = Peripherals::take_with_cs(cs); 517 let p = Peripherals::take_with_cs(cs);
497 518
519 #[cfg(dbgmcu_n6)]
520 {
521 crate::pac::RCC.miscensr().write(|w| w.set_dbgens(true));
522 crate::pac::RCC.miscenr().read(); // volatile read
523 crate::pac::DBGMCU
524 .cr()
525 .modify(|w| w.set_dbgclken(stm32_metapac::dbgmcu::vals::Dbgclken::B_0X1));
526 crate::pac::DBGMCU.cr().read();
527 }
528
498 #[cfg(dbgmcu)] 529 #[cfg(dbgmcu)]
499 crate::pac::DBGMCU.cr().modify(|cr| { 530 crate::pac::DBGMCU.cr().modify(|cr| {
500 #[cfg(dbgmcu_h5)] 531 #[cfg(dbgmcu_h5)]
@@ -509,7 +540,7 @@ fn init_hw(config: Config) -> Peripherals {
509 } 540 }
510 #[cfg(any( 541 #[cfg(any(
511 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, 542 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1,
512 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl 543 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl, dbgmcu_n6
513 ))] 544 ))]
514 { 545 {
515 cr.set_dbg_sleep(config.enable_debug_during_sleep); 546 cr.set_dbg_sleep(config.enable_debug_during_sleep);
@@ -530,7 +561,7 @@ fn init_hw(config: Config) -> Peripherals {
530 rcc::enable_and_reset_with_cs::<peripherals::SYSCFG>(cs); 561 rcc::enable_and_reset_with_cs::<peripherals::SYSCFG>(cs);
531 #[cfg(not(any(stm32h5, stm32h7, stm32h7rs, stm32wb, stm32wl)))] 562 #[cfg(not(any(stm32h5, stm32h7, stm32h7rs, stm32wb, stm32wl)))]
532 rcc::enable_and_reset_with_cs::<peripherals::PWR>(cs); 563 rcc::enable_and_reset_with_cs::<peripherals::PWR>(cs);
533 #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7, stm32h7rs)))] 564 #[cfg(all(flash, not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7, stm32h7rs))))]
534 rcc::enable_and_reset_with_cs::<peripherals::FLASH>(cs); 565 rcc::enable_and_reset_with_cs::<peripherals::FLASH>(cs);
535 566
536 // Enable the VDDIO2 power supply on chips that have it. 567 // Enable the VDDIO2 power supply on chips that have it.
@@ -590,7 +621,7 @@ fn init_hw(config: Config) -> Peripherals {
590 #[cfg(ucpd)] 621 #[cfg(ucpd)]
591 ucpd::init( 622 ucpd::init(
592 cs, 623 cs,
593 #[cfg(peri_ucpd1)] 624 #[cfg(all(peri_ucpd1, not(stm32n6)))]
594 config.enable_ucpd1_dead_battery, 625 config.enable_ucpd1_dead_battery,
595 #[cfg(peri_ucpd2)] 626 #[cfg(peri_ucpd2)]
596 config.enable_ucpd2_dead_battery, 627 config.enable_ucpd2_dead_battery,
@@ -622,8 +653,28 @@ fn init_hw(config: Config) -> Peripherals {
622 exti::init(cs); 653 exti::init(cs);
623 654
624 rcc::init_rcc(cs, config.rcc); 655 rcc::init_rcc(cs, config.rcc);
656
657 #[cfg(feature = "low-power")]
658 rtc::init_rtc(cs, config.rtc, config.min_stop_pause);
659
660 #[cfg(all(stm32wb, feature = "low-power"))]
661 hsem::init_hsem(cs);
625 } 662 }
626 663
627 p 664 p
628 }) 665 })
629} 666}
667
668/// Performs a busy-wait delay for a specified number of microseconds.
669#[allow(unused)]
670pub(crate) fn block_for_us(us: u64) {
671 cfg_if::cfg_if! {
672 // this does strange things on stm32wlx in low power mode depending on exactly when it's called
673 // as in sometimes 15 us (1 tick) would take > 20 seconds.
674 if #[cfg(all(feature = "time", all(not(feature = "low-power"), not(stm32wlex))))] {
675 embassy_time::block_for(embassy_time::Duration::from_micros(us));
676 } else {
677 cortex_m::asm::delay(unsafe { rcc::get_freqs().sys.to_hertz().unwrap().0 as u64 * us / 1_000_000 } as u32);
678 }
679 }
680}