diff options
Diffstat (limited to 'embassy-stm32/src/lib.rs')
| -rw-r--r-- | embassy-stm32/src/lib.rs | 65 |
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)] |
| 55 | pub mod adc; | 56 | pub mod adc; |
| 57 | #[cfg(backup_sram)] | ||
| 58 | pub mod backup_sram; | ||
| 56 | #[cfg(can)] | 59 | #[cfg(can)] |
| 57 | pub mod can; | 60 | pub mod can; |
| 58 | // FIXME: Cordic driver cause stm32u5a5zj crash | 61 | // FIXME: Cordic driver cause stm32u5a5zj crash |
| @@ -74,6 +77,7 @@ pub mod dts; | |||
| 74 | pub mod eth; | 77 | pub mod eth; |
| 75 | #[cfg(feature = "exti")] | 78 | #[cfg(feature = "exti")] |
| 76 | pub mod exti; | 79 | pub mod exti; |
| 80 | #[cfg(flash)] | ||
| 77 | pub mod flash; | 81 | pub mod flash; |
| 78 | #[cfg(fmc)] | 82 | #[cfg(fmc)] |
| 79 | pub mod fmc; | 83 | pub mod fmc; |
| @@ -91,6 +95,8 @@ pub mod i2c; | |||
| 91 | pub mod i2s; | 95 | pub mod i2s; |
| 92 | #[cfg(stm32wb)] | 96 | #[cfg(stm32wb)] |
| 93 | pub mod ipcc; | 97 | pub mod ipcc; |
| 98 | #[cfg(lcd)] | ||
| 99 | pub mod lcd; | ||
| 94 | #[cfg(feature = "low-power")] | 100 | #[cfg(feature = "low-power")] |
| 95 | pub mod low_power; | 101 | pub 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] |
| 180 | macro_rules! bind_interrupts { | 189 | macro_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 |
| 225 | pub use _generated::{peripherals, Peripherals}; | 234 | pub use _generated::{Peripherals, peripherals}; |
| 226 | pub use embassy_hal_internal::{Peri, PeripheralType}; | 235 | pub use embassy_hal_internal::{Peri, PeripheralType}; |
| 227 | #[cfg(feature = "unstable-pac")] | 236 | #[cfg(feature = "unstable-pac")] |
| 228 | pub use stm32_metapac as pac; | 237 | pub 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)] | ||
| 670 | pub(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 | } | ||
