diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index d53a00a47..711b13f30 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -80,6 +80,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Trying to send a single-shot RMT transmission will result in an error now, `RMT` deals with `u32` now, `PulseCode` is a convenience trait now (#2463) - Removed `get_` prefixes from functions (#2528) - The `Camera` and `I8080` drivers' constructors now only accepts blocking-mode DMA channels. (#2519) +- Many peripherals are now disabled by default and also get disabled when the driver is dropped (#2544) ### Fixed diff --git a/esp-hal/src/aes/esp32.rs b/esp-hal/src/aes/esp32.rs index 963e14f6f..c638cc7ec 100644 --- a/esp-hal/src/aes/esp32.rs +++ b/esp-hal/src/aes/esp32.rs @@ -1,11 +1,7 @@ -use crate::{ - aes::{Aes, Aes128, Aes192, Aes256, AesFlavour, Endianness, ALIGN_SIZE}, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, -}; +use crate::aes::{Aes, Aes128, Aes192, Aes256, AesFlavour, Endianness, ALIGN_SIZE}; impl Aes<'_> { pub(super) fn init(&mut self) { - PeripheralClockControl::enable(PeripheralEnable::Aes); self.write_endianness( Endianness::BigEndian, Endianness::BigEndian, diff --git a/esp-hal/src/aes/esp32cX.rs b/esp-hal/src/aes/esp32cX.rs index 9477b1757..1851bba47 100644 --- a/esp-hal/src/aes/esp32cX.rs +++ b/esp-hal/src/aes/esp32cX.rs @@ -1,11 +1,7 @@ -use crate::{ - aes::{Aes, Aes128, Aes256, AesFlavour, ALIGN_SIZE}, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, -}; +use crate::aes::{Aes, Aes128, Aes256, AesFlavour, ALIGN_SIZE}; impl Aes<'_> { pub(super) fn init(&mut self) { - PeripheralClockControl::enable(PeripheralEnable::Aes); self.write_dma(false); } diff --git a/esp-hal/src/aes/esp32s2.rs b/esp-hal/src/aes/esp32s2.rs index ccfb6a57c..cd0888399 100644 --- a/esp-hal/src/aes/esp32s2.rs +++ b/esp-hal/src/aes/esp32s2.rs @@ -1,11 +1,7 @@ -use crate::{ - aes::{Aes, Aes128, Aes192, Aes256, AesFlavour, Endianness, ALIGN_SIZE}, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, -}; +use crate::aes::{Aes, Aes128, Aes192, Aes256, AesFlavour, Endianness, ALIGN_SIZE}; impl Aes<'_> { pub(super) fn init(&mut self) { - PeripheralClockControl::enable(PeripheralEnable::Aes); self.write_dma(false); self.write_endianness( Endianness::BigEndian, diff --git a/esp-hal/src/aes/esp32s3.rs b/esp-hal/src/aes/esp32s3.rs index 447dbacd5..8b2d81e57 100644 --- a/esp-hal/src/aes/esp32s3.rs +++ b/esp-hal/src/aes/esp32s3.rs @@ -1,11 +1,7 @@ -use crate::{ - aes::{Aes, Aes128, Aes256, AesFlavour, ALIGN_SIZE}, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, -}; +use crate::aes::{Aes, Aes128, Aes256, AesFlavour, ALIGN_SIZE}; impl Aes<'_> { pub(super) fn init(&mut self) { - PeripheralClockControl::enable(PeripheralEnable::Aes); self.write_dma(false); } diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index 34a14f03c..5112ebbd2 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -59,6 +59,7 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::AES, reg_access::{AlignmentHelper, NativeEndianess}, + system::GenericPeripheralGuard, }; #[cfg_attr(esp32, path = "esp32.rs")] @@ -136,6 +137,7 @@ pub enum Mode { pub struct Aes<'d> { aes: PeripheralRef<'d, AES>, alignment_helper: AlignmentHelper, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Aes as u8 }>, } impl<'d> Aes<'d> { @@ -143,12 +145,12 @@ impl<'d> Aes<'d> { pub fn new(aes: impl Peripheral

+ 'd) -> Self { crate::into_ref!(aes); - crate::system::PeripheralClockControl::reset(crate::system::Peripheral::Aes); - crate::system::PeripheralClockControl::enable(crate::system::Peripheral::Aes); + let guard = GenericPeripheralGuard::new(); let mut ret = Self { aes, alignment_helper: AlignmentHelper::native_endianess(), + _guard: guard, }; ret.init(); diff --git a/esp-hal/src/analog/adc/riscv.rs b/esp-hal/src/analog/adc/riscv.rs index c9c4bcdd6..c228502e4 100644 --- a/esp-hal/src/analog/adc/riscv.rs +++ b/esp-hal/src/analog/adc/riscv.rs @@ -8,7 +8,7 @@ use crate::efuse::Efuse; use crate::{ peripheral::PeripheralRef, peripherals::APB_SARADC, - system::{Peripheral, PeripheralClockControl}, + system::{GenericPeripheralGuard, Peripheral}, }; mod calibration; @@ -396,6 +396,7 @@ pub struct Adc<'d, ADCI> { _adc: PeripheralRef<'d, ADCI>, attenuations: [Option; NUM_ATTENS], active_channel: Option, + _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>, } impl<'d, ADCI> Adc<'d, ADCI> @@ -408,8 +409,7 @@ where adc_instance: impl crate::peripheral::Peripheral

+ 'd, config: AdcConfig, ) -> Self { - PeripheralClockControl::reset(Peripheral::ApbSarAdc); - PeripheralClockControl::enable(Peripheral::ApbSarAdc); + let guard = GenericPeripheralGuard::new(); unsafe { &*APB_SARADC::PTR }.ctrl().modify(|_, w| unsafe { w.start_force().set_bit(); @@ -422,6 +422,7 @@ where _adc: adc_instance.into_ref(), attenuations: config.attenuations, active_channel: None, + _guard: guard, } } diff --git a/esp-hal/src/analog/adc/xtensa.rs b/esp-hal/src/analog/adc/xtensa.rs index 324c79462..c8f547dce 100644 --- a/esp-hal/src/analog/adc/xtensa.rs +++ b/esp-hal/src/analog/adc/xtensa.rs @@ -6,7 +6,7 @@ use crate::efuse::Efuse; use crate::{ peripheral::PeripheralRef, peripherals::{APB_SARADC, SENS}, - system::{Peripheral, PeripheralClockControl}, + system::{GenericPeripheralGuard, Peripheral}, }; mod calibration; @@ -389,6 +389,7 @@ pub struct Adc<'d, ADC> { _adc: PeripheralRef<'d, ADC>, active_channel: Option, last_init_code: u16, + _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>, } impl<'d, ADCI> Adc<'d, ADCI> @@ -401,9 +402,7 @@ where adc_instance: impl crate::peripheral::Peripheral

+ 'd, config: AdcConfig, ) -> Self { - PeripheralClockControl::reset(Peripheral::ApbSarAdc); - PeripheralClockControl::enable(Peripheral::ApbSarAdc); - + let guard = GenericPeripheralGuard::new(); let sensors = unsafe { &*SENS::ptr() }; // Set attenuation for pins @@ -472,6 +471,7 @@ where _adc: adc_instance.into_ref(), active_channel: None, last_init_code: 0, + _guard: guard, } } diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 8c2ca9a24..c53a5f5a9 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -753,7 +753,9 @@ impl<'d> Dma<'d> { ) -> Dma<'d> { crate::into_ref!(dma); - PeripheralClockControl::enable(Peripheral::Gdma); + if PeripheralClockControl::enable(Peripheral::Gdma) { + PeripheralClockControl::reset(Peripheral::Gdma); + } dma.misc_conf().modify(|_, w| w.ahbm_rst_inter().set_bit()); dma.misc_conf() .modify(|_, w| w.ahbm_rst_inter().clear_bit()); diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 609c89f24..738e486d9 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -942,7 +942,9 @@ impl<'d> Dma<'d> { pub fn new( dma: impl crate::peripheral::Peripheral

+ 'd, ) -> Dma<'d> { - PeripheralClockControl::enable(Peripheral::Dma); + if PeripheralClockControl::enable(Peripheral::Dma) { + PeripheralClockControl::reset(Peripheral::Dma); + } #[cfg(esp32)] { diff --git a/esp-hal/src/ecc.rs b/esp-hal/src/ecc.rs index 7c6ccfcc2..6130d9868 100644 --- a/esp-hal/src/ecc.rs +++ b/esp-hal/src/ecc.rs @@ -32,7 +32,7 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::{Interrupt, ECC}, reg_access::{AlignmentHelper, SocDependentEndianess}, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, + system::{self, GenericPeripheralGuard}, InterruptConfigurable, }; @@ -41,6 +41,7 @@ pub struct Ecc<'d, DM: crate::Mode> { ecc: PeripheralRef<'d, ECC>, alignment_helper: AlignmentHelper, phantom: PhantomData, + _guard: GenericPeripheralGuard<{ system::Peripheral::Ecc as u8 }>, } /// ECC interface error @@ -102,13 +103,13 @@ impl<'d> Ecc<'d, crate::Blocking> { pub fn new(ecc: impl Peripheral

+ 'd) -> Self { crate::into_ref!(ecc); - PeripheralClockControl::reset(PeripheralEnable::Ecc); - PeripheralClockControl::enable(PeripheralEnable::Ecc); + let guard = GenericPeripheralGuard::new(); Self { ecc, alignment_helper: AlignmentHelper::default(), phantom: PhantomData, + _guard: guard, } } } diff --git a/esp-hal/src/etm.rs b/esp-hal/src/etm.rs index 5276eadcc..b39d86573 100644 --- a/esp-hal/src/etm.rs +++ b/esp-hal/src/etm.rs @@ -59,7 +59,7 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, - system::PeripheralClockControl, + system::GenericPeripheralGuard, }; /// Unconfigured EtmChannel. @@ -76,6 +76,7 @@ impl EtmChannel { T: EtmTask, { let etm = unsafe { crate::peripherals::SOC_ETM::steal() }; + let guard = GenericPeripheralGuard::new(); etm.ch(C as usize) .evt_id() @@ -92,6 +93,7 @@ impl EtmChannel { EtmConfiguredChannel { _event: event, _task: task, + _guard: guard, } } } @@ -117,6 +119,7 @@ where { _event: &'a E, _task: &'a T, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Etm as u8 }>, } impl Drop for EtmConfiguredChannel<'_, E, T, C> @@ -125,7 +128,7 @@ where T: EtmTask, { fn drop(&mut self) { - debug!("drop {}", C); + debug!("Drop ETM channel {}", C); disable_channel(C); } } @@ -149,12 +152,9 @@ macro_rules! create_etm { pub fn new(peripheral: impl Peripheral

+ 'd) -> Self { crate::into_ref!(peripheral); - PeripheralClockControl::reset(crate::system::Peripheral::Etm); - PeripheralClockControl::enable(crate::system::Peripheral::Etm); - Self { _peripheral: peripheral, - $([< channel $num >]: EtmChannel {},)+ + $([< channel $num >]: EtmChannel { },)+ } } } diff --git a/esp-hal/src/hmac.rs b/esp-hal/src/hmac.rs index e7709972b..67b5e2620 100644 --- a/esp-hal/src/hmac.rs +++ b/esp-hal/src/hmac.rs @@ -40,7 +40,7 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::HMAC, reg_access::{AlignmentHelper, SocDependentEndianess}, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, + system::{GenericPeripheralGuard, Peripheral as PeripheralEnable}, }; /// Provides an interface for interacting with the HMAC hardware peripheral. @@ -51,6 +51,7 @@ pub struct Hmac<'d> { alignment_helper: AlignmentHelper, byte_written: usize, next_command: NextCommand, + _guard: GenericPeripheralGuard<{ PeripheralEnable::Hmac as u8 }>, } /// HMAC interface error @@ -107,14 +108,14 @@ impl<'d> Hmac<'d> { pub fn new(hmac: impl Peripheral

+ 'd) -> Self { crate::into_ref!(hmac); - PeripheralClockControl::reset(PeripheralEnable::Hmac); - PeripheralClockControl::enable(PeripheralEnable::Hmac); + let guard = GenericPeripheralGuard::new(); Self { hmac, alignment_helper: AlignmentHelper::default(), byte_written: 64, next_command: NextCommand::None, + _guard: guard, } } diff --git a/esp-hal/src/i2c/master/mod.rs b/esp-hal/src/i2c/master/mod.rs index adba76537..2dc00820a 100644 --- a/esp-hal/src/i2c/master/mod.rs +++ b/esp-hal/src/i2c/master/mod.rs @@ -59,7 +59,7 @@ use crate::{ Interrupt, }, private, - system::PeripheralClockControl, + system::{PeripheralClockControl, PeripheralGuard}, Async, Blocking, Cpu, @@ -273,6 +273,7 @@ pub struct I2c<'d, DM: Mode, T = AnyI2c> { i2c: PeripheralRef<'d, T>, phantom: PhantomData, config: Config, + guard: PeripheralGuard, } impl SetConfig for I2c<'_, DM, T> { @@ -352,8 +353,9 @@ where } fn internal_recover(&self) { - PeripheralClockControl::reset(self.driver().info.peripheral); + PeripheralClockControl::disable(self.driver().info.peripheral); PeripheralClockControl::enable(self.driver().info.peripheral); + PeripheralClockControl::reset(self.driver().info.peripheral); // We know the configuration is valid, we can ignore the result. _ = self.driver().setup(&self.config); @@ -469,15 +471,15 @@ where pub fn new_typed(i2c: impl Peripheral

+ 'd, config: Config) -> Self { crate::into_ref!(i2c); + let guard = PeripheralGuard::new(i2c.info().peripheral); + let i2c = I2c { i2c, phantom: PhantomData, config, + guard, }; - PeripheralClockControl::reset(i2c.driver().info.peripheral); - PeripheralClockControl::enable(i2c.driver().info.peripheral); - unwrap!(i2c.driver().setup(&i2c.config)); i2c } @@ -492,6 +494,7 @@ where i2c: self.i2c, phantom: PhantomData, config: self.config, + guard: self.guard, } } @@ -685,6 +688,7 @@ where i2c: self.i2c, phantom: PhantomData, config: self.config, + guard: self.guard, } } diff --git a/esp-hal/src/i2s/master.rs b/esp-hal/src/i2s/master.rs index 111596ae9..5a8e4a84b 100644 --- a/esp-hal/src/i2s/master.rs +++ b/esp-hal/src/i2s/master.rs @@ -100,7 +100,7 @@ use crate::{ gpio::interconnect::PeripheralOutput, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, - system::PeripheralClockControl, + system::PeripheralGuard, Async, Blocking, InterruptConfigurable, @@ -284,8 +284,11 @@ where // could be configured totally independently but for now handle all // the targets the same and force same configuration for both, TX and RX - PeripheralClockControl::reset(i2s.peripheral()); - PeripheralClockControl::enable(i2s.peripheral()); + // make sure the peripheral is enabled before configuring it + let peripheral = i2s.peripheral(); + let rx_guard = PeripheralGuard::new(peripheral); + let tx_guard = PeripheralGuard::new(peripheral); + i2s.set_clock(calculate_clock(sample_rate, 2, data_format.channel_bits())); i2s.configure(&standard, &data_format); i2s.set_master(); @@ -297,11 +300,13 @@ where i2s: unsafe { i2s.clone_unchecked() }, rx_channel: channel.rx, descriptors: rx_descriptors, + guard: rx_guard, }, i2s_tx: TxCreator { i2s, tx_channel: channel.tx, descriptors: tx_descriptors, + guard: tx_guard, }, } } @@ -432,11 +437,13 @@ where i2s: self.i2s_rx.i2s, rx_channel: self.i2s_rx.rx_channel.into_async(), descriptors: self.i2s_rx.descriptors, + guard: self.i2s_rx.guard, }, i2s_tx: TxCreator { i2s: self.i2s_tx.i2s, tx_channel: self.i2s_tx.tx_channel.into_async(), descriptors: self.i2s_tx.descriptors, + guard: self.i2s_tx.guard, }, } } @@ -465,6 +472,7 @@ where i2s: PeripheralRef<'d, T>, tx_channel: ChannelTx<'d, DmaMode, T::Dma>, tx_chain: DescriptorChain, + _guard: PeripheralGuard, } impl core::fmt::Debug for I2sTx<'_, DmaMode, T> @@ -597,6 +605,7 @@ where i2s: PeripheralRef<'d, T>, rx_channel: ChannelRx<'d, DmaMode, T::Dma>, rx_chain: DescriptorChain, + _guard: PeripheralGuard, } impl core::fmt::Debug for I2sRx<'_, DmaMode, T> @@ -742,6 +751,7 @@ mod private { I2sInterrupt, I2sRx, I2sTx, + PeripheralGuard, RegisterAccess, Standard, I2S_LL_MCLK_DIVIDER_MAX, @@ -774,6 +784,7 @@ mod private { pub i2s: PeripheralRef<'d, T>, pub tx_channel: ChannelTx<'d, M, T::Dma>, pub descriptors: &'static mut [DmaDescriptor], + pub(crate) guard: PeripheralGuard, } impl<'d, M, T> TxCreator<'d, M, T> @@ -782,10 +793,12 @@ mod private { T: RegisterAccess, { pub fn build(self) -> I2sTx<'d, M, T> { + let peripheral = self.i2s.peripheral(); I2sTx { i2s: self.i2s, tx_channel: self.tx_channel, tx_chain: DescriptorChain::new(self.descriptors), + _guard: PeripheralGuard::new(peripheral), } } @@ -831,6 +844,7 @@ mod private { pub i2s: PeripheralRef<'d, T>, pub rx_channel: ChannelRx<'d, M, T::Dma>, pub descriptors: &'static mut [DmaDescriptor], + pub(crate) guard: PeripheralGuard, } impl<'d, M, T> RxCreator<'d, M, T> @@ -839,10 +853,12 @@ mod private { T: RegisterAccess, { pub fn build(self) -> I2sRx<'d, M, T> { + let peripheral = self.i2s.peripheral(); I2sRx { i2s: self.i2s, rx_channel: self.rx_channel, rx_chain: DescriptorChain::new(self.descriptors), + _guard: PeripheralGuard::new(peripheral), } } diff --git a/esp-hal/src/i2s/parallel.rs b/esp-hal/src/i2s/parallel.rs index 9d6ab818a..810b11686 100644 --- a/esp-hal/src/i2s/parallel.rs +++ b/esp-hal/src/i2s/parallel.rs @@ -60,7 +60,7 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::{i2s0::RegisterBlock, I2S0, I2S1}, private::Internal, - system::PeripheralClockControl, + system::PeripheralGuard, Async, Mode, }; @@ -177,6 +177,7 @@ where { instance: PeripheralRef<'d, I>, tx_channel: ChannelTx<'d, DM, I::Dma>, + _guard: PeripheralGuard, } impl<'d, DM> I2sParallel<'d, DM> @@ -220,8 +221,8 @@ where channel.runtime_ensure_compatible(&i2s); let channel = channel.degrade(); - PeripheralClockControl::reset(i2s.peripheral()); - PeripheralClockControl::enable(i2s.peripheral()); + let guard = PeripheralGuard::new(i2s.peripheral()); + // configure the I2S peripheral for parallel mode i2s.setup(frequency, pins.bus_width()); // setup the clock pin @@ -232,6 +233,7 @@ where Self { instance: i2s, tx_channel: channel.tx, + _guard: guard, } } diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 358643e87..e22ab2868 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -82,6 +82,7 @@ use crate::{ lcd_cam::{calculate_clkm, BitOrder, ByteOrder}, peripheral::{Peripheral, PeripheralRef}, peripherals::LCD_CAM, + system::{self, GenericPeripheralGuard}, Blocking, }; @@ -121,12 +122,14 @@ pub enum VsyncFilterThreshold { pub struct Cam<'d> { /// The LCD_CAM peripheral reference for managing the camera functionality. pub(crate) lcd_cam: PeripheralRef<'d, LCD_CAM>, + pub(super) _guard: GenericPeripheralGuard<{ system::Peripheral::LcdCam as u8 }>, } /// Represents the camera interface with DMA support. pub struct Camera<'d> { lcd_cam: PeripheralRef<'d, LCD_CAM>, rx_channel: ChannelRx<'d, Blocking, ::Dma>, + _guard: GenericPeripheralGuard<{ system::Peripheral::LcdCam as u8 }>, } impl<'d> Camera<'d> { @@ -187,6 +190,7 @@ impl<'d> Camera<'d> { Self { lcd_cam, rx_channel: channel.degrade(), + _guard: cam._guard, } } } diff --git a/esp-hal/src/lcd_cam/lcd/mod.rs b/esp-hal/src/lcd_cam/lcd/mod.rs index 7727400fa..66bd82a65 100644 --- a/esp-hal/src/lcd_cam/lcd/mod.rs +++ b/esp-hal/src/lcd_cam/lcd/mod.rs @@ -10,7 +10,12 @@ //! ## Implementation State //! - RGB is not supported yet -use crate::{peripheral::PeripheralRef, peripherals::LCD_CAM}; +use super::GenericPeripheralGuard; +use crate::{ + peripheral::PeripheralRef, + peripherals::LCD_CAM, + system::{self}, +}; pub mod dpi; pub mod i8080; @@ -22,6 +27,8 @@ pub struct Lcd<'d, DM: crate::Mode> { /// A marker for the mode of operation (blocking or asynchronous). pub(crate) _mode: core::marker::PhantomData, + + pub(super) _guard: GenericPeripheralGuard<{ system::Peripheral::LcdCam as u8 }>, } #[derive(Debug, Clone, Copy, PartialEq, Default)] diff --git a/esp-hal/src/lcd_cam/mod.rs b/esp-hal/src/lcd_cam/mod.rs index b442b2450..7e22c2299 100644 --- a/esp-hal/src/lcd_cam/mod.rs +++ b/esp-hal/src/lcd_cam/mod.rs @@ -18,7 +18,7 @@ use crate::{ macros::handler, peripheral::Peripheral, peripherals::{Interrupt, LCD_CAM}, - system::{self, PeripheralClockControl}, + system::GenericPeripheralGuard, Async, Blocking, Cpu, @@ -38,15 +38,19 @@ impl<'d> LcdCam<'d, Blocking> { pub fn new(lcd_cam: impl Peripheral

+ 'd) -> Self { crate::into_ref!(lcd_cam); - PeripheralClockControl::reset(system::Peripheral::LcdCam); - PeripheralClockControl::enable(system::Peripheral::LcdCam); + let lcd_guard = GenericPeripheralGuard::new(); + let cam_guard = GenericPeripheralGuard::new(); Self { lcd: Lcd { lcd_cam: unsafe { lcd_cam.clone_unchecked() }, _mode: PhantomData, + _guard: lcd_guard, + }, + cam: Cam { + lcd_cam, + _guard: cam_guard, }, - cam: Cam { lcd_cam }, } } @@ -57,6 +61,7 @@ impl<'d> LcdCam<'d, Blocking> { lcd: Lcd { lcd_cam: self.lcd.lcd_cam, _mode: PhantomData, + _guard: self.lcd._guard, }, cam: self.cam, } @@ -87,6 +92,7 @@ impl<'d> LcdCam<'d, Async> { lcd: Lcd { lcd_cam: self.lcd.lcd_cam, _mode: PhantomData, + _guard: self.lcd._guard, }, cam: self.cam, } diff --git a/esp-hal/src/ledc/mod.rs b/esp-hal/src/ledc/mod.rs index 98b95ff72..1c4b5c58c 100644 --- a/esp-hal/src/ledc/mod.rs +++ b/esp-hal/src/ledc/mod.rs @@ -111,8 +111,9 @@ impl<'d> Ledc<'d> { pub fn new(_instance: impl Peripheral

+ 'd) -> Self { crate::into_ref!(_instance); - PeripheralClockControl::reset(PeripheralEnable::Ledc); - PeripheralClockControl::enable(PeripheralEnable::Ledc); + if PeripheralClockControl::enable(PeripheralEnable::Ledc) { + PeripheralClockControl::reset(PeripheralEnable::Ledc); + } let ledc = unsafe { &*crate::peripherals::LEDC::ptr() }; Ledc { _instance, ledc } diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 755f02b1e..c9fd6b643 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -515,6 +515,8 @@ pub struct Config { /// This function sets up the CPU clock and watchdog, then, returns the /// peripherals and clocks. pub fn init(config: Config) -> Peripherals { + system::disable_peripherals(); + let mut peripherals = Peripherals::take(); // RTC domain must be enabled before we try to disable diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index dc981794a..f61f7035e 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -94,7 +94,7 @@ use crate::{ clock::Clocks, gpio::OutputSignal, peripheral::{Peripheral, PeripheralRef}, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, + system::{self, PeripheralGuard}, }; /// MCPWM operators @@ -115,11 +115,12 @@ pub struct McPwm<'d, PWM> { /// Timer2 pub timer2: Timer<2, PWM>, /// Operator0 - pub operator0: Operator<0, PWM>, + pub operator0: Operator<'d, 0, PWM>, /// Operator1 - pub operator1: Operator<1, PWM>, + pub operator1: Operator<'d, 1, PWM>, /// Operator2 - pub operator2: Operator<2, PWM>, + pub operator2: Operator<'d, 2, PWM>, + _guard: PeripheralGuard, } impl<'d, PWM: PwmPeripheral> McPwm<'d, PWM> { @@ -131,8 +132,7 @@ impl<'d, PWM: PwmPeripheral> McPwm<'d, PWM> { ) -> Self { crate::into_ref!(peripheral); - PWM::reset(); - PWM::enable(); + let guard = PeripheralGuard::new(PWM::peripheral()); #[cfg(not(esp32c6))] { @@ -181,6 +181,7 @@ impl<'d, PWM: PwmPeripheral> McPwm<'d, PWM> { operator0: Operator::new(), operator1: Operator::new(), operator2: Operator::new(), + _guard: guard, } } } @@ -313,26 +314,16 @@ pub struct FrequencyError; /// A MCPWM peripheral pub trait PwmPeripheral: Deref + crate::private::Sealed { - /// Enable peripheral - fn enable(); - /// Reset peripheral - fn reset(); /// Get a pointer to the peripheral RegisterBlock fn block() -> *const RegisterBlock; /// Get operator GPIO mux output signal fn output_signal() -> OutputSignal; + /// Peripheral + fn peripheral() -> system::Peripheral; } #[cfg(mcpwm0)] impl PwmPeripheral for crate::peripherals::MCPWM0 { - fn enable() { - PeripheralClockControl::enable(PeripheralEnable::Mcpwm0) - } - - fn reset() { - PeripheralClockControl::reset(PeripheralEnable::Mcpwm0) - } - fn block() -> *const RegisterBlock { Self::PTR } @@ -348,18 +339,14 @@ impl PwmPeripheral for crate::peripherals::MCPWM0 { _ => unreachable!(), } } + + fn peripheral() -> system::Peripheral { + system::Peripheral::Mcpwm0 + } } #[cfg(mcpwm1)] impl PwmPeripheral for crate::peripherals::MCPWM1 { - fn enable() { - PeripheralClockControl::enable(PeripheralEnable::Mcpwm1) - } - - fn reset() { - PeripheralClockControl::reset(PeripheralEnable::Mcpwm1) - } - fn block() -> *const RegisterBlock { Self::PTR } @@ -375,4 +362,8 @@ impl PwmPeripheral for crate::peripherals::MCPWM1 { _ => unreachable!(), } } + + fn peripheral() -> system::Peripheral { + system::Peripheral::Mcpwm1 + } } diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 8c99ee03e..98441048e 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -11,6 +11,7 @@ use core::marker::PhantomData; +use super::PeripheralGuard; use crate::{ gpio::interconnect::{OutputConnection, PeripheralOutput}, mcpwm::{timer::Timer, PwmPeripheral}, @@ -167,12 +168,15 @@ impl DeadTimeCfg { /// * Superimposes a carrier on the PWM signal, if configured to do so. (Not yet /// implemented) /// * Handles response under fault conditions. (Not yet implemented) -pub struct Operator { - phantom: PhantomData, +pub struct Operator<'d, const OP: u8, PWM> { + phantom: PhantomData<&'d PWM>, + _guard: PeripheralGuard, } -impl Operator { +impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> { pub(super) fn new() -> Self { + let guard = PeripheralGuard::new(PWM::peripheral()); + // Side note: // It would have been nice to deselect any timer reference on peripheral // initialization. @@ -181,6 +185,7 @@ impl Operator { // written. Operator { phantom: PhantomData, + _guard: guard, } } @@ -204,7 +209,7 @@ impl Operator { } /// Use the A output with the given pin and configuration - pub fn with_pin_a<'d>( + pub fn with_pin_a( self, pin: impl Peripheral

+ 'd, config: PwmPinConfig, @@ -213,7 +218,7 @@ impl Operator { } /// Use the B output with the given pin and configuration - pub fn with_pin_b<'d>( + pub fn with_pin_b( self, pin: impl Peripheral

+ 'd, config: PwmPinConfig, @@ -222,7 +227,7 @@ impl Operator { } /// Use both the A and the B output with the given pins and configurations - pub fn with_pins<'d>( + pub fn with_pins( self, pin_a: impl Peripheral

+ 'd, config_a: PwmPinConfig, @@ -236,7 +241,7 @@ impl Operator { /// /// This is useful for complementary or mirrored signals with or without /// configured deadtime - pub fn with_linked_pins<'d>( + pub fn with_linked_pins( self, pin_a: impl Peripheral

+ 'd, config_a: PwmPinConfig, @@ -283,6 +288,7 @@ impl PwmPinConfig { pub struct PwmPin<'d, PWM, const OP: u8, const IS_A: bool> { pin: PeripheralRef<'d, OutputConnection>, phantom: PhantomData, + _guard: PeripheralGuard, } impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A> { @@ -291,9 +297,13 @@ impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, config: PwmPinConfig, ) -> Self { crate::into_mapped_ref!(pin); + + let guard = PeripheralGuard::new(PWM::peripheral()); + let mut pin = PwmPin { pin, phantom: PhantomData, + _guard: guard, }; pin.set_actions(config.actions); pin.set_update_method(config.update_method); diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 5afe5a374..b4c31b584 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -8,6 +8,7 @@ use core::marker::PhantomData; use fugit::HertzU32; +use super::PeripheralGuard; use crate::mcpwm::{FrequencyError, PeripheralClockConfig, PwmPeripheral}; /// A MCPWM timer @@ -17,12 +18,15 @@ use crate::mcpwm::{FrequencyError, PeripheralClockConfig, PwmPeripheral}; /// [`Operator`](super::operator::Operator) of that peripheral pub struct Timer { pub(super) phantom: PhantomData, + _guard: PeripheralGuard, } impl Timer { pub(super) fn new() -> Self { + let guard = PeripheralGuard::new(PWM::peripheral()); Timer { phantom: PhantomData, + _guard: guard, } } diff --git a/esp-hal/src/otg_fs.rs b/esp-hal/src/otg_fs.rs index 97e0d246f..6b680b502 100644 --- a/esp-hal/src/otg_fs.rs +++ b/esp-hal/src/otg_fs.rs @@ -43,7 +43,7 @@ use crate::{ gpio::InputSignal, peripheral::{Peripheral, PeripheralRef}, peripherals, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, + system::{GenericPeripheralGuard, Peripheral as PeripheralEnable}, }; #[doc(hidden)] @@ -57,6 +57,7 @@ pub trait UsbDm: crate::private::Sealed {} /// USB peripheral. pub struct Usb<'d> { _usb0: PeripheralRef<'d, peripherals::USB0>, + _guard: GenericPeripheralGuard<{ PeripheralEnable::Usb as u8 }>, } impl<'d> Usb<'d> { @@ -70,11 +71,11 @@ impl<'d> Usb<'d> { P: UsbDp + Send + Sync, M: UsbDm + Send + Sync, { - PeripheralClockControl::reset(PeripheralEnable::Usb); - PeripheralClockControl::enable(PeripheralEnable::Usb); + let guard = GenericPeripheralGuard::new(); Self { _usb0: usb0.into_ref(), + _guard: guard, } } diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 1b81ca290..e2badab61 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -54,7 +54,7 @@ use crate::{ interrupt::InterruptHandler, peripheral::{self, Peripheral}, peripherals::{self, Interrupt, PARL_IO}, - system::PeripheralClockControl, + system::{self, GenericPeripheralGuard}, Async, Blocking, InterruptConfigurable, @@ -767,6 +767,7 @@ where Ok(ParlIoTx { tx_channel: self.tx_channel, tx_chain: DescriptorChain::new(self.descriptors), + _guard: self._guard, }) } } @@ -798,6 +799,7 @@ where Ok(ParlIoTx { tx_channel: self.tx_channel, tx_chain: DescriptorChain::new(self.descriptors), + _guard: self._guard, }) } } @@ -809,6 +811,7 @@ where { tx_channel: ChannelTx<'d, DM, ::Dma>, tx_chain: DescriptorChain, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::ParlIo as u8 }>, } impl core::fmt::Debug for ParlIoTx<'_, DM> @@ -836,6 +839,8 @@ where P: FullDuplex + RxPins + ConfigurePins, CP: RxClkPin, { + let guard = GenericPeripheralGuard::new(); + rx_pins.configure()?; clk_pin.configure(); @@ -845,6 +850,7 @@ where Ok(ParlIoRx { rx_channel: self.rx_channel, rx_chain: DescriptorChain::new(self.descriptors), + _guard: guard, }) } } @@ -874,6 +880,7 @@ where Ok(ParlIoRx { rx_channel: self.rx_channel, rx_chain: DescriptorChain::new(self.descriptors), + _guard: self._guard, }) } } @@ -885,6 +892,7 @@ where { rx_channel: ChannelRx<'d, DM, ::Dma>, rx_chain: DescriptorChain, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::ParlIo as u8 }>, } impl core::fmt::Debug for ParlIoRx<'_, DM> @@ -1007,6 +1015,8 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> { CH: DmaChannelConvert<::Dma>, Channel<'d, Blocking, CH>: From>, { + let tx_guard = GenericPeripheralGuard::new(); + let rx_guard = GenericPeripheralGuard::new(); let dma_channel = Channel::::from(dma_channel); internal_init(frequency)?; @@ -1014,10 +1024,12 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> { tx: TxCreatorFullDuplex { tx_channel: dma_channel.tx.degrade(), descriptors: tx_descriptors, + _guard: tx_guard, }, rx: RxCreatorFullDuplex { rx_channel: dma_channel.rx.degrade(), descriptors: rx_descriptors, + _guard: rx_guard, }, }) } @@ -1028,10 +1040,12 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> { tx: TxCreatorFullDuplex { tx_channel: self.tx.tx_channel.into_async(), descriptors: self.tx.descriptors, + _guard: self.tx._guard, }, rx: RxCreatorFullDuplex { rx_channel: self.rx.rx_channel.into_async(), descriptors: self.rx.descriptors, + _guard: self.rx._guard, }, } } @@ -1080,10 +1094,12 @@ impl<'d> ParlIoFullDuplex<'d, Async> { tx: TxCreatorFullDuplex { tx_channel: self.tx.tx_channel.into_blocking(), descriptors: self.tx.descriptors, + _guard: self.tx._guard, }, rx: RxCreatorFullDuplex { rx_channel: self.rx.rx_channel.into_blocking(), descriptors: self.rx.descriptors, + _guard: self.rx._guard, }, } } @@ -1114,12 +1130,14 @@ where where CH: DmaChannelConvert<::Dma>, { + let guard = GenericPeripheralGuard::new(); internal_init(frequency)?; Ok(Self { tx: TxCreator { tx_channel: dma_channel.tx.degrade(), descriptors, + _guard: guard, }, }) } @@ -1188,12 +1206,14 @@ where where CH: DmaChannelConvert<::Dma>, { + let guard = GenericPeripheralGuard::new(); internal_init(frequency)?; Ok(Self { rx: RxCreator { rx_channel: dma_channel.rx.degrade(), descriptors, + _guard: guard, }, }) } @@ -1242,9 +1262,6 @@ fn internal_init(frequency: HertzU32) -> Result<(), Error> { return Err(Error::UnreachableClockRate); } - PeripheralClockControl::reset(crate::system::Peripheral::ParlIo); - PeripheralClockControl::enable(crate::system::Peripheral::ParlIo); - let pcr = unsafe { &*crate::peripherals::PCR::PTR }; let divider = crate::soc::constants::PARL_IO_SCLK / frequency.raw(); @@ -1458,6 +1475,7 @@ where { tx_channel: ChannelTx<'d, DM, ::Dma>, descriptors: &'static mut [DmaDescriptor], + _guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>, } /// Creates a RX channel @@ -1467,6 +1485,7 @@ where { rx_channel: ChannelRx<'d, DM, ::Dma>, descriptors: &'static mut [DmaDescriptor], + _guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>, } /// Creates a TX channel @@ -1476,6 +1495,7 @@ where { tx_channel: ChannelTx<'d, DM, ::Dma>, descriptors: &'static mut [DmaDescriptor], + _guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>, } /// Creates a RX channel @@ -1485,6 +1505,7 @@ where { rx_channel: ChannelRx<'d, DM, ::Dma>, descriptors: &'static mut [DmaDescriptor], + _guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>, } #[doc(hidden)] diff --git a/esp-hal/src/pcnt/channel.rs b/esp-hal/src/pcnt/channel.rs index c1c565b38..677c792f6 100644 --- a/esp-hal/src/pcnt/channel.rs +++ b/esp-hal/src/pcnt/channel.rs @@ -13,6 +13,7 @@ pub use crate::peripherals::pcnt::unit::conf0::{CTRL_MODE as CtrlMode, EDGE_MODE use crate::{ gpio::{interconnect::PeripheralInput, InputSignal}, peripheral::Peripheral, + system::GenericPeripheralGuard, }; /// Represents a channel within a pulse counter unit. @@ -20,14 +21,18 @@ pub struct Channel<'d, const UNIT: usize, const NUM: usize> { _phantom: PhantomData<&'d ()>, // Individual channels are not Send, since they share registers. _not_send: PhantomData<*const ()>, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Pcnt as u8 }>, } impl Channel<'_, UNIT, NUM> { /// return a new Channel pub(super) fn new() -> Self { + let guard = GenericPeripheralGuard::new(); + Self { _phantom: PhantomData, _not_send: PhantomData, + _guard: guard, } } diff --git a/esp-hal/src/pcnt/mod.rs b/esp-hal/src/pcnt/mod.rs index 742404b3f..e0072619a 100644 --- a/esp-hal/src/pcnt/mod.rs +++ b/esp-hal/src/pcnt/mod.rs @@ -25,7 +25,7 @@ use crate::{ interrupt::{self, InterruptHandler}, peripheral::{Peripheral, PeripheralRef}, peripherals::{self, Interrupt}, - system::PeripheralClockControl, + system::GenericPeripheralGuard, InterruptConfigurable, }; @@ -56,6 +56,8 @@ pub struct Pcnt<'d> { #[cfg(esp32)] /// Unit 7 pub unit7: Unit<'d, 7>, + + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Pcnt as u8 }>, } impl<'d> Pcnt<'d> { @@ -63,10 +65,7 @@ impl<'d> Pcnt<'d> { pub fn new(_instance: impl Peripheral

+ 'd) -> Self { crate::into_ref!(_instance); - // Enable the PCNT peripherals clock in the system peripheral - PeripheralClockControl::reset(crate::system::Peripheral::Pcnt); - PeripheralClockControl::enable(crate::system::Peripheral::Pcnt); - + let guard = GenericPeripheralGuard::new(); let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; // disable filter, all events, and channel settings @@ -105,6 +104,7 @@ impl<'d> Pcnt<'d> { unit6: Unit::new(), #[cfg(esp32)] unit7: Unit::new(), + _guard: guard, } } } diff --git a/esp-hal/src/pcnt/unit.rs b/esp-hal/src/pcnt/unit.rs index fb1a0cf49..ee3d3584a 100644 --- a/esp-hal/src/pcnt/unit.rs +++ b/esp-hal/src/pcnt/unit.rs @@ -13,7 +13,7 @@ use core::marker::PhantomData; use critical_section::CriticalSection; -use crate::pcnt::channel::Channel; +use crate::{pcnt::channel::Channel, system::GenericPeripheralGuard}; /// Invalid filter threshold value #[derive(Debug, Clone, Copy, PartialEq)] @@ -82,15 +82,20 @@ pub struct Unit<'d, const NUM: usize> { pub channel0: Channel<'d, NUM, 0>, /// The second channel in PCNT unit. pub channel1: Channel<'d, NUM, 1>, + + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Pcnt as u8 }>, } impl Unit<'_, NUM> { /// return a new Unit pub(super) fn new() -> Self { + let guard = GenericPeripheralGuard::new(); + Self { counter: Counter::new(), channel0: Channel::new(), channel1: Channel::new(), + _guard: guard, } } diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs index f1c0975e6..1cb83b368 100644 --- a/esp-hal/src/rmt.rs +++ b/esp-hal/src/rmt.rs @@ -94,7 +94,7 @@ use crate::{ peripheral::Peripheral, peripherals::Interrupt, soc::constants, - system::PeripheralClockControl, + system::{self, GenericPeripheralGuard}, Async, Blocking, InterruptConfigurable, @@ -228,9 +228,6 @@ where return Err(Error::UnreachableTargetFrequency); } - PeripheralClockControl::reset(crate::system::Peripheral::Rmt); - PeripheralClockControl::enable(crate::system::Peripheral::Rmt); - cfg_if::cfg_if! { if #[cfg(any(esp32, esp32s2))] { self::chip_specific::configure_clock(); @@ -603,7 +600,10 @@ macro_rules! impl_rx_channel_creator { mod impl_for_chip { use core::marker::PhantomData; - use crate::peripheral::{Peripheral, PeripheralRef}; + use crate::{ + peripheral::{Peripheral, PeripheralRef}, + system::GenericPeripheralGuard, + }; /// RMT Instance pub struct Rmt<'d, M> @@ -635,15 +635,19 @@ mod impl_for_chip { peripheral, channel0: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel1: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel2: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel3: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, phantom: PhantomData, } @@ -656,6 +660,7 @@ mod impl_for_chip { M: crate::Mode, { phantom: PhantomData, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Rmt as u8 }>, } impl_tx_channel_creator!(0); @@ -675,7 +680,10 @@ mod impl_for_chip { mod impl_for_chip { use core::marker::PhantomData; - use crate::peripheral::{Peripheral, PeripheralRef}; + use crate::{ + peripheral::{Peripheral, PeripheralRef}, + system::GenericPeripheralGuard, + }; /// RMT Instance pub struct Rmt<'d, M> @@ -710,32 +718,39 @@ mod impl_for_chip { peripheral: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(peripheral); - Self { peripheral, channel0: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel1: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel2: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel3: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel4: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel5: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel6: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel7: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, phantom: PhantomData, } @@ -748,6 +763,7 @@ mod impl_for_chip { M: crate::Mode, { phantom: PhantomData, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Rmt as u8 }>, } impl_tx_channel_creator!(0); @@ -791,7 +807,10 @@ mod impl_for_chip { mod impl_for_chip { use core::marker::PhantomData; - use crate::peripheral::{Peripheral, PeripheralRef}; + use crate::{ + peripheral::{Peripheral, PeripheralRef}, + system::GenericPeripheralGuard, + }; /// RMT Instance pub struct Rmt<'d, M> @@ -823,15 +842,19 @@ mod impl_for_chip { peripheral, channel0: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel1: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel2: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel3: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, phantom: PhantomData, } @@ -844,6 +867,7 @@ mod impl_for_chip { M: crate::Mode, { phantom: PhantomData, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Rmt as u8 }>, } impl_tx_channel_creator!(0); @@ -871,7 +895,10 @@ mod impl_for_chip { mod impl_for_chip { use core::marker::PhantomData; - use crate::peripheral::{Peripheral, PeripheralRef}; + use crate::{ + peripheral::{Peripheral, PeripheralRef}, + system::GenericPeripheralGuard, + }; /// RMT Instance pub struct Rmt<'d, M> @@ -911,27 +938,35 @@ mod impl_for_chip { peripheral, channel0: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel1: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel2: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel3: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel4: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel5: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel6: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, channel7: ChannelCreator { phantom: PhantomData, + _guard: GenericPeripheralGuard::new(), }, phantom: PhantomData, } @@ -944,6 +979,7 @@ mod impl_for_chip { M: crate::Mode, { phantom: PhantomData, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Rmt as u8 }>, } impl_tx_channel_creator!(0); @@ -968,13 +1004,14 @@ mod impl_for_chip { } /// RMT Channel -#[non_exhaustive] #[derive(Debug)] +#[non_exhaustive] pub struct Channel where M: crate::Mode, { phantom: PhantomData, + _guard: GenericPeripheralGuard<{ system::Peripheral::Rmt as u8 }>, } /// Channel in TX mode @@ -1594,8 +1631,10 @@ mod chip_specific { const CHANNEL: u8 = $ch_num; fn new() -> Self { + let guard = GenericPeripheralGuard::new(); Self { phantom: core::marker::PhantomData, + _guard: guard, } } @@ -1755,8 +1794,10 @@ mod chip_specific { const CHANNEL: u8 = $ch_num; fn new() -> Self { + let guard = GenericPeripheralGuard::new(); Self { phantom: core::marker::PhantomData, + _guard: guard, } } @@ -1944,8 +1985,10 @@ mod chip_specific { const CHANNEL: u8 = $ch_num; fn new() -> Self { + let guard = GenericPeripheralGuard::new(); Self { phantom: core::marker::PhantomData, + _guard: guard, } } @@ -2095,8 +2138,10 @@ mod chip_specific { const CHANNEL: u8 = $ch_num; fn new() -> Self { + let guard = GenericPeripheralGuard::new(); Self { phantom: core::marker::PhantomData, + _guard: guard, } } diff --git a/esp-hal/src/rsa/mod.rs b/esp-hal/src/rsa/mod.rs index cde24f4e8..673458945 100644 --- a/esp-hal/src/rsa/mod.rs +++ b/esp-hal/src/rsa/mod.rs @@ -27,7 +27,7 @@ use crate::{ interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::{Interrupt, RSA}, - system::{Peripheral as PeripheralEnable, PeripheralClockControl}, + system::{GenericPeripheralGuard, Peripheral as PeripheralEnable}, Async, Blocking, Cpu, @@ -48,6 +48,7 @@ pub use rsa_spec_impl::operand_sizes; pub struct Rsa<'d, DM: crate::Mode> { rsa: PeripheralRef<'d, RSA>, phantom: PhantomData, + _guard: GenericPeripheralGuard<{ PeripheralEnable::Rsa as u8 }>, } impl<'d> Rsa<'d, Blocking> { @@ -64,6 +65,7 @@ impl<'d> Rsa<'d, Blocking> { Rsa { rsa: self.rsa, phantom: PhantomData, + _guard: self._guard, } } } @@ -87,6 +89,7 @@ impl<'d> Rsa<'d, Async> { Rsa { rsa: self.rsa, phantom: PhantomData, + _guard: self._guard, } } } @@ -95,12 +98,12 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { fn new_internal(rsa: impl Peripheral

+ 'd) -> Self { crate::into_ref!(rsa); - PeripheralClockControl::reset(PeripheralEnable::Rsa); - PeripheralClockControl::enable(PeripheralEnable::Rsa); + let guard = GenericPeripheralGuard::new(); Self { rsa, phantom: PhantomData, + _guard: guard, } } diff --git a/esp-hal/src/sha.rs b/esp-hal/src/sha.rs index 48e852276..91526b09c 100644 --- a/esp-hal/src/sha.rs +++ b/esp-hal/src/sha.rs @@ -68,23 +68,22 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::SHA, reg_access::{AlignmentHelper, SocDependentEndianess}, - system::PeripheralClockControl, + system::GenericPeripheralGuard, }; /// The SHA Accelerator driver instance pub struct Sha<'d> { sha: PeripheralRef<'d, SHA>, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Sha as u8 }>, } impl<'d> Sha<'d> { /// Create a new instance of the SHA Accelerator driver. pub fn new(sha: impl Peripheral

+ 'd) -> Self { crate::into_ref!(sha); + let guard = GenericPeripheralGuard::new(); - PeripheralClockControl::reset(crate::system::Peripheral::Sha); - PeripheralClockControl::enable(crate::system::Peripheral::Sha); - - Self { sha } + Self { sha, _guard: guard } } /// Start a new digest. diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 2bc93c5d6..b850dabe6 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -85,7 +85,7 @@ use crate::{ peripherals::spi2::RegisterBlock, private, spi::AnySpi, - system::PeripheralClockControl, + system::PeripheralGuard, Async, Blocking, Mode, @@ -462,6 +462,7 @@ pub enum ConfigError {} pub struct Spi<'d, M, T = AnySpi> { spi: PeripheralRef<'d, T>, _mode: PhantomData, + guard: PeripheralGuard, } impl<'d, M, T> Spi<'d, M, T> @@ -543,6 +544,7 @@ impl<'d> Spi<'d, Blocking> { Spi { spi: self.spi, _mode: PhantomData, + guard: self.guard, } } } @@ -553,6 +555,7 @@ impl<'d> Spi<'d, Async> { Spi { spi: self.spi, _mode: PhantomData, + guard: self.guard, } } } @@ -573,14 +576,14 @@ where ) -> Spi<'d, M, T> { crate::into_ref!(spi); + let guard = PeripheralGuard::new(spi.info().peripheral); + let mut this = Spi { spi, _mode: PhantomData, + guard, }; - PeripheralClockControl::enable(this.driver().peripheral); - PeripheralClockControl::reset(this.driver().peripheral); - this.driver().init(); unwrap!(this.apply_config(&config)); // FIXME: update based on the resolution of https://github.com/esp-rs/esp-hal/issues/2416 @@ -885,6 +888,7 @@ mod dma { rx_transfer_in_progress: bool, #[cfg(all(esp32, spi_address_workaround))] address_buffer: DmaTxBuf, + guard: PeripheralGuard, } impl crate::private::Sealed for SpiDma<'_, M, T> @@ -907,6 +911,7 @@ mod dma { rx_transfer_in_progress: self.rx_transfer_in_progress, #[cfg(all(esp32, spi_address_workaround))] address_buffer: self.address_buffer, + guard: self.guard, } } } @@ -924,6 +929,7 @@ mod dma { rx_transfer_in_progress: self.rx_transfer_in_progress, #[cfg(all(esp32, spi_address_workaround))] address_buffer: self.address_buffer, + guard: self.guard, } } } @@ -1015,6 +1021,8 @@ mod dma { )) }; + let guard = PeripheralGuard::new(spi.info().peripheral); + Self { spi, channel: channel.degrade(), @@ -1022,6 +1030,7 @@ mod dma { address_buffer, tx_transfer_in_progress: false, rx_transfer_in_progress: false, + guard, } } diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 7e00288f4..576f8cd95 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -88,7 +88,7 @@ use crate::{ peripherals::spi2::RegisterBlock, private, spi::AnySpi, - system::PeripheralClockControl, + system::PeripheralGuard, Blocking, }; @@ -102,6 +102,7 @@ pub struct Spi<'d, M, T = AnySpi> { #[allow(dead_code)] data_mode: SpiMode, _mode: PhantomData, + _guard: PeripheralGuard, } impl<'d> Spi<'d, Blocking> { @@ -119,15 +120,15 @@ where pub fn new_typed(spi: impl Peripheral

+ 'd, mode: SpiMode) -> Spi<'d, M, T> { crate::into_ref!(spi); + let guard = PeripheralGuard::new(spi.info().peripheral); + let this = Spi { spi, data_mode: mode, _mode: PhantomData, + _guard: guard, }; - PeripheralClockControl::reset(this.spi.info().peripheral); - PeripheralClockControl::enable(this.spi.info().peripheral); - this.spi.info().init(); this.spi.info().set_data_mode(mode, false); @@ -226,6 +227,7 @@ pub mod dma { pub(crate) channel: Channel<'d, M, T::Dma>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, + _guard: PeripheralGuard, } impl core::fmt::Debug for SpiDma<'_, DmaMode, T> @@ -304,11 +306,14 @@ pub mod dma { CH: DmaChannelConvert, { channel.runtime_ensure_compatible(&spi); + let guard = PeripheralGuard::new(spi.info().peripheral); + Self { spi, channel: channel.degrade(), rx_chain: DescriptorChain::new(rx_descriptors), tx_chain: DescriptorChain::new(tx_descriptors), + _guard: guard, } } diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index 0406d89d0..40f0a69b3 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -5,8 +5,23 @@ //! This `system` module defines the available radio peripherals and provides an //! interface to control and configure radio clocks. +use core::sync::atomic::Ordering; + +use critical_section::CriticalSection; +use portable_atomic::AtomicUsize; +use strum::{EnumCount, EnumIter, IntoEnumIterator}; + use crate::peripherals::SYSTEM; +pub(crate) const KEEP_ENABLED: &[Peripheral] = &[ + Peripheral::Uart0, + #[cfg(usb_device)] + Peripheral::UsbDevice, + #[cfg(systimer)] + Peripheral::Systimer, + Peripheral::Timg0, +]; + /// Peripherals which can be enabled via `PeripheralClockControl`. /// /// This enum represents various hardware peripherals that can be enabled @@ -15,7 +30,8 @@ use crate::peripherals::SYSTEM; // FIXME: This enum needs to be public because it's exposed via a bunch of traits, but it's not // useful to users. #[doc(hidden)] -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, EnumCount, EnumIter)] +#[repr(u8)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Peripheral { /// SPI2 peripheral. @@ -78,9 +94,6 @@ pub enum Peripheral { /// Timer Group 1 peripheral. #[cfg(timg1)] Timg1, - /// Low-power watchdog timer (WDT) peripheral. - #[cfg(lp_wdt)] - Wdt, /// SHA peripheral (Secure Hash Algorithm). #[cfg(sha)] Sha, @@ -122,234 +135,256 @@ pub enum Peripheral { Systimer, } +impl Peripheral { + pub fn try_from(value: u8) -> Option { + if value >= Peripheral::COUNT as u8 { + return None; + } + + Some(unsafe { core::mem::transmute::(value) }) + } +} + +static PERIPHERAL_REF_COUNT: [AtomicUsize; Peripheral::COUNT] = + [const { AtomicUsize::new(0) }; Peripheral::COUNT]; + +/// Disable all peripherals. +/// +/// Peripherals listed in [KEEP_ENABLED] are NOT disabled. +pub(crate) fn disable_peripherals() { + for p in Peripheral::iter() { + if KEEP_ENABLED.contains(&p) { + continue; + } + PeripheralClockControl::enable_forced(p, false, true); + } +} + +#[derive(Debug)] +pub(crate) struct PeripheralGuard { + peripheral: Peripheral, +} + +impl PeripheralGuard { + pub(crate) fn new(p: Peripheral) -> Self { + if !KEEP_ENABLED.contains(&p) && PeripheralClockControl::enable(p) { + PeripheralClockControl::reset(p); + } + + Self { peripheral: p } + } +} + +impl Drop for PeripheralGuard { + fn drop(&mut self) { + if !KEEP_ENABLED.contains(&self.peripheral) { + PeripheralClockControl::disable(self.peripheral); + } + } +} + +#[derive(Debug)] +pub(crate) struct GenericPeripheralGuard {} + +impl GenericPeripheralGuard

{ + pub(crate) fn new() -> Self { + let peripheral = unwrap!(Peripheral::try_from(P)); + if !KEEP_ENABLED.contains(&peripheral) && PeripheralClockControl::enable(peripheral) { + PeripheralClockControl::reset(peripheral); + } + + Self {} + } +} + +impl Drop for GenericPeripheralGuard

{ + fn drop(&mut self) { + let peripheral = unwrap!(Peripheral::try_from(P)); + if !KEEP_ENABLED.contains(&peripheral) { + PeripheralClockControl::disable(peripheral); + } + } +} + /// Controls the enablement of peripheral clocks. pub(crate) struct PeripheralClockControl; #[cfg(not(any(esp32c6, esp32h2)))] impl PeripheralClockControl { - /// Enables and resets the given peripheral - pub(crate) fn enable(peripheral: Peripheral) { + fn enable_internal(peripheral: Peripheral, enable: bool, _cs: &CriticalSection<'_>) { + debug!("Enable {:?} {}", peripheral, enable); + let system = unsafe { &*SYSTEM::PTR }; #[cfg(esp32)] - let (perip_clk_en0, perip_rst_en0, peri_clk_en, peri_rst_en) = { - ( - &system.perip_clk_en(), - &system.perip_rst_en(), - &system.peri_clk_en(), - &system.peri_rst_en(), - ) - }; + let (perip_clk_en0, peri_clk_en) = { (&system.perip_clk_en(), &system.peri_clk_en()) }; #[cfg(not(esp32))] - let (perip_clk_en0, perip_rst_en0) = { (&system.perip_clk_en0(), &system.perip_rst_en0()) }; + let perip_clk_en0 = &system.perip_clk_en0(); #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))] - let (perip_clk_en1, perip_rst_en1) = { (&system.perip_clk_en1(), &system.perip_rst_en1()) }; + let perip_clk_en1 = &system.perip_clk_en1(); - critical_section::with(|_cs| match peripheral { + match peripheral { #[cfg(spi2)] Peripheral::Spi2 => { - perip_clk_en0.modify(|_, w| w.spi2_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.spi2_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.spi2_clk_en().bit(enable)); } #[cfg(spi3)] Peripheral::Spi3 => { - perip_clk_en0.modify(|_, w| w.spi3_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.spi3_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.spi3_clk_en().bit(enable)); } #[cfg(all(i2c0, esp32))] Peripheral::I2cExt0 => { - perip_clk_en0.modify(|_, w| w.i2c0_ext0_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.i2c0_ext0_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.i2c0_ext0_clk_en().bit(enable)); } #[cfg(all(i2c0, not(esp32)))] Peripheral::I2cExt0 => { - perip_clk_en0.modify(|_, w| w.i2c_ext0_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.i2c_ext0_clk_en().bit(enable)); } #[cfg(i2c1)] Peripheral::I2cExt1 => { - perip_clk_en0.modify(|_, w| w.i2c_ext1_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.i2c_ext1_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.i2c_ext1_clk_en().bit(enable)); } #[cfg(rmt)] Peripheral::Rmt => { - perip_clk_en0.modify(|_, w| w.rmt_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.rmt_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.rmt_clk_en().bit(enable)); } #[cfg(ledc)] Peripheral::Ledc => { - perip_clk_en0.modify(|_, w| w.ledc_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.ledc_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.ledc_clk_en().bit(enable)); } #[cfg(mcpwm0)] Peripheral::Mcpwm0 => { - perip_clk_en0.modify(|_, w| w.pwm0_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.pwm0_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.pwm0_clk_en().bit(enable)); } #[cfg(mcpwm1)] Peripheral::Mcpwm1 => { - perip_clk_en0.modify(|_, w| w.pwm1_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.pwm1_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.pwm1_clk_en().bit(enable)); } #[cfg(pcnt)] Peripheral::Pcnt => { - perip_clk_en0.modify(|_, w| w.pcnt_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.pcnt_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.pcnt_clk_en().bit(enable)); } #[cfg(apb_saradc)] Peripheral::ApbSarAdc => { - perip_clk_en0.modify(|_, w| w.apb_saradc_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.apb_saradc_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.apb_saradc_clk_en().bit(enable)); } #[cfg(gdma)] Peripheral::Gdma => { - perip_clk_en1.modify(|_, w| w.dma_clk_en().set_bit()); - perip_rst_en1.modify(|_, w| w.dma_rst().clear_bit()); + perip_clk_en1.modify(|_, w| w.dma_clk_en().bit(enable)); } #[cfg(esp32)] Peripheral::Dma => { - perip_clk_en0.modify(|_, w| w.spi_dma_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.spi_dma_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.spi_dma_clk_en().bit(enable)); } #[cfg(esp32s2)] Peripheral::Dma => { - perip_clk_en0.modify(|_, w| w.spi2_dma_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.spi2_dma_rst().clear_bit()); - perip_clk_en0.modify(|_, w| w.spi3_dma_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.spi3_dma_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.spi2_dma_clk_en().bit(enable)); + perip_clk_en0.modify(|_, w| w.spi3_dma_clk_en().bit(enable)); } #[cfg(esp32c3)] Peripheral::I2s0 => { // on ESP32-C3 note that i2s1_clk_en / rst is really I2s0 - perip_clk_en0.modify(|_, w| w.i2s1_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.i2s1_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.i2s1_clk_en().bit(enable)); } #[cfg(any(esp32s3, esp32, esp32s2))] Peripheral::I2s0 => { - perip_clk_en0.modify(|_, w| w.i2s0_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.i2s0_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.i2s0_clk_en().bit(enable)); } #[cfg(any(esp32s3, esp32))] Peripheral::I2s1 => { - perip_clk_en0.modify(|_, w| w.i2s1_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.i2s1_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.i2s1_clk_en().bit(enable)); } #[cfg(usb0)] Peripheral::Usb => { - perip_clk_en0.modify(|_, w| w.usb_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.usb_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.usb_clk_en().bit(enable)); } #[cfg(twai0)] Peripheral::Twai0 => { - perip_clk_en0.modify(|_, w| w.twai_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.twai_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.twai_clk_en().bit(enable)); } #[cfg(esp32)] Peripheral::Aes => { - peri_clk_en.modify(|r, w| unsafe { w.bits(r.bits() | 1) }); - peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() & (!1)) }); + peri_clk_en.modify(|r, w| unsafe { w.bits(r.bits() | enable as u32) }); } #[cfg(any(esp32c3, esp32s2, esp32s3))] Peripheral::Aes => { - perip_clk_en1.modify(|_, w| w.crypto_aes_clk_en().set_bit()); - perip_rst_en1.modify(|_, w| w.crypto_aes_rst().clear_bit()); + perip_clk_en1.modify(|_, w| w.crypto_aes_clk_en().bit(enable)); } #[cfg(timg0)] Peripheral::Timg0 => { #[cfg(any(esp32c3, esp32s2, esp32s3))] - perip_clk_en0.modify(|_, w| w.timers_clk_en().set_bit()); - perip_clk_en0.modify(|_, w| w.timergroup_clk_en().set_bit()); - - #[cfg(any(esp32c3, esp32s2, esp32s3))] - perip_rst_en0.modify(|_, w| w.timers_rst().clear_bit()); - perip_rst_en0.modify(|_, w| w.timergroup_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.timers_clk_en().bit(enable)); + perip_clk_en0.modify(|_, w| w.timergroup_clk_en().bit(enable)); } #[cfg(timg1)] Peripheral::Timg1 => { #[cfg(any(esp32c3, esp32s2, esp32s3))] - perip_clk_en0.modify(|_, w| w.timers_clk_en().set_bit()); - perip_clk_en0.modify(|_, w| w.timergroup1_clk_en().set_bit()); - - #[cfg(any(esp32c3, esp32s2, esp32s3))] - perip_rst_en0.modify(|_, w| w.timers_rst().clear_bit()); - perip_rst_en0.modify(|_, w| w.timergroup1_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.timers_clk_en().bit(enable)); + perip_clk_en0.modify(|_, w| w.timergroup1_clk_en().bit(enable)); } #[cfg(sha)] Peripheral::Sha => { #[cfg(not(esp32))] - perip_clk_en1.modify(|_, w| w.crypto_sha_clk_en().set_bit()); - #[cfg(not(esp32))] - perip_rst_en1.modify(|_, w| w.crypto_sha_rst().clear_bit()); + perip_clk_en1.modify(|_, w| w.crypto_sha_clk_en().bit(enable)); } #[cfg(esp32c3)] Peripheral::UsbDevice => { - perip_clk_en0.modify(|_, w| w.usb_device_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.usb_device_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.usb_device_clk_en().bit(enable)); } #[cfg(esp32s3)] Peripheral::UsbDevice => { - perip_clk_en1.modify(|_, w| w.usb_device_clk_en().set_bit()); - perip_rst_en1.modify(|_, w| w.usb_device_rst().clear_bit()); + perip_clk_en1.modify(|_, w| w.usb_device_clk_en().bit(enable)); } #[cfg(uart0)] Peripheral::Uart0 => { - perip_clk_en0.modify(|_, w| w.uart_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.uart_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.uart_clk_en().bit(enable)); } #[cfg(uart1)] Peripheral::Uart1 => { - perip_clk_en0.modify(|_, w| w.uart1_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.uart1_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.uart1_clk_en().bit(enable)); } #[cfg(all(uart2, esp32s3))] Peripheral::Uart2 => { perip_clk_en1.modify(|_, w| w.uart2_clk_en().set_bit()); - perip_rst_en1.modify(|_, w| w.uart2_rst().clear_bit()); } #[cfg(all(uart2, esp32))] Peripheral::Uart2 => { - perip_clk_en0.modify(|_, w| w.uart2_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.uart2_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.uart2_clk_en().bit(enable)); } #[cfg(all(rsa, esp32))] Peripheral::Rsa => { - peri_clk_en.modify(|r, w| unsafe { w.bits(r.bits() | 1 << 2) }); - peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << 2)) }); + peri_clk_en.modify(|r, w| unsafe { w.bits(r.bits() | (enable as u32) << 2) }); } #[cfg(all(rsa, any(esp32c3, esp32s2, esp32s3)))] Peripheral::Rsa => { - perip_clk_en1.modify(|_, w| w.crypto_rsa_clk_en().set_bit()); - perip_rst_en1.modify(|_, w| w.crypto_rsa_rst().clear_bit()); + perip_clk_en1.modify(|_, w| w.crypto_rsa_clk_en().bit(enable)); system .rsa_pd_ctrl() - .modify(|_, w| w.rsa_mem_pd().clear_bit()); + .modify(|_, w| w.rsa_mem_pd().bit(!enable)); } #[cfg(hmac)] Peripheral::Hmac => { - perip_clk_en1.modify(|_, w| w.crypto_hmac_clk_en().set_bit()); - perip_rst_en1.modify(|_, w| w.crypto_hmac_rst().clear_bit()); + perip_clk_en1.modify(|_, w| w.crypto_hmac_clk_en().bit(enable)); } #[cfg(ecc)] Peripheral::Ecc => { - perip_clk_en1.modify(|_, w| w.crypto_ecc_clk_en().set_bit()); - perip_rst_en1.modify(|_, w| w.crypto_ecc_rst().clear_bit()); + perip_clk_en1.modify(|_, w| w.crypto_ecc_clk_en().bit(enable)); } #[cfg(lcd_cam)] Peripheral::LcdCam => { - perip_clk_en1.modify(|_, w| w.lcd_cam_clk_en().set_bit()); - perip_rst_en1.modify(|_, w| w.lcd_cam_rst().clear_bit()); + perip_clk_en1.modify(|_, w| w.lcd_cam_clk_en().bit(enable)); } #[cfg(systimer)] Peripheral::Systimer => { - perip_clk_en0.modify(|_, w| w.systimer_clk_en().set_bit()); - perip_rst_en0.modify(|_, w| w.systimer_rst().clear_bit()); + perip_clk_en0.modify(|_, w| w.systimer_clk_en().bit(enable)); } - }); + } } /// Resets the given peripheral pub(crate) fn reset(peripheral: Peripheral) { + debug!("Reset {:?}", peripheral); let system = unsafe { &*SYSTEM::PTR }; #[cfg(esp32)] @@ -560,176 +595,132 @@ impl PeripheralClockControl { #[cfg(any(esp32c6, esp32h2))] impl PeripheralClockControl { - /// Enables and resets the given peripheral - pub(crate) fn enable(peripheral: Peripheral) { + fn enable_internal(peripheral: Peripheral, enable: bool, _cs: &CriticalSection<'_>) { + debug!("Enable {:?} {}", peripheral, enable); let system = unsafe { &*SYSTEM::PTR }; match peripheral { #[cfg(spi2)] Peripheral::Spi2 => { - system.spi2_conf().modify(|_, w| w.spi2_clk_en().set_bit()); system .spi2_conf() - .modify(|_, w| w.spi2_rst_en().clear_bit()); + .modify(|_, w| w.spi2_clk_en().bit(enable)); } #[cfg(i2c0)] Peripheral::I2cExt0 => { - #[cfg(any(esp32c6, esp32h2))] - { - system.i2c0_conf().modify(|_, w| w.i2c0_clk_en().set_bit()); - system - .i2c0_conf() - .modify(|_, w| w.i2c0_rst_en().clear_bit()); - } + system + .i2c0_conf() + .modify(|_, w| w.i2c0_clk_en().bit(enable)); } #[cfg(i2c1)] Peripheral::I2cExt1 => { - #[cfg(esp32h2)] - { - system.i2c1_conf().modify(|_, w| w.i2c1_clk_en().set_bit()); - system - .i2c1_conf() - .modify(|_, w| w.i2c1_rst_en().clear_bit()); - } + system + .i2c1_conf() + .modify(|_, w| w.i2c1_clk_en().bit(enable)); } #[cfg(rmt)] Peripheral::Rmt => { - system.rmt_conf().modify(|_, w| w.rmt_clk_en().set_bit()); - system.rmt_conf().modify(|_, w| w.rmt_rst_en().clear_bit()); + system.rmt_conf().modify(|_, w| w.rmt_clk_en().bit(enable)); } #[cfg(ledc)] Peripheral::Ledc => { - system.ledc_conf().modify(|_, w| w.ledc_clk_en().set_bit()); system .ledc_conf() - .modify(|_, w| w.ledc_rst_en().clear_bit()); + .modify(|_, w| w.ledc_clk_en().bit(enable)); } #[cfg(mcpwm0)] Peripheral::Mcpwm0 => { - system.pwm_conf().modify(|_, w| w.pwm_clk_en().set_bit()); - system.pwm_conf().modify(|_, w| w.pwm_rst_en().clear_bit()); + system.pwm_conf().modify(|_, w| w.pwm_clk_en().bit(enable)); } #[cfg(mcpwm1)] Peripheral::Mcpwm1 => { - system.pwm_conf.modify(|_, w| w.pwm_clk_en().set_bit()); - system.pwm_conf.modify(|_, w| w.pwm_rst_en().clear_bit()); + system.pwm_conf.modify(|_, w| w.pwm_clk_en().bit(enable)); } #[cfg(apb_saradc)] Peripheral::ApbSarAdc => { system .saradc_conf() - .modify(|_, w| w.saradc_reg_clk_en().set_bit()); - system - .saradc_conf() - .modify(|_, w| w.saradc_reg_rst_en().clear_bit()); + .modify(|_, w| w.saradc_reg_clk_en().bit(enable)); } #[cfg(gdma)] Peripheral::Gdma => { - system.gdma_conf().modify(|_, w| w.gdma_clk_en().set_bit()); system .gdma_conf() - .modify(|_, w| w.gdma_rst_en().clear_bit()); + .modify(|_, w| w.gdma_clk_en().bit(enable)); } #[cfg(i2s0)] Peripheral::I2s0 => { - system.i2s_conf().modify(|_, w| w.i2s_clk_en().set_bit()); - system.i2s_conf().modify(|_, w| w.i2s_rst_en().clear_bit()); + system.i2s_conf().modify(|_, w| w.i2s_clk_en().bit(enable)); } #[cfg(twai0)] Peripheral::Twai0 => { system .twai0_conf() - .modify(|_, w| w.twai0_clk_en().set_bit()); - system - .twai0_conf() - .modify(|_, w| w.twai0_rst_en().clear_bit()); + .modify(|_, w| w.twai0_clk_en().bit(enable)); - // use Xtal clk-src - system.twai0_func_clk_conf().modify(|_, w| { - w.twai0_func_clk_en() - .set_bit() - .twai0_func_clk_sel() - .variant(false) - }); + if enable { + // use Xtal clk-src + system.twai0_func_clk_conf().modify(|_, w| { + w.twai0_func_clk_en() + .set_bit() + .twai0_func_clk_sel() + .variant(false) + }); + } } #[cfg(twai1)] Peripheral::Twai1 => { system .twai1_conf() - .modify(|_, w| w.twai1_clk_en().set_bit()); - system - .twai1_conf() - .modify(|_, w| w.twai1_rst_en().clear_bit()); + .modify(|_, w| w.twai1_clk_en().bit(enable)); } #[cfg(aes)] Peripheral::Aes => { - system.aes_conf().modify(|_, w| w.aes_clk_en().set_bit()); - system.aes_conf().modify(|_, w| w.aes_rst_en().clear_bit()); + system.aes_conf().modify(|_, w| w.aes_clk_en().bit(enable)); } #[cfg(pcnt)] Peripheral::Pcnt => { - system.pcnt_conf().modify(|_, w| w.pcnt_clk_en().set_bit()); system .pcnt_conf() - .modify(|_, w| w.pcnt_rst_en().clear_bit()); + .modify(|_, w| w.pcnt_clk_en().bit(enable)); } #[cfg(timg0)] Peripheral::Timg0 => { system .timergroup0_timer_clk_conf() - .modify(|_, w| w.tg0_timer_clk_en().set_bit()); + .modify(|_, w| w.tg0_timer_clk_en().bit(enable)); } #[cfg(timg1)] Peripheral::Timg1 => { system .timergroup1_timer_clk_conf() - .modify(|_, w| w.tg1_timer_clk_en().set_bit()); - } - #[cfg(lp_wdt)] - Peripheral::Wdt => { - system - .timergroup0_wdt_clk_conf() - .modify(|_, w| w.tg0_wdt_clk_en().set_bit()); - system - .timergroup1_timer_clk_conf() - .modify(|_, w| w.tg1_timer_clk_en().set_bit()); + .modify(|_, w| w.tg1_timer_clk_en().bit(enable)); } #[cfg(sha)] Peripheral::Sha => { - system.sha_conf().modify(|_, w| w.sha_clk_en().set_bit()); - system.sha_conf().modify(|_, w| w.sha_rst_en().clear_bit()); + system.sha_conf().modify(|_, w| w.sha_clk_en().bit(enable)); } #[cfg(usb_device)] Peripheral::UsbDevice => { system .usb_device_conf() - .modify(|_, w| w.usb_device_clk_en().set_bit()); - system - .usb_device_conf() - .modify(|_, w| w.usb_device_rst_en().clear_bit()); + .modify(|_, w| w.usb_device_clk_en().bit(enable)); } #[cfg(uart0)] Peripheral::Uart0 => { system .uart0_conf() - .modify(|_, w| w.uart0_clk_en().set_bit()); - system - .uart0_conf() - .modify(|_, w| w.uart0_rst_en().clear_bit()); + .modify(|_, w| w.uart0_clk_en().bit(enable)); } #[cfg(uart1)] Peripheral::Uart1 => { system .uart1_conf() - .modify(|_, w| w.uart1_clk_en().set_bit()); - system - .uart1_conf() - .modify(|_, w| w.uart1_rst_en().clear_bit()); + .modify(|_, w| w.uart1_clk_en().bit(enable)); } #[cfg(rsa)] Peripheral::Rsa => { - system.rsa_conf().modify(|_, w| w.rsa_clk_en().set_bit()); - system.rsa_conf().modify(|_, w| w.rsa_rst_en().clear_bit()); + system.rsa_conf().modify(|_, w| w.rsa_clk_en().bit(enable)); system .rsa_pd_ctrl() .modify(|_, w| w.rsa_mem_pd().clear_bit()); @@ -738,54 +729,41 @@ impl PeripheralClockControl { Peripheral::ParlIo => { system .parl_io_conf() - .modify(|_, w| w.parl_clk_en().set_bit()); - system - .parl_io_conf() - .modify(|_, w| w.parl_rst_en().set_bit()); - system - .parl_io_conf() - .modify(|_, w| w.parl_rst_en().clear_bit()); + .modify(|_, w| w.parl_clk_en().bit(enable)); } #[cfg(hmac)] Peripheral::Hmac => { - system.hmac_conf().modify(|_, w| w.hmac_clk_en().set_bit()); system .hmac_conf() - .modify(|_, w| w.hmac_rst_en().clear_bit()); + .modify(|_, w| w.hmac_clk_en().bit(enable)); } #[cfg(ecc)] Peripheral::Ecc => { - system.ecc_conf().modify(|_, w| w.ecc_clk_en().set_bit()); - system.ecc_conf().modify(|_, w| w.ecc_rst_en().clear_bit()); + system.ecc_conf().modify(|_, w| w.ecc_clk_en().bit(enable)); } #[cfg(soc_etm)] Peripheral::Etm => { - system.etm_conf().modify(|_, w| w.etm_clk_en().set_bit()); - system.etm_conf().modify(|_, w| w.etm_rst_en().clear_bit()); + system.etm_conf().modify(|_, w| w.etm_clk_en().bit(enable)); } #[cfg(trace0)] Peripheral::Trace0 => { system .trace_conf() - .modify(|_, w| w.trace_clk_en().set_bit()); - system - .trace_conf() - .modify(|_, w| w.trace_rst_en().clear_bit()); + .modify(|_, w| w.trace_clk_en().bit(enable)); } #[cfg(systimer)] Peripheral::Systimer => { system .systimer_conf() - .modify(|_, w| w.systimer_clk_en().set_bit()); - system - .systimer_conf() - .modify(|_, w| w.systimer_rst_en().clear_bit()); + .modify(|_, w| w.systimer_clk_en().bit(enable)); } } } /// Resets the given peripheral pub(crate) fn reset(peripheral: Peripheral) { + debug!("Reset {:?}", peripheral); + let system = unsafe { &*SYSTEM::PTR }; match peripheral { @@ -897,10 +875,6 @@ impl PeripheralClockControl { Peripheral::Timg1 => { // no reset? } - #[cfg(lp_wdt)] - Peripheral::Wdt => { - // no reset? - } #[cfg(sha)] Peripheral::Sha => { system.sha_conf().modify(|_, w| w.sha_rst_en().set_bit()); @@ -986,6 +960,61 @@ impl PeripheralClockControl { } } +impl PeripheralClockControl { + /// Enables the given peripheral. + /// + /// This keeps track of enabling a peripheral - i.e. a peripheral + /// is only enabled with the first call attempt to enable it. + /// + /// Returns `true` if it actually enabled the peripheral. + pub(crate) fn enable(peripheral: Peripheral) -> bool { + Self::enable_forced(peripheral, true, false) + } + + /// Disables the given peripheral. + /// + /// This keeps track of disabling a peripheral - i.e. it only + /// gets disabled when the number of enable/disable attempts is balanced. + /// + /// Returns `true` if it actually disabled the peripheral. + /// + /// Before disabling a peripheral it will also get reset + pub(crate) fn disable(peripheral: Peripheral) -> bool { + Self::enable_forced(peripheral, false, false) + } + + pub(crate) fn enable_forced(peripheral: Peripheral, enable: bool, force: bool) -> bool { + critical_section::with(|cs| { + if !force { + if enable { + let prev = + PERIPHERAL_REF_COUNT[peripheral as usize].fetch_add(1, Ordering::Relaxed); + if prev > 0 { + return false; + } + } else { + let prev = + PERIPHERAL_REF_COUNT[peripheral as usize].fetch_sub(1, Ordering::Relaxed); + assert!(prev != 0); + if prev > 1 { + return false; + } + }; + } else if !enable { + assert!(PERIPHERAL_REF_COUNT[peripheral as usize].swap(0, Ordering::Relaxed) == 0); + } + + if !enable { + Self::reset(peripheral); + } + + Self::enable_internal(peripheral, enable, &cs); + + true + }) + } +} + /// Enumeration of the available radio peripherals for this chip. #[cfg(any(bt, ieee802154, wifi))] pub enum RadioPeripherals { diff --git a/esp-hal/src/timer/timg.rs b/esp-hal/src/timer/timg.rs index d51eec9e2..bcbfc6193 100644 --- a/esp-hal/src/timer/timg.rs +++ b/esp-hal/src/timer/timg.rs @@ -152,7 +152,7 @@ impl TimerGroupInstance for TIMG0 { } fn enable_peripheral() { - PeripheralClockControl::enable(crate::system::Peripheral::Timg0) + PeripheralClockControl::enable(crate::system::Peripheral::Timg0); } fn reset_peripheral() { @@ -215,7 +215,7 @@ impl TimerGroupInstance for crate::peripherals::TIMG1 { } fn enable_peripheral() { - PeripheralClockControl::enable(crate::system::Peripheral::Timg1) + PeripheralClockControl::enable(crate::system::Peripheral::Timg1); } fn reset_peripheral() { @@ -929,9 +929,6 @@ where { /// Construct a new instance of [`Wdt`] pub fn new() -> Self { - #[cfg(lp_wdt)] - PeripheralClockControl::enable(crate::system::Peripheral::Wdt); - TG::configure_wdt_src_clk(); Self { diff --git a/esp-hal/src/trace.rs b/esp-hal/src/trace.rs index a0c735b1e..097775157 100644 --- a/esp-hal/src/trace.rs +++ b/esp-hal/src/trace.rs @@ -22,8 +22,8 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::trace::Trace; -//! let mut trace = Trace::new(peripherals.TRACE0); //! let mut buffer = [0_u8; 1024]; +//! let mut trace = Trace::new(peripherals.TRACE0); //! trace.start_trace(&mut buffer); //! // traced code //! @@ -36,7 +36,7 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::trace::RegisterBlock, - system::PeripheralClockControl, + system::PeripheralGuard, }; /// Errors returned from [Trace::stop_trace] @@ -56,9 +56,13 @@ pub struct TraceResult { } /// TRACE Encoder Instance -pub struct Trace<'d, T> { +pub struct Trace<'d, T> +where + T: Instance, +{ peripheral: PeripheralRef<'d, T>, buffer: Option<&'d mut [u8]>, + _guard: PeripheralGuard, } impl<'d, T> Trace<'d, T> @@ -68,13 +72,12 @@ where /// Construct a new instance pub fn new(peripheral: impl Peripheral

+ 'd) -> Self { crate::into_ref!(peripheral); - - PeripheralClockControl::reset(crate::system::Peripheral::Trace0); - PeripheralClockControl::enable(crate::system::Peripheral::Trace0); + let guard = PeripheralGuard::new(peripheral.peripheral()); Self { peripheral, buffer: None, + _guard: guard, } } @@ -207,10 +210,17 @@ where pub trait Instance: crate::private::Sealed { /// Get a reference to the peripheral's underlying register block fn register_block(&self) -> &RegisterBlock; + + /// Peripheral + fn peripheral(&self) -> crate::system::Peripheral; } impl Instance for crate::peripherals::TRACE0 { fn register_block(&self) -> &RegisterBlock { self } + + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::Trace0 + } } diff --git a/esp-hal/src/twai/mod.rs b/esp-hal/src/twai/mod.rs index cfbb1f7ea..32a8eccd3 100644 --- a/esp-hal/src/twai/mod.rs +++ b/esp-hal/src/twai/mod.rs @@ -134,7 +134,7 @@ use crate::{ interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::twai0::RegisterBlock, - system::PeripheralClockControl, + system::PeripheralGuard, twai::filter::SingleStandardFilter, Async, Blocking, @@ -751,6 +751,7 @@ pub struct TwaiConfiguration<'d, DM: crate::Mode, T = AnyTwai> { filter: Option<(FilterType, [u8; 8])>, phantom: PhantomData, mode: TwaiMode, + _guard: PeripheralGuard, } impl<'d, DM, T> TwaiConfiguration<'d, DM, T> @@ -769,15 +770,14 @@ where crate::into_ref!(twai); crate::into_mapped_ref!(tx_pin, rx_pin); - // Enable the peripheral clock for the TWAI peripheral. - PeripheralClockControl::enable(twai.peripheral()); - PeripheralClockControl::reset(twai.peripheral()); + let guard = PeripheralGuard::new(twai.peripheral()); let mut this = TwaiConfiguration { twai, filter: None, // We'll immediately call `set_filter` phantom: PhantomData, mode, + _guard: guard, }; // Accept all messages by default. @@ -1035,10 +1035,12 @@ where rx: TwaiRx { twai: unsafe { self.twai.clone_unchecked() }, phantom: PhantomData, + _guard: PeripheralGuard::new(self.twai.peripheral()), }, tx: TwaiTx { twai: unsafe { self.twai.clone_unchecked() }, phantom: PhantomData, + _guard: PeripheralGuard::new(self.twai.peripheral()), }, twai: unsafe { self.twai.clone_unchecked() }, phantom: PhantomData, @@ -1116,6 +1118,7 @@ where filter: self.filter, phantom: PhantomData, mode: self.mode, + _guard: self._guard, } } } @@ -1136,6 +1139,7 @@ where filter: self.filter, phantom: PhantomData, mode: self.mode, + _guard: self._guard, } } } @@ -1191,11 +1195,13 @@ where let mode = self.mode(); + let guard = PeripheralGuard::new(self.twai.peripheral()); TwaiConfiguration { twai: self.twai, filter: None, // filter already applied, no need to restore it phantom: PhantomData, mode, + _guard: guard, } } @@ -1277,6 +1283,7 @@ where pub struct TwaiTx<'d, DM: crate::Mode, T = AnyTwai> { twai: PeripheralRef<'d, T>, phantom: PhantomData, + _guard: PeripheralGuard, } impl TwaiTx<'_, DM, T> @@ -1319,6 +1326,7 @@ where pub struct TwaiRx<'d, DM: crate::Mode, T = AnyTwai> { twai: PeripheralRef<'d, T>, phantom: PhantomData, + _guard: PeripheralGuard, } impl TwaiRx<'_, DM, T> diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index b67f6b974..82447b33c 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -132,7 +132,7 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::{uart0::RegisterBlock, Interrupt}, private::Internal, - system::PeripheralClockControl, + system::{PeripheralClockControl, PeripheralGuard}, Async, Blocking, InterruptConfigurable, @@ -462,14 +462,19 @@ where } fn init(self, config: Config) -> Result, Error> { + let rx_guard = PeripheralGuard::new(self.uart.parts().0.peripheral); + let tx_guard = PeripheralGuard::new(self.uart.parts().0.peripheral); + let mut serial = Uart { rx: UartRx { uart: unsafe { self.uart.clone_unchecked() }, phantom: PhantomData, + guard: rx_guard, }, tx: UartTx { uart: self.uart, phantom: PhantomData, + guard: tx_guard, }, }; serial.init(config)?; @@ -488,12 +493,14 @@ pub struct Uart<'d, M, T = AnyUart> { pub struct UartTx<'d, M, T = AnyUart> { uart: PeripheralRef<'d, T>, phantom: PhantomData, + guard: PeripheralGuard, } /// UART (Receive) pub struct UartRx<'d, M, T = AnyUart> { uart: PeripheralRef<'d, T>, phantom: PhantomData, + guard: PeripheralGuard, } impl SetConfig for Uart<'_, M, T> @@ -698,6 +705,7 @@ where UartTx { uart: self.uart, phantom: PhantomData, + guard: self.guard, } } } @@ -719,6 +727,7 @@ where UartTx { uart: self.uart, phantom: PhantomData, + guard: self.guard, } } } @@ -951,6 +960,7 @@ where UartRx { uart: self.uart, phantom: PhantomData, + guard: self.guard, } } } @@ -972,6 +982,7 @@ where UartRx { uart: self.uart, phantom: PhantomData, + guard: self.guard, } } } @@ -1197,8 +1208,8 @@ where } }; - PeripheralClockControl::enable(self.tx.uart.info().peripheral); self.uart_peripheral_reset(); + self.rx.disable_rx_interrupts(); self.tx.disable_tx_interrupts(); @@ -1242,7 +1253,7 @@ where } fn rst_core(_reg_block: &RegisterBlock, _enable: bool) { - #[cfg(not(any(esp32, esp32s2)))] + #[cfg(not(any(esp32, esp32s2, esp32c6, esp32h2)))] _reg_block .clk_conf() .modify(|_, w| w.rst_core().bit(_enable)); diff --git a/examples/src/bin/spi_loopback.rs b/examples/src/bin/spi_loopback.rs index 22e92a29c..67ff6a9a7 100644 --- a/examples/src/bin/spi_loopback.rs +++ b/examples/src/bin/spi_loopback.rs @@ -46,8 +46,8 @@ fn main() -> ! { }, ) .with_sck(sclk) - .with_mosi(miso_mosi) - .with_miso(miso) + .with_miso(miso) // order matters + .with_mosi(miso_mosi) // order matters .with_cs(cs); let delay = Delay::new(); diff --git a/hil-test/tests/spi_half_duplex_write.rs b/hil-test/tests/spi_half_duplex_write.rs index 1db9ad2cb..8bd445a77 100644 --- a/hil-test/tests/spi_half_duplex_write.rs +++ b/hil-test/tests/spi_half_duplex_write.rs @@ -112,7 +112,8 @@ mod tests { ) .map_err(|e| e.0) .unwrap(); - transfer.wait(); + // dropping SPI would make us see an additional edge - so let's keep SPI alive + let (_spi, _) = transfer.wait(); assert_eq!(unit.value(), (6 * DMA_BUFFER_SIZE) as _); }