Disable peripherals when unused (#2544)

* Disable peripherals when unused

* Fixes

* CHANGELOG.md

* Fix

* Address review comments

* Have dedicated guards for CAM and LCD

* Re-use `Cam`'s guard

* De-duplicate, assert

* fmt

* Require CriticalSection

* Address comments

* Remove redundant guard

* Use `GenericPeripheralGuard`

* Renaming
This commit is contained in:
Björn Quentin 2024-11-21 10:21:28 +01:00 committed by GitHub
parent 457ed44802
commit f9203dc523
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 550 additions and 360 deletions

View File

@ -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

View File

@ -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,

View File

@ -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);
}

View File

@ -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,

View File

@ -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);
}

View File

@ -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<NativeEndianess>,
_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<P = AES> + '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();

View File

@ -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<Attenuation>; NUM_ATTENS],
active_channel: Option<u8>,
_guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>,
}
impl<'d, ADCI> Adc<'d, ADCI>
@ -408,8 +409,7 @@ where
adc_instance: impl crate::peripheral::Peripheral<P = ADCI> + 'd,
config: AdcConfig<ADCI>,
) -> 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,
}
}

View File

@ -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<u8>,
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<P = ADCI> + 'd,
config: AdcConfig<ADCI>,
) -> 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,
}
}

View File

@ -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());

View File

@ -942,7 +942,9 @@ impl<'d> Dma<'d> {
pub fn new(
dma: impl crate::peripheral::Peripheral<P = crate::peripherals::DMA> + 'd,
) -> Dma<'d> {
PeripheralClockControl::enable(Peripheral::Dma);
if PeripheralClockControl::enable(Peripheral::Dma) {
PeripheralClockControl::reset(Peripheral::Dma);
}
#[cfg(esp32)]
{

View File

@ -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<SocDependentEndianess>,
phantom: PhantomData<DM>,
_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<P = ECC> + '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,
}
}
}

View File

@ -59,7 +59,7 @@
use crate::{
peripheral::{Peripheral, PeripheralRef},
system::PeripheralClockControl,
system::GenericPeripheralGuard,
};
/// Unconfigured EtmChannel.
@ -76,6 +76,7 @@ impl<const C: u8> EtmChannel<C> {
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<const C: u8> EtmChannel<C> {
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<E, T, const C: u8> 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<P = crate::peripherals::SOC_ETM> + '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 { },)+
}
}
}

View File

@ -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<SocDependentEndianess>,
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<P = HMAC> + '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,
}
}

View File

@ -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<DM>,
config: Config,
guard: PeripheralGuard,
}
impl<T: Instance, DM: Mode> 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<P = T> + '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,
}
}

View File

@ -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<DmaMode, T> 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<DmaMode, T> 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),
}
}

View File

@ -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,
}
}

View File

@ -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, <LCD_CAM as DmaEligible>::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,
}
}
}

View File

@ -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<DM>,
pub(super) _guard: GenericPeripheralGuard<{ system::Peripheral::LcdCam as u8 }>,
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]

View File

@ -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<P = LCD_CAM> + '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,
}

View File

@ -111,8 +111,9 @@ impl<'d> Ledc<'d> {
pub fn new(_instance: impl Peripheral<P = crate::peripherals::LEDC> + '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 }

View File

@ -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

View File

@ -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<Target = RegisterBlock> + 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<const OP: u8, const IS_A: bool>() -> 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
}
}

View File

@ -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<const OP: u8, PWM> {
phantom: PhantomData<PWM>,
pub struct Operator<'d, const OP: u8, PWM> {
phantom: PhantomData<&'d PWM>,
_guard: PeripheralGuard,
}
impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
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<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
// written.
Operator {
phantom: PhantomData,
_guard: guard,
}
}
@ -204,7 +209,7 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
}
/// 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<P = impl PeripheralOutput> + 'd,
config: PwmPinConfig<true>,
@ -213,7 +218,7 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
}
/// 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<P = impl PeripheralOutput> + 'd,
config: PwmPinConfig<false>,
@ -222,7 +227,7 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
}
/// 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<P = impl PeripheralOutput> + 'd,
config_a: PwmPinConfig<true>,
@ -236,7 +241,7 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
///
/// 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<P = impl PeripheralOutput> + 'd,
config_a: PwmPinConfig<true>,
@ -283,6 +288,7 @@ impl<const IS_A: bool> PwmPinConfig<IS_A> {
pub struct PwmPin<'d, PWM, const OP: u8, const IS_A: bool> {
pin: PeripheralRef<'d, OutputConnection>,
phantom: PhantomData<PWM>,
_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<IS_A>,
) -> 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);

View File

@ -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<const TIM: u8, PWM> {
pub(super) phantom: PhantomData<PWM>,
_guard: PeripheralGuard,
}
impl<const TIM: u8, PWM: PwmPeripheral> Timer<TIM, PWM> {
pub(super) fn new() -> Self {
let guard = PeripheralGuard::new(PWM::peripheral());
Timer {
phantom: PhantomData,
_guard: guard,
}
}

View File

@ -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,
}
}

View File

@ -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, <PARL_IO as DmaEligible>::Dma>,
tx_chain: DescriptorChain,
_guard: GenericPeripheralGuard<{ crate::system::Peripheral::ParlIo as u8 }>,
}
impl<DM> 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, <PARL_IO as DmaEligible>::Dma>,
rx_chain: DescriptorChain,
_guard: GenericPeripheralGuard<{ crate::system::Peripheral::ParlIo as u8 }>,
}
impl<DM> core::fmt::Debug for ParlIoRx<'_, DM>
@ -1007,6 +1015,8 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> {
CH: DmaChannelConvert<<PARL_IO as DmaEligible>::Dma>,
Channel<'d, Blocking, CH>: From<Channel<'d, DM, CH>>,
{
let tx_guard = GenericPeripheralGuard::new();
let rx_guard = GenericPeripheralGuard::new();
let dma_channel = Channel::<Blocking, CH>::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<<PARL_IO as DmaEligible>::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<<PARL_IO as DmaEligible>::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, <PARL_IO as DmaEligible>::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, <PARL_IO as DmaEligible>::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, <PARL_IO as DmaEligible>::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, <PARL_IO as DmaEligible>::Dma>,
descriptors: &'static mut [DmaDescriptor],
_guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>,
}
#[doc(hidden)]

View File

@ -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<const UNIT: usize, const NUM: usize> Channel<'_, UNIT, NUM> {
/// return a new Channel
pub(super) fn new() -> Self {
let guard = GenericPeripheralGuard::new();
Self {
_phantom: PhantomData,
_not_send: PhantomData,
_guard: guard,
}
}

View File

@ -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<P = peripherals::PCNT> + '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,
}
}
}

View File

@ -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<const NUM: usize> 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,
}
}

View File

@ -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<M>,
_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<P = crate::peripherals::RMT> + '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<M>,
_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<M>,
_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<M>,
_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<M, const CHANNEL: u8>
where
M: crate::Mode,
{
phantom: PhantomData<M>,
_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,
}
}

View File

@ -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<DM>,
_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<P = RSA> + 'd) -> Self {
crate::into_ref!(rsa);
PeripheralClockControl::reset(PeripheralEnable::Rsa);
PeripheralClockControl::enable(PeripheralEnable::Rsa);
let guard = GenericPeripheralGuard::new();
Self {
rsa,
phantom: PhantomData,
_guard: guard,
}
}

View File

@ -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<P = SHA> + '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.

View File

@ -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<M>,
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<M, T> 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,
}
}

View File

@ -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<M>,
_guard: PeripheralGuard,
}
impl<'d> Spi<'d, Blocking> {
@ -119,15 +120,15 @@ where
pub fn new_typed(spi: impl Peripheral<P = T> + '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<DmaMode, T> core::fmt::Debug for SpiDma<'_, DmaMode, T>
@ -304,11 +306,14 @@ pub mod dma {
CH: DmaChannelConvert<T::Dma>,
{
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,
}
}

View File

@ -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<Peripheral> {
if value >= Peripheral::COUNT as u8 {
return None;
}
Some(unsafe { core::mem::transmute::<u8, Peripheral>(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<const P: u8> {}
impl<const P: u8> GenericPeripheralGuard<P> {
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<const P: u8> Drop for GenericPeripheralGuard<P> {
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 {

View File

@ -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 {

View File

@ -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<P = T> + '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
}
}

View File

@ -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<DM>,
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<DM>,
_guard: PeripheralGuard,
}
impl<DM, T> TwaiTx<'_, DM, T>
@ -1319,6 +1326,7 @@ where
pub struct TwaiRx<'d, DM: crate::Mode, T = AnyTwai> {
twai: PeripheralRef<'d, T>,
phantom: PhantomData<DM>,
_guard: PeripheralGuard,
}
impl<DM, T> TwaiRx<'_, DM, T>

View File

@ -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<Uart<'d, M, T>, 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<M>,
guard: PeripheralGuard,
}
/// UART (Receive)
pub struct UartRx<'d, M, T = AnyUart> {
uart: PeripheralRef<'d, T>,
phantom: PhantomData<M>,
guard: PeripheralGuard,
}
impl<M, T> 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));

View File

@ -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();

View File

@ -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 _);
}