diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 33f22f676..214813a42 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -779,13 +779,6 @@ pub(crate) unsafe fn init(_cs: CriticalSection) { <crate::peripherals::AFIO as crate::rcc::SealedRccPeripheral>::enable_and_reset_with_cs(_cs); crate::_generated::init_gpio(); - - // Setting this bit is mandatory to use PG[15:2]. - #[cfg(stm32u5)] - crate::pac::PWR.svmcr().modify(|w| { - w.set_io2sv(true); - w.set_io2vmen(true); - }); } impl<'d> embedded_hal_02::digital::v2::InputPin for Input<'d> { diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 6a3d1c463..ab6ef8ef4 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -172,6 +172,14 @@ pub struct Config { #[cfg(dbgmcu)] pub enable_debug_during_sleep: bool, + /// On low-power boards (eg. `stm32l4`, `stm32l5` and `stm32u5`), + /// some GPIO pins are powered by an auxiliary, independent power supply (`VDDIO2`), + /// which needs to be enabled before these pins can be used. + /// + /// May increase power consumption. Defaults to true. + #[cfg(any(stm32l4, stm32l5, stm32u5))] + pub enable_independent_io_supply: bool, + /// BDMA interrupt priority. /// /// Defaults to P0 (highest). @@ -209,6 +217,8 @@ impl Default for Config { rcc: Default::default(), #[cfg(dbgmcu)] enable_debug_during_sleep: true, + #[cfg(any(stm32l4, stm32l5, stm32u5))] + enable_independent_io_supply: true, #[cfg(bdma)] bdma_interrupt_priority: Priority::P0, #[cfg(dma)] @@ -270,6 +280,24 @@ pub fn init(config: Config) -> Peripherals { #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))] peripherals::FLASH::enable_and_reset_with_cs(cs); + // Enable the VDDIO2 power supply on chips that have it. + // Note that this requires the PWR peripheral to be enabled first. + #[cfg(any(stm32l4, stm32l5))] + { + crate::pac::PWR.cr2().modify(|w| { + // The official documentation states that we should ideally enable VDDIO2 + // through the PVME2 bit, but it looks like this isn't required, + // and CubeMX itself skips this step. + w.set_iosv(config.enable_independent_io_supply); + }); + } + #[cfg(stm32u5)] + { + crate::pac::PWR.svmcr().modify(|w| { + w.set_io2sv(config.enable_independent_io_supply); + }); + } + // dead battery functionality is still present on these // chips despite them not having UCPD- disable it #[cfg(any(stm32g070, stm32g0b0))] diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 343e09e68..77aa929ab 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -93,12 +93,6 @@ async fn main(spawner: Spawner) { let dp = embassy_stm32::init(config); - // RM0432rev9, 5.1.2: Independent I/O supply rail - // After reset, the I/Os supplied by VDDIO2 are logically and electrically isolated and - // therefore are not available. The isolation must be removed before using any I/O from - // PG[15:2], by setting the IOSV bit in the PWR_CR2 register, once the VDDIO2 supply is present - pac::PWR.cr2().modify(|w| w.set_iosv(true)); - let reset_status = pac::RCC.bdcr().read().0; defmt::println!("bdcr before: 0x{:X}", reset_status); diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index c379863a8..0e555efc8 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -251,13 +251,6 @@ define_peris!( ); pub fn config() -> Config { - // Setting this bit is mandatory to use PG[15:2]. - #[cfg(feature = "stm32u5a5zj")] - embassy_stm32::pac::PWR.svmcr().modify(|w| { - w.set_io2sv(true); - w.set_io2vmen(true); - }); - #[allow(unused_mut)] let mut config = Config::default();