diff --git a/esp-hal/README.md b/esp-hal/README.md index ee66f4763bd..d6709fdc1e6 100644 --- a/esp-hal/README.md +++ b/esp-hal/README.md @@ -101,7 +101,7 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a | SDIO host | ❌ | | | | | | | ❌ | | ❌ | | SDIO slave | ❌ | | | [❌][5169] [^1] | ❌ | [❌][5417] [^1] | | ❌ | | | | SHA | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ❌ | ⚒️ | ⚒️ | -| SDM | [❌][2370] [^1] | | [❌][2370] [^1] | [❌][2370] [^1] | [❌][2370] [^1] | | [❌][2370] [^1] | [❌][2370] [^1] | [❌][2370] [^1] | [❌][2370] [^1] | +| SDM | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | Light/deep sleep | ⚒️ | ⚒️ | ⚒️ | [❌][5165] [^1] | ⚒️ | [❌][5424] [^1] | ⚒️ | ❌ | ⚒️ | ⚒️ | | SPI master | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ⚒️ | ✔️ | ✔️ | | SPI slave | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ❌ | ⚒️ | ⚒️ | @@ -128,7 +128,6 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a [884]: https://github.com/esp-rs/esp-hal/issues/884 [1905]: https://github.com/esp-rs/esp-hal/issues/1905 [1909]: https://github.com/esp-rs/esp-hal/issues/1909 -[2370]: https://github.com/esp-rs/esp-hal/issues/2370 [5153]: https://github.com/esp-rs/esp-hal/issues/5153 [5154]: https://github.com/esp-rs/esp-hal/issues/5154 [5155]: https://github.com/esp-rs/esp-hal/issues/5155 diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 56fb7b7d939..79867386157 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -389,6 +389,8 @@ unstable_driver! { pub mod rsa; #[cfg(sha_driver_supported)] pub mod sha; + #[cfg(sdm_driver_supported)] + pub mod sdm; #[cfg(touch)] pub mod touch; #[cfg(soc_has_trace0)] diff --git a/esp-hal/src/sdm.rs b/esp-hal/src/sdm.rs new file mode 100644 index 00000000000..c962082ca1c --- /dev/null +++ b/esp-hal/src/sdm.rs @@ -0,0 +1,529 @@ +//! Sigma-delta modulation peripheral. +//! +//! The sigma-delta modulator produces a pulse-density modulated output on a +//! GPIO matrix signal. Each channel can be configured with a carrier frequency +//! and pulse density, then routed to one output pin. + +use core::fmt; + +use esp_sync::NonReentrantMutex; + +use crate::{ + gpio::{ + OutputConfig, OutputSignal, PinGuard, + interconnect::{OutputSignal as GpioOutputSignal, PeripheralOutput}, + }, + peripherals::GPIO_SD, + system::{GenericPeripheralGuard, Peripheral}, + time::Rate, +}; + +static CLOCK_STATE: NonReentrantMutex = NonReentrantMutex::new(SdmClockState::new()); + +struct SdmClockState { + users: usize, + source: Option, +} + +impl SdmClockState { + const fn new() -> Self { + Self { + users: 0, + source: None, + } + } +} + +for_each_sdm_channel!( + (channels $(($ch:literal, $signal:ident)),*) => { + paste::paste! { + /// Sigma-delta peripheral. + /// + /// This type only owns the SDM peripheral token and exposes the hardware + /// channel creators. Moving individual channel creators out of this + /// collection is supported. + #[derive(Debug)] + #[non_exhaustive] + pub struct Sdm<'d> { + _instance: GPIO_SD<'d>, + $( + #[doc = concat!("Channel ", stringify!($ch), " creator.")] + pub []: ChannelCreator<$ch>, + )* + } + + impl<'d> Sdm<'d> { + /// Creates a new sigma-delta peripheral driver. + pub fn new(instance: GPIO_SD<'d>) -> Self { + Self::new_with_config(instance, SdmConfig::default()) + } + + /// Creates a new sigma-delta peripheral driver with the given + /// peripheral-wide configuration. + /// + /// The SDM clock source is shared by all SDM channels through the IO_MUX + /// clock, so it is selected here instead of being configurable per channel. + pub fn new_with_config(instance: GPIO_SD<'d>, config: SdmConfig) -> Self { + Self { + _instance: instance, + $( + []: ChannelCreator::new(config.clock_source), + )* + } + } + } + } + }; +); + +for_each_sdm_channel!( + (channels $(($ch:literal, $signal:ident)),*) => { + fn output_signal(channel: usize) -> OutputSignal { + match channel { + $( + $ch => OutputSignal::$signal, + )* + _ => unreachable!("SDM channel index out of range"), + } + } + }; +); + +/// Sigma-delta peripheral configuration. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub struct SdmConfig { + /// Clock source used by the shared SDM/IO_MUX clock. + pub clock_source: ClockSource, +} + +impl SdmConfig { + /// Selects the source clock used by all SDM channels. + pub const fn with_clock_source(mut self, clock_source: ClockSource) -> Self { + self.clock_source = clock_source; + self + } +} + +impl Default for SdmConfig { + fn default() -> Self { + Self { + clock_source: ClockSource::default(), + } + } +} + +/// Source clock for the shared SDM/IO_MUX clock. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum ClockSource { + /// APB clock. + #[cfg(any(esp32, esp32c3, esp32s2, esp32s3))] + Apb, + /// XTAL clock. + #[cfg(any(esp32c5, esp32c6, esp32h2, esp32p4))] + Xtal, + /// Fixed 80 MHz PLL clock. + #[cfg(any(esp32c5, esp32c6, esp32p4))] + PllF80m, + /// Fixed 48 MHz PLL clock. + #[cfg(esp32h2)] + PllF48m, +} + +impl Default for ClockSource { + fn default() -> Self { + cfg_if::cfg_if! { + if #[cfg(any(esp32, esp32c3, esp32s2, esp32s3))] { + Self::Apb + } else if #[cfg(any(esp32c5, esp32c6, esp32p4))] { + Self::PllF80m + } else if #[cfg(esp32h2)] { + Self::PllF48m + } + } + } +} + +impl ClockSource { + fn frequency(self) -> Rate { + match self { + #[cfg(any(esp32, esp32c3, esp32s2, esp32s3))] + Self::Apb => Rate::from_hz(crate::soc::clocks::apb_clk_frequency()), + #[cfg(any(esp32c5, esp32c6, esp32h2, esp32p4))] + Self::Xtal => crate::clock::xtal_clock(), + #[cfg(any(esp32c5, esp32c6, esp32p4))] + Self::PllF80m => Rate::from_mhz(80), + #[cfg(esp32h2)] + Self::PllF48m => Rate::from_mhz(48), + } + } +} + +/// Sigma-delta configuration or runtime error. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + /// The requested frequency cannot be represented by the hardware prescaler. + UnreachableTargetFrequency, + /// Another SDM channel is already using a different clock source. + ClockSourceConflict, + /// The raw prescaler is outside the hardware range. + PrescalerOutOfRange, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::UnreachableTargetFrequency => f.write_str("unreachable target frequency"), + Self::ClockSourceConflict => f.write_str("SDM clock source conflict"), + Self::PrescalerOutOfRange => f.write_str("prescaler out of range"), + } + } +} + +impl core::error::Error for Error {} + +/// Creates a connected sigma-delta channel. +/// +/// Channel creators are exposed by [`Sdm`]. Calling [`connect`](Self::connect) +/// consumes the creator and returns an active [`Channel`], which prevents +/// accidentally connecting the same channel twice. +#[derive(Debug)] +pub struct ChannelCreator { + // This is copied from the Sdm-level configuration so partially moved + // channel creators still use the shared clock source selected at construction time. + // It is intentionally not configurable per channel. + clock_source: ClockSource, + prescaler: u16, + pulse_density: i8, +} + +impl ChannelCreator { + const fn new(clock_source: ClockSource) -> Self { + Self { + clock_source, + prescaler: 1, + pulse_density: 0, + } + } + + const fn with_raw_config(clock_source: ClockSource, prescaler: u16, pulse_density: i8) -> Self { + Self { + clock_source, + prescaler, + pulse_density, + } + } + + /// Sets the requested output frequency. + /// + /// The frequency is converted immediately using the SDM clock source + /// selected in [`SdmConfig`]. + pub fn with_frequency(mut self, frequency: Rate) -> Result { + self.prescaler = prescaler_from_frequency(frequency, self.clock_source)?; + Ok(self) + } + + /// Sets the raw hardware prescaler. + /// + /// The hardware divider range is `1..=256`. + pub fn with_prescaler(mut self, prescaler: u16) -> Result { + check_prescaler(prescaler)?; + self.prescaler = prescaler; + Ok(self) + } + + /// Sets the pulse density. + /// + /// The value ranges is `-128..=127` + pub const fn with_pulse_density(mut self, density: i8) -> Self { + self.pulse_density = density; + self + } + + /// Sets duty cycle. `0` maps to the minimum density and `255` maps to the + /// maximum density. + pub const fn with_duty(mut self, duty: u8) -> Self { + self.pulse_density = duty_to_density(duty); + self + } + + /// Configures this channel and connects it to an output pin. + pub fn connect<'d>(self, pin: impl PeripheralOutput<'d>) -> Result, Error> { + let clock_guard = SdmClockGuard::new(self.clock_source)?; + set_prescaler_raw(CHANNEL, self.prescaler); + set_pulse_density_raw(CHANNEL, self.pulse_density); + + Ok(Channel { + clock_source: self.clock_source, + _pin_guard: connect_pin(CHANNEL, pin), + _clock_guard: clock_guard, + }) + } +} + +/// A connected sigma-delta channel. +/// +/// Dropping a channel disconnects its output pin and releases the SDM clock +/// guard. Use [`disconnect`](Self::disconnect) to explicitly release the +/// channel and recover its [`ChannelCreator`]. +#[derive(Debug)] +pub struct Channel { + clock_source: ClockSource, + _pin_guard: PinGuard, + _clock_guard: SdmClockGuard, +} + +impl Channel { + /// Sets raw pulse density. + /// + /// The value ranges from `-128` to `127`. + pub fn set_pulse_density(&mut self, density: i8) { + set_pulse_density_raw(CHANNEL, density); + } + + /// Sets duty cycle. `0` maps to the minimum density and `255` maps to the + /// maximum density. + pub fn set_duty(&mut self, duty: u8) { + self.set_pulse_density(duty_to_density(duty)) + } + + /// Sets raw prescaler. + /// + /// The hardware divider range is `1..=256`. + pub fn set_prescaler(&mut self, prescaler: u16) -> Result<(), Error> { + check_prescaler(prescaler)?; + set_prescaler_raw(CHANNEL, prescaler); + Ok(()) + } + + /// Sets the output frequency. + pub fn set_frequency(&mut self, frequency: Rate) -> Result<(), Error> { + let prescaler = prescaler_from_frequency(frequency, self.clock_source)?; + self.set_prescaler(prescaler) + } + + /// Reads the raw hardware prescaler. + /// + /// The returned value is in the hardware divider range `1..=256`. + pub fn prescaler(&mut self) -> Result { + Ok(prescaler_raw(CHANNEL)) + } + + /// Reads the raw pulse density. + /// + /// The returned value is in the hardware range `-128..=127`. + pub fn pulse_density(&mut self) -> Result { + Ok(pulse_density_raw(CHANNEL)) + } + + /// Disconnects this channel and returns its channel creator. + pub fn disconnect(self) -> ChannelCreator { + let clock_source = self.clock_source; + let prescaler = prescaler_raw(CHANNEL); + let pulse_density = pulse_density_raw(CHANNEL); + drop(self); + ChannelCreator::with_raw_config(clock_source, prescaler, pulse_density) + } +} + +impl Drop for Channel { + fn drop(&mut self) { + set_pulse_density_raw(CHANNEL, 0); + } +} + +fn connect_pin<'d>(channel: usize, pin: impl PeripheralOutput<'d>) -> PinGuard { + let pin: GpioOutputSignal<'d> = pin.into(); + pin.apply_output_config(&OutputConfig::default()); + pin.set_output_enable(true); + pin.connect_with_guard(output_signal(channel)) +} + +#[derive(Debug)] +struct SdmClockGuard { + _peripheral: GenericPeripheralGuard<{ Peripheral::GpioSd as u8 }>, + clock_source: ClockSource, +} + +impl SdmClockGuard { + fn new(clock_source: ClockSource) -> Result { + CLOCK_STATE.with(|state| { + if state.users == usize::MAX { + panic!("SDM clock reference counter overflowed"); + } + + if state.users == 0 { + configure_clock_source(clock_source); + state.source = Some(clock_source); + } else if state.source != Some(clock_source) { + return Err(Error::ClockSourceConflict); + } + + state.users += 1; + Ok(()) + })?; + + Ok(Self { + _peripheral: GenericPeripheralGuard::new(), + clock_source, + }) + } +} + +impl Drop for SdmClockGuard { + fn drop(&mut self) { + CLOCK_STATE.with(|state| match state.users { + 0 => panic!("SDM clock reference counter underflowed"), + 1 => { + debug_assert_eq!(state.source, Some(self.clock_source)); + state.users = 0; + state.source = None; + } + _ => { + debug_assert_eq!(state.source, Some(self.clock_source)); + state.users -= 1; + } + }); + } +} + +fn prescaler_from_frequency(frequency: Rate, clock_source: ClockSource) -> Result { + let source_frequency = clock_source.frequency().as_hz(); + let requested_frequency = frequency.as_hz(); + + if requested_frequency == 0 || requested_frequency > source_frequency { + return Err(Error::UnreachableTargetFrequency); + } + + let prescaler = + (source_frequency as u64 + requested_frequency as u64 / 2) / requested_frequency as u64; + if prescaler == 0 || prescaler > 256 { + return Err(Error::UnreachableTargetFrequency); + } + + Ok(prescaler as u16) +} + +fn check_prescaler(prescaler: u16) -> Result<(), Error> { + if (1..=256).contains(&prescaler) { + Ok(()) + } else { + Err(Error::PrescalerOutOfRange) + } +} + +const fn duty_to_density(duty: u8) -> i8 { + (duty as i16 - 128) as i8 +} + +fn configure_clock_source(clock_source: ClockSource) { + // Newer chips expose this selector in different clock-control blocks: + // - C5/C6/H2 use PCR.iomux_clk_conf.iomux_func_clk_sel, but the selector + // encodings differ by chip. + // - P4 uses HP_SYS_CLKRST.peri_clk_ctrl26.iomux_clk_src_sel, a one-bit + // XTAL/PLL_F80M selector. + // - ESP32/C3/S2/S3 use APB for this driver path and do not need a source + // selector write here. + cfg_if::cfg_if! { + if #[cfg(esp32c5)] { + crate::peripherals::PCR::regs().iomux_clk_conf().modify(|_, w| unsafe { + w.iomux_func_clk_sel() + .bits(match clock_source { + ClockSource::Xtal => 0, + ClockSource::PllF80m => 2, + }) + .iomux_func_clk_en() + .set_bit() + }); + } else if #[cfg(esp32c6)] { + crate::peripherals::PCR::regs().iomux_clk_conf().modify(|_, w| unsafe { + w.iomux_func_clk_sel() + .bits(match clock_source { + ClockSource::PllF80m => 1, + ClockSource::Xtal => 3, + }) + .iomux_func_clk_en() + .set_bit() + }); + } else if #[cfg(esp32h2)] { + crate::peripherals::PCR::regs().iomux_clk_conf().modify(|_, w| unsafe { + w.iomux_func_clk_sel() + .bits(match clock_source { + ClockSource::Xtal => 0, + ClockSource::PllF48m => 2, + }) + .iomux_func_clk_en() + .set_bit() + }); + } else if #[cfg(esp32p4)] { + crate::peripherals::HP_SYS_CLKRST::regs() + .peri_clk_ctrl26() + .modify(|_, w| { + match clock_source { + ClockSource::Xtal => w.iomux_clk_src_sel().clear_bit(), + ClockSource::PllF80m => w.iomux_clk_src_sel().set_bit(), + } + .iomux_clk_en() + .set_bit() + }); + } else { + let _ = clock_source; + } + } +} + +fn set_pulse_density_raw(channel: usize, density: i8) { + // The register layout is the same conceptually, but ESP32-C5's PAC names + // the field `sd_in`; the other supported PACs name it `in`. + let sd = GPIO_SD::regs(); + + #[cfg(esp32c5)] + sd.sigmadelta(channel) + .modify(|_, w| unsafe { w.sd_in().bits(density as _) }); + + #[cfg(not(esp32c5))] + sd.sigmadelta(channel) + .modify(|_, w| unsafe { w.in_().bits(density as _) }); +} + +fn set_prescaler_raw(channel: usize, prescaler: u16) { + // Hardware stores prescaler - 1. ESP32-C5's PAC names the field + // `sd_prescale`; the other supported PACs name it `prescale`. + let bits = (prescaler - 1) as _; + let sd = GPIO_SD::regs(); + + #[cfg(esp32c5)] + sd.sigmadelta(channel) + .modify(|_, w| unsafe { w.sd_prescale().bits(bits) }); + + #[cfg(not(esp32c5))] + sd.sigmadelta(channel) + .modify(|_, w| unsafe { w.prescale().bits(bits) }); +} + +fn pulse_density_raw(channel: usize) -> i8 { + let sd = GPIO_SD::regs(); + + #[cfg(esp32c5)] + return sd.sigmadelta(channel).read().sd_in().bits() as i8; + + #[cfg(not(esp32c5))] + return sd.sigmadelta(channel).read().in_().bits() as i8; +} + +fn prescaler_raw(channel: usize) -> u16 { + let sd = GPIO_SD::regs(); + + #[cfg(esp32c5)] + let bits = sd.sigmadelta(channel).read().sd_prescale().bits(); + + #[cfg(not(esp32c5))] + let bits = sd.sigmadelta(channel).read().prescale().bits(); + + bits as u16 + 1 +} diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 53d38ca26d0..dbd7c88336f 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -290,6 +290,7 @@ impl Chip { "rsa_driver_supported", "lp_timer_driver_supported", "sha_driver_supported", + "sdm_driver_supported", "sleep_driver_supported", "soc_driver_supported", "spi_master_driver_supported", @@ -359,6 +360,8 @@ impl Chip { "rsa_version=\"1\"", "rsa_size_increment=\"512\"", "rsa_memory_size_bytes=\"512\"", + "sdm_clock_sources_apb", + "sdm_default_clock_source=\"apb\"", "sleep_light_sleep", "sleep_deep_sleep", "soc_multi_core_enabled", @@ -503,6 +506,7 @@ impl Chip { "cargo:rustc-cfg=rsa_driver_supported", "cargo:rustc-cfg=lp_timer_driver_supported", "cargo:rustc-cfg=sha_driver_supported", + "cargo:rustc-cfg=sdm_driver_supported", "cargo:rustc-cfg=sleep_driver_supported", "cargo:rustc-cfg=soc_driver_supported", "cargo:rustc-cfg=spi_master_driver_supported", @@ -572,6 +576,8 @@ impl Chip { "cargo:rustc-cfg=rsa_version=\"1\"", "cargo:rustc-cfg=rsa_size_increment=\"512\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"512\"", + "cargo:rustc-cfg=sdm_clock_sources_apb", + "cargo:rustc-cfg=sdm_default_clock_source=\"apb\"", "cargo:rustc-cfg=sleep_light_sleep", "cargo:rustc-cfg=sleep_deep_sleep", "cargo:rustc-cfg=soc_multi_core_enabled", @@ -1302,6 +1308,7 @@ impl Chip { "rsa_driver_supported", "lp_timer_driver_supported", "sha_driver_supported", + "sdm_driver_supported", "sleep_driver_supported", "soc_driver_supported", "spi_master_driver_supported", @@ -1389,6 +1396,8 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"384\"", "sha_dma", + "sdm_clock_sources_apb", + "sdm_default_clock_source=\"apb\"", "sleep_light_sleep", "sleep_deep_sleep", "soc_cpu_has_csr_pc", @@ -1519,6 +1528,7 @@ impl Chip { "cargo:rustc-cfg=rsa_driver_supported", "cargo:rustc-cfg=lp_timer_driver_supported", "cargo:rustc-cfg=sha_driver_supported", + "cargo:rustc-cfg=sdm_driver_supported", "cargo:rustc-cfg=sleep_driver_supported", "cargo:rustc-cfg=soc_driver_supported", "cargo:rustc-cfg=spi_master_driver_supported", @@ -1606,6 +1616,8 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", "cargo:rustc-cfg=sha_dma", + "cargo:rustc-cfg=sdm_clock_sources_apb", + "cargo:rustc-cfg=sdm_default_clock_source=\"apb\"", "cargo:rustc-cfg=sleep_light_sleep", "cargo:rustc-cfg=sleep_deep_sleep", "cargo:rustc-cfg=soc_cpu_has_csr_pc", @@ -1877,6 +1889,7 @@ impl Chip { "rsa_driver_supported", "lp_timer_driver_supported", "sha_driver_supported", + "sdm_driver_supported", "soc_driver_supported", "spi_master_driver_supported", "spi_slave_driver_supported", @@ -1975,6 +1988,9 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"384\"", "sha_dma", + "sdm_clock_sources_xtal", + "sdm_clock_sources_pll_f80m", + "sdm_default_clock_source=\"pll_f80m\"", "soc_cpu_has_branch_predictor", "soc_cpu_csr_prv_mode=\"2064\"", "soc_cpu_csr_prv_mode_is_set", @@ -2142,6 +2158,7 @@ impl Chip { "cargo:rustc-cfg=rsa_driver_supported", "cargo:rustc-cfg=lp_timer_driver_supported", "cargo:rustc-cfg=sha_driver_supported", + "cargo:rustc-cfg=sdm_driver_supported", "cargo:rustc-cfg=soc_driver_supported", "cargo:rustc-cfg=spi_master_driver_supported", "cargo:rustc-cfg=spi_slave_driver_supported", @@ -2240,6 +2257,9 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", "cargo:rustc-cfg=sha_dma", + "cargo:rustc-cfg=sdm_clock_sources_xtal", + "cargo:rustc-cfg=sdm_clock_sources_pll_f80m", + "cargo:rustc-cfg=sdm_default_clock_source=\"pll_f80m\"", "cargo:rustc-cfg=soc_cpu_has_branch_predictor", "cargo:rustc-cfg=soc_cpu_csr_prv_mode=\"2064\"", "cargo:rustc-cfg=soc_cpu_csr_prv_mode_is_set", @@ -2563,6 +2583,7 @@ impl Chip { "rsa_driver_supported", "lp_timer_driver_supported", "sha_driver_supported", + "sdm_driver_supported", "sleep_driver_supported", "soc_driver_supported", "spi_master_driver_supported", @@ -2660,6 +2681,9 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"384\"", "sha_dma", + "sdm_clock_sources_xtal", + "sdm_clock_sources_pll_f80m", + "sdm_default_clock_source=\"pll_f80m\"", "sleep_light_sleep", "sleep_deep_sleep", "soc_cpu_has_csr_pc", @@ -2850,6 +2874,7 @@ impl Chip { "cargo:rustc-cfg=rsa_driver_supported", "cargo:rustc-cfg=lp_timer_driver_supported", "cargo:rustc-cfg=sha_driver_supported", + "cargo:rustc-cfg=sdm_driver_supported", "cargo:rustc-cfg=sleep_driver_supported", "cargo:rustc-cfg=soc_driver_supported", "cargo:rustc-cfg=spi_master_driver_supported", @@ -2947,6 +2972,9 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", "cargo:rustc-cfg=sha_dma", + "cargo:rustc-cfg=sdm_clock_sources_xtal", + "cargo:rustc-cfg=sdm_clock_sources_pll_f80m", + "cargo:rustc-cfg=sdm_default_clock_source=\"pll_f80m\"", "cargo:rustc-cfg=sleep_light_sleep", "cargo:rustc-cfg=sleep_deep_sleep", "cargo:rustc-cfg=soc_cpu_has_csr_pc", @@ -3820,6 +3848,7 @@ impl Chip { "rsa_driver_supported", "lp_timer_driver_supported", "sha_driver_supported", + "sdm_driver_supported", "sleep_driver_supported", "soc_driver_supported", "spi_master_driver_supported", @@ -3917,6 +3946,9 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"384\"", "sha_dma", + "sdm_clock_sources_xtal", + "sdm_clock_sources_pll_f48m", + "sdm_default_clock_source=\"pll_f48m\"", "sleep_light_sleep", "sleep_deep_sleep", "soc_cpu_has_csr_pc", @@ -4074,6 +4106,7 @@ impl Chip { "cargo:rustc-cfg=rsa_driver_supported", "cargo:rustc-cfg=lp_timer_driver_supported", "cargo:rustc-cfg=sha_driver_supported", + "cargo:rustc-cfg=sdm_driver_supported", "cargo:rustc-cfg=sleep_driver_supported", "cargo:rustc-cfg=soc_driver_supported", "cargo:rustc-cfg=spi_master_driver_supported", @@ -4171,6 +4204,9 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", "cargo:rustc-cfg=sha_dma", + "cargo:rustc-cfg=sdm_clock_sources_xtal", + "cargo:rustc-cfg=sdm_clock_sources_pll_f48m", + "cargo:rustc-cfg=sdm_default_clock_source=\"pll_f48m\"", "cargo:rustc-cfg=sleep_light_sleep", "cargo:rustc-cfg=sleep_deep_sleep", "cargo:rustc-cfg=soc_cpu_has_csr_pc", @@ -4332,6 +4368,7 @@ impl Chip { "multi_core", "soc_has_efuse", "soc_has_gpio", + "soc_has_gpio_sd", "soc_has_system", "soc_has_hp_sys", "soc_has_hp_sys_clkrst", @@ -4397,6 +4434,7 @@ impl Chip { "interrupts_driver_supported", "psram_driver_supported", "rng_driver_supported", + "sdm_driver_supported", "soc_driver_supported", "spi_master_driver_supported", "systimer_driver_supported", @@ -4462,6 +4500,9 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"384\"", "sha_dma", + "sdm_clock_sources_xtal", + "sdm_clock_sources_pll_f80m", + "sdm_default_clock_source=\"pll_f80m\"", "soc_cpu_has_branch_predictor", "soc_multi_core_enabled", "soc_rc_fast_clk_default=\"20000000\"", @@ -4511,6 +4552,7 @@ impl Chip { "cargo:rustc-cfg=multi_core", "cargo:rustc-cfg=soc_has_efuse", "cargo:rustc-cfg=soc_has_gpio", + "cargo:rustc-cfg=soc_has_gpio_sd", "cargo:rustc-cfg=soc_has_system", "cargo:rustc-cfg=soc_has_hp_sys", "cargo:rustc-cfg=soc_has_hp_sys_clkrst", @@ -4576,6 +4618,7 @@ impl Chip { "cargo:rustc-cfg=interrupts_driver_supported", "cargo:rustc-cfg=psram_driver_supported", "cargo:rustc-cfg=rng_driver_supported", + "cargo:rustc-cfg=sdm_driver_supported", "cargo:rustc-cfg=soc_driver_supported", "cargo:rustc-cfg=spi_master_driver_supported", "cargo:rustc-cfg=systimer_driver_supported", @@ -4641,6 +4684,9 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", "cargo:rustc-cfg=sha_dma", + "cargo:rustc-cfg=sdm_clock_sources_xtal", + "cargo:rustc-cfg=sdm_clock_sources_pll_f80m", + "cargo:rustc-cfg=sdm_default_clock_source=\"pll_f80m\"", "cargo:rustc-cfg=soc_cpu_has_branch_predictor", "cargo:rustc-cfg=soc_multi_core_enabled", "cargo:rustc-cfg=soc_rc_fast_clk_default=\"20000000\"", @@ -5016,6 +5062,7 @@ impl Chip { "rsa_driver_supported", "lp_timer_driver_supported", "sha_driver_supported", + "sdm_driver_supported", "sleep_driver_supported", "soc_driver_supported", "spi_master_driver_supported", @@ -5105,6 +5152,8 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"512\"", "sha_dma", + "sdm_clock_sources_apb", + "sdm_default_clock_source=\"apb\"", "sleep_light_sleep", "sleep_deep_sleep", "soc_rc_fast_clk_default=\"8500000\"", @@ -5244,6 +5293,7 @@ impl Chip { "cargo:rustc-cfg=rsa_driver_supported", "cargo:rustc-cfg=lp_timer_driver_supported", "cargo:rustc-cfg=sha_driver_supported", + "cargo:rustc-cfg=sdm_driver_supported", "cargo:rustc-cfg=sleep_driver_supported", "cargo:rustc-cfg=soc_driver_supported", "cargo:rustc-cfg=spi_master_driver_supported", @@ -5333,6 +5383,8 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"512\"", "cargo:rustc-cfg=sha_dma", + "cargo:rustc-cfg=sdm_clock_sources_apb", + "cargo:rustc-cfg=sdm_default_clock_source=\"apb\"", "cargo:rustc-cfg=sleep_light_sleep", "cargo:rustc-cfg=sleep_deep_sleep", "cargo:rustc-cfg=soc_rc_fast_clk_default=\"8500000\"", @@ -5682,6 +5734,7 @@ impl Chip { "rsa_driver_supported", "lp_timer_driver_supported", "sha_driver_supported", + "sdm_driver_supported", "sleep_driver_supported", "soc_driver_supported", "spi_master_driver_supported", @@ -5785,6 +5838,8 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"512\"", "sha_dma", + "sdm_clock_sources_apb", + "sdm_default_clock_source=\"apb\"", "sleep_light_sleep", "sleep_deep_sleep", "soc_multi_core_enabled", @@ -5943,6 +5998,7 @@ impl Chip { "cargo:rustc-cfg=rsa_driver_supported", "cargo:rustc-cfg=lp_timer_driver_supported", "cargo:rustc-cfg=sha_driver_supported", + "cargo:rustc-cfg=sdm_driver_supported", "cargo:rustc-cfg=sleep_driver_supported", "cargo:rustc-cfg=soc_driver_supported", "cargo:rustc-cfg=spi_master_driver_supported", @@ -6046,6 +6102,8 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"512\"", "cargo:rustc-cfg=sha_dma", + "cargo:rustc-cfg=sdm_clock_sources_apb", + "cargo:rustc-cfg=sdm_default_clock_source=\"apb\"", "cargo:rustc-cfg=sleep_light_sleep", "cargo:rustc-cfg=sleep_deep_sleep", "cargo:rustc-cfg=soc_multi_core_enabled", @@ -6449,6 +6507,7 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(rsa_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(lp_timer_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(sha_driver_supported)"); + println!("cargo:rustc-check-cfg=cfg(sdm_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(sleep_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(soc_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(spi_master_driver_supported)"); @@ -6490,6 +6549,7 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(phy_combo_module)"); println!("cargo:rustc-check-cfg=cfg(rmt_has_per_channel_clock)"); println!("cargo:rustc-check-cfg=cfg(rng_trng_supported)"); + println!("cargo:rustc-check-cfg=cfg(sdm_clock_sources_apb)"); println!("cargo:rustc-check-cfg=cfg(sleep_light_sleep)"); println!("cargo:rustc-check-cfg=cfg(sleep_deep_sleep)"); println!("cargo:rustc-check-cfg=cfg(soc_multi_core_enabled)"); @@ -6680,6 +6740,8 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(i2c_master_has_reliable_fsm_reset)"); println!("cargo:rustc-check-cfg=cfg(i2s_clock_configured_by_pcr)"); println!("cargo:rustc-check-cfg=cfg(rmt_has_tx_loop_auto_stop)"); + println!("cargo:rustc-check-cfg=cfg(sdm_clock_sources_xtal)"); + println!("cargo:rustc-check-cfg=cfg(sdm_clock_sources_pll_f80m)"); println!("cargo:rustc-check-cfg=cfg(soc_cpu_has_branch_predictor)"); println!("cargo:rustc-check-cfg=cfg(soc_cpu_csr_prv_mode_is_set)"); println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_pll_f12m)"); @@ -6733,6 +6795,7 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem10)"); println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem11)"); println!("cargo:rustc-check-cfg=cfg(esp32h2)"); + println!("cargo:rustc-check-cfg=cfg(sdm_clock_sources_pll_f48m)"); println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_pll_f96m_clk)"); println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_pll_f64m_clk)"); println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_pll_f48m_clk)"); @@ -6847,6 +6910,10 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(rsa_version, values(\"1\",\"3\",\"2\"))"); println!("cargo:rustc-check-cfg=cfg(rsa_size_increment, values(\"512\",\"32\"))"); println!("cargo:rustc-check-cfg=cfg(rsa_memory_size_bytes, values(\"512\",\"384\"))"); + println!( + "cargo:rustc-check-cfg=cfg(sdm_default_clock_source, \ + values(\"apb\",\"pll_f80m\",\"pll_f48m\"))" + ); println!( "cargo:rustc-check-cfg=cfg(soc_rc_fast_clk_default, \ values(\"8500000\",\"17500000\",\"20000000\"))" diff --git a/esp-metadata-generated/src/_generated_esp32.rs b/esp-metadata-generated/src/_generated_esp32.rs index 483de5ad739..56d2a21bc81 100644 --- a/esp-metadata-generated/src/_generated_esp32.rs +++ b/esp-metadata-generated/src/_generated_esp32.rs @@ -313,6 +313,15 @@ macro_rules! property { ("sha.dma") => { false }; + ("sdm.channel_count") => { + 8 + }; + ("sdm.channel_count", str) => { + stringify!(8) + }; + ("sdm.default_clock_source") => { + "apb" + }; ("sleep.light_sleep") => { true }; @@ -578,6 +587,22 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sdm_channel { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sdm_channel { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_sdm_channel!((0, GPIO_SD0)); + _for_each_inner_sdm_channel!((1, GPIO_SD1)); _for_each_inner_sdm_channel!((2, + GPIO_SD2)); _for_each_inner_sdm_channel!((3, GPIO_SD3)); + _for_each_inner_sdm_channel!((4, GPIO_SD4)); _for_each_inner_sdm_channel!((5, + GPIO_SD5)); _for_each_inner_sdm_channel!((6, GPIO_SD6)); + _for_each_inner_sdm_channel!((7, GPIO_SD7)); + _for_each_inner_sdm_channel!((channels(0, GPIO_SD0), (1, GPIO_SD1), (2, + GPIO_SD2), (3, GPIO_SD3), (4, GPIO_SD4), (5, GPIO_SD5), (6, GPIO_SD6), (7, + GPIO_SD7))); + }; +} +#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK @@ -3111,6 +3136,8 @@ macro_rules! implement_peripheral_clocks { Aes, /// EMAC peripheral clock signal Emac, + /// GPIO_SD peripheral clock signal + GpioSd, /// I2C_EXT0 peripheral clock signal I2cExt0, /// I2C_EXT1 peripheral clock signal @@ -3164,6 +3191,7 @@ macro_rules! implement_peripheral_clocks { const ALL: &[Self] = &[ Self::Aes, Self::Emac, + Self::GpioSd, Self::I2cExt0, Self::I2cExt1, Self::I2s0, @@ -3201,6 +3229,9 @@ macro_rules! implement_peripheral_clocks { .wifi_clk_en() .modify(|_, w| w.emac_clk_en().bit(enable)); } + Peripheral::GpioSd => { + let _ = enable; + } Peripheral::I2cExt0 => { crate::peripherals::SYSTEM::regs() .perip_clk_en() @@ -3330,6 +3361,9 @@ macro_rules! implement_peripheral_clocks { .wifi_rst_en() .modify(|_, w| w.emac_rst().bit(reset)); } + Peripheral::GpioSd => { + let _ = reset; + } Peripheral::I2cExt0 => { crate::peripherals::SYSTEM::regs() .perip_rst_en() diff --git a/esp-metadata-generated/src/_generated_esp32c3.rs b/esp-metadata-generated/src/_generated_esp32c3.rs index 56442b383a9..76fd927af5d 100644 --- a/esp-metadata-generated/src/_generated_esp32c3.rs +++ b/esp-metadata-generated/src/_generated_esp32c3.rs @@ -331,6 +331,15 @@ macro_rules! property { ("sha.dma") => { true }; + ("sdm.channel_count") => { + 4 + }; + ("sdm.channel_count", str) => { + stringify!(4) + }; + ("sdm.default_clock_source") => { + "apb" + }; ("sleep.light_sleep") => { true }; @@ -871,6 +880,18 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sdm_channel { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sdm_channel { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_sdm_channel!((0, GPIO_SD0)); + _for_each_inner_sdm_channel!((1, GPIO_SD1)); _for_each_inner_sdm_channel!((2, + GPIO_SD2)); _for_each_inner_sdm_channel!((3, GPIO_SD3)); + _for_each_inner_sdm_channel!((channels(0, GPIO_SD0), (1, GPIO_SD1), (2, + GPIO_SD2), (3, GPIO_SD3))); + }; +} +#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK @@ -3102,6 +3123,8 @@ macro_rules! implement_peripheral_clocks { Dma, /// DS peripheral clock signal Ds, + /// GPIO_SD peripheral clock signal + GpioSd, /// HMAC peripheral clock signal Hmac, /// I2C_EXT0 peripheral clock signal @@ -3153,6 +3176,7 @@ macro_rules! implement_peripheral_clocks { Self::ApbSarAdc, Self::Dma, Self::Ds, + Self::GpioSd, Self::Hmac, Self::I2cExt0, Self::I2s0, @@ -3195,6 +3219,14 @@ macro_rules! implement_peripheral_clocks { .perip_clk_en1() .modify(|_, w| w.crypto_ds_clk_en().bit(enable)); } + Peripheral::GpioSd => { + crate::peripherals::GPIO_SD::regs() + .clock_gate() + .modify(|_, w| w.clk_en().bit(enable)); + crate::peripherals::GPIO_SD::regs() + .sigmadelta_misc() + .modify(|_, w| w.function_clk_en().bit(enable)); + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .perip_clk_en1() @@ -3309,6 +3341,9 @@ macro_rules! implement_peripheral_clocks { .perip_rst_en1() .modify(|_, w| w.crypto_ds_rst().bit(reset)); } + Peripheral::GpioSd => { + let _ = reset; + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .perip_rst_en1() diff --git a/esp-metadata-generated/src/_generated_esp32c5.rs b/esp-metadata-generated/src/_generated_esp32c5.rs index 792e48c6b20..bd3633c7668 100644 --- a/esp-metadata-generated/src/_generated_esp32c5.rs +++ b/esp-metadata-generated/src/_generated_esp32c5.rs @@ -367,6 +367,15 @@ macro_rules! property { ("sha.dma") => { true }; + ("sdm.channel_count") => { + 4 + }; + ("sdm.channel_count", str) => { + stringify!(4) + }; + ("sdm.default_clock_source") => { + "pll_f80m" + }; ("sleep.light_sleep") => { false }; @@ -1009,6 +1018,18 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sdm_channel { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sdm_channel { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_sdm_channel!((0, GPIO_SD0)); + _for_each_inner_sdm_channel!((1, GPIO_SD1)); _for_each_inner_sdm_channel!((2, + GPIO_SD2)); _for_each_inner_sdm_channel!((3, GPIO_SD3)); + _for_each_inner_sdm_channel!((channels(0, GPIO_SD0), (1, GPIO_SD1), (2, + GPIO_SD2), (3, GPIO_SD3))); + }; +} +#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK @@ -3278,6 +3299,8 @@ macro_rules! implement_peripheral_clocks { Dma, /// ECC peripheral clock signal Ecc, + /// GPIO_SD peripheral clock signal + GpioSd, /// I2C_EXT0 peripheral clock signal I2cExt0, /// I2S0 peripheral clock signal @@ -3323,6 +3346,7 @@ macro_rules! implement_peripheral_clocks { Self::ApbSarAdc, Self::Dma, Self::Ecc, + Self::GpioSd, Self::I2cExt0, Self::I2s0, Self::ParlIo, @@ -3362,6 +3386,14 @@ macro_rules! implement_peripheral_clocks { .ecc_conf() .modify(|_, w| w.ecc_clk_en().bit(enable)); } + Peripheral::GpioSd => { + crate::peripherals::GPIO_SD::regs() + .clock_gate() + .modify(|_, w| w.clk_en().bit(enable)); + crate::peripherals::GPIO_SD::regs() + .sigmadelta_misc() + .modify(|_, w| w.sigmadelta_clk_en().bit(enable)); + } Peripheral::I2cExt0 => { crate::peripherals::SYSTEM::regs() .i2c0_conf() @@ -3465,6 +3497,9 @@ macro_rules! implement_peripheral_clocks { .ecc_conf() .modify(|_, w| w.ecc_rst_en().bit(reset)); } + Peripheral::GpioSd => { + let _ = reset; + } Peripheral::I2cExt0 => { crate::peripherals::SYSTEM::regs() .i2c0_conf() diff --git a/esp-metadata-generated/src/_generated_esp32c6.rs b/esp-metadata-generated/src/_generated_esp32c6.rs index 3a59a0cacd4..8bf67d1ca73 100644 --- a/esp-metadata-generated/src/_generated_esp32c6.rs +++ b/esp-metadata-generated/src/_generated_esp32c6.rs @@ -358,6 +358,15 @@ macro_rules! property { ("sha.dma") => { true }; + ("sdm.channel_count") => { + 4 + }; + ("sdm.channel_count", str) => { + stringify!(4) + }; + ("sdm.default_clock_source") => { + "pll_f80m" + }; ("sleep.light_sleep") => { true }; @@ -946,6 +955,18 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sdm_channel { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sdm_channel { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_sdm_channel!((0, GPIO_SD0)); + _for_each_inner_sdm_channel!((1, GPIO_SD1)); _for_each_inner_sdm_channel!((2, + GPIO_SD2)); _for_each_inner_sdm_channel!((3, GPIO_SD3)); + _for_each_inner_sdm_channel!((channels(0, GPIO_SD0), (1, GPIO_SD1), (2, + GPIO_SD2), (3, GPIO_SD3))); + }; +} +#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK @@ -3980,6 +4001,8 @@ macro_rules! implement_peripheral_clocks { Ecc, /// ETM peripheral clock signal Etm, + /// GPIO_SD peripheral clock signal + GpioSd, /// HMAC peripheral clock signal Hmac, /// I2C_EXT0 peripheral clock signal @@ -4043,6 +4066,7 @@ macro_rules! implement_peripheral_clocks { Self::Ds, Self::Ecc, Self::Etm, + Self::GpioSd, Self::Hmac, Self::I2cExt0, Self::I2s0, @@ -4100,6 +4124,14 @@ macro_rules! implement_peripheral_clocks { .etm_conf() .modify(|_, w| w.etm_clk_en().bit(enable)); } + Peripheral::GpioSd => { + crate::peripherals::GPIO_SD::regs() + .clock_gate() + .modify(|_, w| w.clk_en().bit(enable)); + crate::peripherals::GPIO_SD::regs() + .sigmadelta_misc() + .modify(|_, w| w.function_clk_en().bit(enable)); + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .hmac_conf() @@ -4259,6 +4291,9 @@ macro_rules! implement_peripheral_clocks { .etm_conf() .modify(|_, w| w.etm_rst_en().bit(reset)); } + Peripheral::GpioSd => { + let _ = reset; + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .hmac_conf() diff --git a/esp-metadata-generated/src/_generated_esp32h2.rs b/esp-metadata-generated/src/_generated_esp32h2.rs index 0dc3afec27d..8dc25f39730 100644 --- a/esp-metadata-generated/src/_generated_esp32h2.rs +++ b/esp-metadata-generated/src/_generated_esp32h2.rs @@ -346,6 +346,15 @@ macro_rules! property { ("sha.dma") => { true }; + ("sdm.channel_count") => { + 4 + }; + ("sdm.channel_count", str) => { + stringify!(4) + }; + ("sdm.default_clock_source") => { + "pll_f48m" + }; ("sleep.light_sleep") => { true }; @@ -926,6 +935,18 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sdm_channel { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sdm_channel { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_sdm_channel!((0, GPIO_SD0)); + _for_each_inner_sdm_channel!((1, GPIO_SD1)); _for_each_inner_sdm_channel!((2, + GPIO_SD2)); _for_each_inner_sdm_channel!((3, GPIO_SD3)); + _for_each_inner_sdm_channel!((channels(0, GPIO_SD0), (1, GPIO_SD1), (2, + GPIO_SD2), (3, GPIO_SD3))); + }; +} +#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK @@ -2987,6 +3008,8 @@ macro_rules! implement_peripheral_clocks { Ecdsa, /// ETM peripheral clock signal Etm, + /// GPIO_SD peripheral clock signal + GpioSd, /// HMAC peripheral clock signal Hmac, /// I2C_EXT0 peripheral clock signal @@ -3044,6 +3067,7 @@ macro_rules! implement_peripheral_clocks { Self::Ecc, Self::Ecdsa, Self::Etm, + Self::GpioSd, Self::Hmac, Self::I2cExt0, Self::I2cExt1, @@ -3105,6 +3129,14 @@ macro_rules! implement_peripheral_clocks { .etm_conf() .modify(|_, w| w.etm_clk_en().bit(enable)); } + Peripheral::GpioSd => { + crate::peripherals::GPIO_SD::regs() + .clock_gate() + .modify(|_, w| w.clk_en().bit(enable)); + crate::peripherals::GPIO_SD::regs() + .sigmadelta_misc() + .modify(|_, w| w.function_clk_en().bit(enable)); + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .hmac_conf() @@ -3261,6 +3293,9 @@ macro_rules! implement_peripheral_clocks { .etm_conf() .modify(|_, w| w.etm_rst_en().bit(reset)); } + Peripheral::GpioSd => { + let _ = reset; + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .hmac_conf() diff --git a/esp-metadata-generated/src/_generated_esp32p4.rs b/esp-metadata-generated/src/_generated_esp32p4.rs index 4660f358b87..d333deea5e7 100644 --- a/esp-metadata-generated/src/_generated_esp32p4.rs +++ b/esp-metadata-generated/src/_generated_esp32p4.rs @@ -286,6 +286,15 @@ macro_rules! property { ("sha.dma") => { true }; + ("sdm.channel_count") => { + 8 + }; + ("sdm.channel_count", str) => { + stringify!(8) + }; + ("sdm.default_clock_source") => { + "pll_f80m" + }; ("sleep.light_sleep") => { false }; @@ -858,6 +867,22 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sdm_channel { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sdm_channel { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_sdm_channel!((0, GPIO_SD0)); + _for_each_inner_sdm_channel!((1, GPIO_SD1)); _for_each_inner_sdm_channel!((2, + GPIO_SD2)); _for_each_inner_sdm_channel!((3, GPIO_SD3)); + _for_each_inner_sdm_channel!((4, GPIO_SD4)); _for_each_inner_sdm_channel!((5, + GPIO_SD5)); _for_each_inner_sdm_channel!((6, GPIO_SD6)); + _for_each_inner_sdm_channel!((7, GPIO_SD7)); + _for_each_inner_sdm_channel!((channels(0, GPIO_SD0), (1, GPIO_SD1), (2, + GPIO_SD2), (3, GPIO_SD3), (4, GPIO_SD4), (5, GPIO_SD5), (6, GPIO_SD6), (7, + GPIO_SD7))); + }; +} +#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK @@ -2717,6 +2742,8 @@ macro_rules! implement_peripheral_clocks { Emac, /// GDMA peripheral clock signal Gdma, + /// GPIO_SD peripheral clock signal + GpioSd, /// HMAC peripheral clock signal Hmac, /// I2C0 peripheral clock signal @@ -2806,6 +2833,7 @@ macro_rules! implement_peripheral_clocks { Self::Ecdsa, Self::Emac, Self::Gdma, + Self::GpioSd, Self::Hmac, Self::I2c0, Self::I2c1, @@ -2894,6 +2922,14 @@ macro_rules! implement_peripheral_clocks { .soc_clk_ctrl1() .modify(|_, w| w.gdma_sys_clk_en().bit(enable)); } + Peripheral::GpioSd => { + crate::peripherals::GPIO_SD::regs() + .clock_gate() + .modify(|_, w| w.clk_en().bit(enable)); + crate::peripherals::GPIO_SD::regs() + .sigmadelta_misc() + .modify(|_, w| w.function_clk_en().bit(enable)); + } Peripheral::Hmac => { crate::peripherals::HP_SYS_CLKRST::regs() .soc_clk_ctrl1() @@ -3142,6 +3178,9 @@ macro_rules! implement_peripheral_clocks { .hp_rst_en0() .modify(|_, w| w.rst_en_gdma().bit(reset)); } + Peripheral::GpioSd => { + let _ = reset; + } Peripheral::Hmac => { crate::peripherals::HP_SYS_CLKRST::regs() .hp_rst_en2() @@ -3657,10 +3696,11 @@ macro_rules! for_each_peripheral { _for_each_inner_peripheral!((@ peri_type #[doc = "EFUSE peripheral singleton"] EFUSE <= EFUSE() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO peripheral singleton"] GPIO <= GPIO() (unstable))); - _for_each_inner_peripheral!((@ peri_type #[doc = "SYSTEM peripheral singleton"] - SYSTEM <= HP_SYS() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = - "HP_SYS peripheral singleton"] HP_SYS <= HP_SYS() (unstable))); - _for_each_inner_peripheral!((@ peri_type #[doc = + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO_SD peripheral singleton"] + GPIO_SD <= GPIO_SD() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc + = "SYSTEM peripheral singleton"] SYSTEM <= HP_SYS() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "HP_SYS peripheral singleton"] + HP_SYS <= HP_SYS() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = "HP_SYS_CLKRST peripheral singleton"] HP_SYS_CLKRST <= HP_SYS_CLKRST() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = "RNG peripheral singleton"] RNG <= LP_SYS() (unstable))); @@ -3798,6 +3838,7 @@ macro_rules! for_each_peripheral { _for_each_inner_peripheral!((DMA_CH1(unstable))); _for_each_inner_peripheral!((DMA_CH2(unstable))); _for_each_inner_peripheral!((GPIO(unstable))); + _for_each_inner_peripheral!((GPIO_SD(unstable))); _for_each_inner_peripheral!((SYSTEM(unstable))); _for_each_inner_peripheral!((HP_SYS(unstable))); _for_each_inner_peripheral!((HP_SYS_CLKRST(unstable))); @@ -3983,19 +4024,21 @@ macro_rules! for_each_peripheral { disable_dma_out_interrupt }) (unstable)), (@ peri_type #[doc = "EFUSE peripheral singleton"] EFUSE <= EFUSE() (unstable)), (@ peri_type #[doc = "GPIO peripheral singleton"] GPIO <= GPIO() (unstable)), (@ peri_type #[doc = - "SYSTEM peripheral singleton"] SYSTEM <= HP_SYS() (unstable)), (@ peri_type #[doc - = "HP_SYS peripheral singleton"] HP_SYS <= HP_SYS() (unstable)), (@ peri_type - #[doc = "HP_SYS_CLKRST peripheral singleton"] HP_SYS_CLKRST <= HP_SYS_CLKRST() - (unstable)), (@ peri_type #[doc = "RNG peripheral singleton"] RNG <= LP_SYS() - (unstable)), (@ peri_type #[doc = "INTERRUPT_CORE0 peripheral singleton"] - INTERRUPT_CORE0 <= INTERRUPT_CORE0() (unstable)), (@ peri_type #[doc = - "INTERRUPT_CORE1 peripheral singleton"] INTERRUPT_CORE1 <= INTERRUPT_CORE1() - (unstable)), (@ peri_type #[doc = "LP_I2C_ANA_MST peripheral singleton"] - LP_I2C_ANA_MST <= LP_I2C_ANA_MST() (unstable)), (@ peri_type #[doc = - "CLIC peripheral singleton"] CLIC <= CLIC() (unstable)), (@ peri_type #[doc = - "IO_MUX peripheral singleton"] IO_MUX <= IO_MUX() (unstable)), (@ peri_type #[doc - = "LP_AON peripheral singleton"] LP_AON <= LP_SYS() (unstable)), (@ peri_type - #[doc = "LP_AON_CLKRST peripheral singleton"] LP_AON_CLKRST <= LP_AON_CLKRST() + "GPIO_SD peripheral singleton"] GPIO_SD <= GPIO_SD() (unstable)), (@ peri_type + #[doc = "SYSTEM peripheral singleton"] SYSTEM <= HP_SYS() (unstable)), (@ + peri_type #[doc = "HP_SYS peripheral singleton"] HP_SYS <= HP_SYS() (unstable)), + (@ peri_type #[doc = "HP_SYS_CLKRST peripheral singleton"] HP_SYS_CLKRST <= + HP_SYS_CLKRST() (unstable)), (@ peri_type #[doc = "RNG peripheral singleton"] RNG + <= LP_SYS() (unstable)), (@ peri_type #[doc = + "INTERRUPT_CORE0 peripheral singleton"] INTERRUPT_CORE0 <= INTERRUPT_CORE0() + (unstable)), (@ peri_type #[doc = "INTERRUPT_CORE1 peripheral singleton"] + INTERRUPT_CORE1 <= INTERRUPT_CORE1() (unstable)), (@ peri_type #[doc = + "LP_I2C_ANA_MST peripheral singleton"] LP_I2C_ANA_MST <= LP_I2C_ANA_MST() + (unstable)), (@ peri_type #[doc = "CLIC peripheral singleton"] CLIC <= CLIC() + (unstable)), (@ peri_type #[doc = "IO_MUX peripheral singleton"] IO_MUX <= + IO_MUX() (unstable)), (@ peri_type #[doc = "LP_AON peripheral singleton"] LP_AON + <= LP_SYS() (unstable)), (@ peri_type #[doc = + "LP_AON_CLKRST peripheral singleton"] LP_AON_CLKRST <= LP_AON_CLKRST() (unstable)), (@ peri_type #[doc = "LP_SYS peripheral singleton"] LP_SYS <= LP_SYS() (unstable)), (@ peri_type #[doc = "LP_WDT peripheral singleton"] LP_WDT <= LP_WDT() (unstable)), (@ peri_type #[doc = "LPWR peripheral singleton"] LPWR @@ -4071,22 +4114,22 @@ macro_rules! for_each_peripheral { (GPIO35), (GPIO36), (GPIO37), (GPIO38), (GPIO39), (GPIO40), (GPIO41), (GPIO42), (GPIO43), (GPIO44), (GPIO45), (GPIO46), (GPIO47), (GPIO48), (GPIO49), (GPIO50), (GPIO51), (GPIO52), (GPIO53), (GPIO54), (DMA_CH0(unstable)), (DMA_CH1(unstable)), - (DMA_CH2(unstable)), (GPIO(unstable)), (SYSTEM(unstable)), (HP_SYS(unstable)), - (HP_SYS_CLKRST(unstable)), (RNG(unstable)), (INTERRUPT_CORE0(unstable)), - (INTERRUPT_CORE1(unstable)), (LP_I2C_ANA_MST(unstable)), (CLIC(unstable)), - (IO_MUX(unstable)), (LP_AON(unstable)), (LP_AON_CLKRST(unstable)), - (LP_SYS(unstable)), (LP_WDT(unstable)), (LPWR(unstable)), (PMU(unstable)), - (SYSTIMER(unstable)), (TIMG0(unstable)), (TIMG1(unstable)), (UART0(unstable)), - (UART1(unstable)), (UART2(unstable)), (UART3(unstable)), (UART4(unstable)), - (SPI2), (SPI3), (I2C0(unstable)), (I2C1(unstable)), (TWAI0(unstable)), - (TWAI1(unstable)), (TWAI2(unstable)), (PSRAM(unstable)), (DMA(unstable)), - (ETH(unstable)), (USB_DEVICE(unstable)), (SDHOST(unstable)), (LEDC(unstable)), - (MCPWM0(unstable)), (MCPWM1(unstable)), (PCNT(unstable)), (RMT(unstable)), - (ADC(unstable)), (AES(unstable)), (SHA(unstable)), (RSA(unstable)), - (ECC(unstable)), (USB_FS(unstable)), (USB_HS(unstable)), - (SW_INTERRUPT(unstable)), (CPU_CTRL(unstable)))); - _for_each_inner_peripheral!((dma_eligible(SPI2, Spi2, 1), (SPI3, Spi3, 2), (AES, - Aes, 4), (SHA, Sha, 5))); + (DMA_CH2(unstable)), (GPIO(unstable)), (GPIO_SD(unstable)), (SYSTEM(unstable)), + (HP_SYS(unstable)), (HP_SYS_CLKRST(unstable)), (RNG(unstable)), + (INTERRUPT_CORE0(unstable)), (INTERRUPT_CORE1(unstable)), + (LP_I2C_ANA_MST(unstable)), (CLIC(unstable)), (IO_MUX(unstable)), + (LP_AON(unstable)), (LP_AON_CLKRST(unstable)), (LP_SYS(unstable)), + (LP_WDT(unstable)), (LPWR(unstable)), (PMU(unstable)), (SYSTIMER(unstable)), + (TIMG0(unstable)), (TIMG1(unstable)), (UART0(unstable)), (UART1(unstable)), + (UART2(unstable)), (UART3(unstable)), (UART4(unstable)), (SPI2), (SPI3), + (I2C0(unstable)), (I2C1(unstable)), (TWAI0(unstable)), (TWAI1(unstable)), + (TWAI2(unstable)), (PSRAM(unstable)), (DMA(unstable)), (ETH(unstable)), + (USB_DEVICE(unstable)), (SDHOST(unstable)), (LEDC(unstable)), (MCPWM0(unstable)), + (MCPWM1(unstable)), (PCNT(unstable)), (RMT(unstable)), (ADC(unstable)), + (AES(unstable)), (SHA(unstable)), (RSA(unstable)), (ECC(unstable)), + (USB_FS(unstable)), (USB_HS(unstable)), (SW_INTERRUPT(unstable)), + (CPU_CTRL(unstable)))); _for_each_inner_peripheral!((dma_eligible(SPI2, Spi2, 1), + (SPI3, Spi3, 2), (AES, Aes, 4), (SHA, Sha, 5))); }; } /// This macro can be used to generate code for each `GPIOn` instance. diff --git a/esp-metadata-generated/src/_generated_esp32s2.rs b/esp-metadata-generated/src/_generated_esp32s2.rs index d497cfced08..a68552e99dc 100644 --- a/esp-metadata-generated/src/_generated_esp32s2.rs +++ b/esp-metadata-generated/src/_generated_esp32s2.rs @@ -316,6 +316,15 @@ macro_rules! property { ("sha.dma") => { true }; + ("sdm.channel_count") => { + 8 + }; + ("sdm.channel_count", str) => { + stringify!(8) + }; + ("sdm.default_clock_source") => { + "apb" + }; ("sleep.light_sleep") => { true }; @@ -805,6 +814,22 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sdm_channel { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sdm_channel { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_sdm_channel!((0, GPIO_SD0)); + _for_each_inner_sdm_channel!((1, GPIO_SD1)); _for_each_inner_sdm_channel!((2, + GPIO_SD2)); _for_each_inner_sdm_channel!((3, GPIO_SD3)); + _for_each_inner_sdm_channel!((4, GPIO_SD4)); _for_each_inner_sdm_channel!((5, + GPIO_SD5)); _for_each_inner_sdm_channel!((6, GPIO_SD6)); + _for_each_inner_sdm_channel!((7, GPIO_SD7)); + _for_each_inner_sdm_channel!((channels(0, GPIO_SD0), (1, GPIO_SD1), (2, + GPIO_SD2), (3, GPIO_SD3), (4, GPIO_SD4), (5, GPIO_SD5), (6, GPIO_SD6), (7, + GPIO_SD7))); + }; +} +#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK @@ -3121,6 +3146,8 @@ macro_rules! implement_peripheral_clocks { DedicatedGpio, /// DS peripheral clock signal Ds, + /// GPIO_SD peripheral clock signal + GpioSd, /// HMAC peripheral clock signal Hmac, /// I2C_EXT0 peripheral clock signal @@ -3185,6 +3212,7 @@ macro_rules! implement_peripheral_clocks { Self::CryptoDma, Self::DedicatedGpio, Self::Ds, + Self::GpioSd, Self::Hmac, Self::I2cExt0, Self::I2cExt1, @@ -3245,6 +3273,14 @@ macro_rules! implement_peripheral_clocks { .perip_clk_en1() .modify(|_, w| w.crypto_ds_clk_en().bit(enable)); } + Peripheral::GpioSd => { + crate::peripherals::GPIO_SD::regs() + .clock_gate() + .modify(|_, w| w.clk_en().bit(enable)); + crate::peripherals::GPIO_SD::regs() + .sigmadelta_misc() + .modify(|_, w| w.function_clk_en().bit(enable)); + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .perip_clk_en1() @@ -3416,6 +3452,9 @@ macro_rules! implement_peripheral_clocks { .perip_rst_en1() .modify(|_, w| w.crypto_ds_rst().bit(reset)); } + Peripheral::GpioSd => { + let _ = reset; + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .perip_rst_en1() diff --git a/esp-metadata-generated/src/_generated_esp32s3.rs b/esp-metadata-generated/src/_generated_esp32s3.rs index d2b1b779d85..fbbd33a59f9 100644 --- a/esp-metadata-generated/src/_generated_esp32s3.rs +++ b/esp-metadata-generated/src/_generated_esp32s3.rs @@ -337,6 +337,15 @@ macro_rules! property { ("sha.dma") => { true }; + ("sdm.channel_count") => { + 8 + }; + ("sdm.channel_count", str) => { + stringify!(8) + }; + ("sdm.default_clock_source") => { + "apb" + }; ("sleep.light_sleep") => { true }; @@ -841,6 +850,22 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sdm_channel { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sdm_channel { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_sdm_channel!((0, GPIO_SD0)); + _for_each_inner_sdm_channel!((1, GPIO_SD1)); _for_each_inner_sdm_channel!((2, + GPIO_SD2)); _for_each_inner_sdm_channel!((3, GPIO_SD3)); + _for_each_inner_sdm_channel!((4, GPIO_SD4)); _for_each_inner_sdm_channel!((5, + GPIO_SD5)); _for_each_inner_sdm_channel!((6, GPIO_SD6)); + _for_each_inner_sdm_channel!((7, GPIO_SD7)); + _for_each_inner_sdm_channel!((channels(0, GPIO_SD0), (1, GPIO_SD1), (2, + GPIO_SD2), (3, GPIO_SD3), (4, GPIO_SD4), (5, GPIO_SD5), (6, GPIO_SD6), (7, + GPIO_SD7))); + }; +} +#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK @@ -3145,6 +3170,8 @@ macro_rules! implement_peripheral_clocks { Dma, /// DS peripheral clock signal Ds, + /// GPIO_SD peripheral clock signal + GpioSd, /// HMAC peripheral clock signal Hmac, /// I2C_EXT0 peripheral clock signal @@ -3217,6 +3244,7 @@ macro_rules! implement_peripheral_clocks { Self::DedicatedGpio, Self::Dma, Self::Ds, + Self::GpioSd, Self::Hmac, Self::I2cExt0, Self::I2cExt1, @@ -3274,6 +3302,14 @@ macro_rules! implement_peripheral_clocks { .perip_clk_en1() .modify(|_, w| w.crypto_ds_clk_en().bit(enable)); } + Peripheral::GpioSd => { + crate::peripherals::GPIO_SD::regs() + .clock_gate() + .modify(|_, w| w.clk_en().bit(enable)); + crate::peripherals::GPIO_SD::regs() + .sigmadelta_misc() + .modify(|_, w| w.function_clk_en().bit(enable)); + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .perip_clk_en1() @@ -3443,6 +3479,9 @@ macro_rules! implement_peripheral_clocks { .perip_rst_en1() .modify(|_, w| w.crypto_ds_rst().bit(reset)); } + Peripheral::GpioSd => { + let _ = reset; + } Peripheral::Hmac => { crate::peripherals::SYSTEM::regs() .perip_rst_en1() diff --git a/esp-metadata/devices/esp32.toml b/esp-metadata/devices/esp32.toml index 332183eb9f6..79366364fb4 100644 --- a/esp-metadata/devices/esp32.toml +++ b/esp-metadata/devices/esp32.toml @@ -297,6 +297,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "Ledc" }, { name = "Pcnt" }, { name = "Rmt" }, + { name = "GpioSd", template_params = { clk_en_template = "let _ = enable;", rst_template = "let _ = reset;" } }, { name = "Uhci0" }, { name = "I2cExt0" }, { name = "Spi2" }, @@ -834,7 +835,10 @@ support_status = "partial" algo = { sha1 = 0, sha256 = 0, sha384 = 0, sha512 = 0 } # fake mode bits, ESP32 has separate register sets [device.sdm] -support_status = { status = "not_supported", issue = 2370 } +support_status = "partial" +channel_count = 8 +clock_sources = ["apb"] +default_clock_source = "apb" [device.spi_master] version = 1 diff --git a/esp-metadata/devices/esp32c3.toml b/esp-metadata/devices/esp32c3.toml index e0c7b31a6c3..e046529d03c 100644 --- a/esp-metadata/devices/esp32c3.toml +++ b/esp-metadata/devices/esp32c3.toml @@ -224,6 +224,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "Timg0", template_params = { peripheral = "timergroup" }, keep_enabled = true }, { name = "Ledc" }, { name = "Rmt" }, + { name = "GpioSd", template_params = { clk_en_template = "crate::peripherals::GPIO_SD::regs().clock_gate().modify(|_, w| w.clk_en().bit(enable)); crate::peripherals::GPIO_SD::regs().sigmadelta_misc().modify(|_, w| w.function_clk_en().bit(enable));", rst_template = "let _ = reset;" } }, { name = "Uhci0" }, { name = "I2cExt0" }, { name = "Spi2" }, @@ -487,7 +488,10 @@ dma = true algo = { sha1 = 0, sha224 = 1, sha256 = 2 } [device.sdm] -support_status = { status = "not_supported", issue = 2370 } +support_status = "partial" +channel_count = 4 +clock_sources = ["apb"] +default_clock_source = "apb" [device.spi_master] version = 3 diff --git a/esp-metadata/devices/esp32c5.toml b/esp-metadata/devices/esp32c5.toml index 5fec9d08bc2..87f490f2774 100644 --- a/esp-metadata/devices/esp32c5.toml +++ b/esp-metadata/devices/esp32c5.toml @@ -264,6 +264,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "I2s0", template_params = { peripheral = "i2s" } }, { name = "Pcnt" }, { name = "Rmt" }, + { name = "GpioSd", template_params = { clk_en_template = "crate::peripherals::GPIO_SD::regs().clock_gate().modify(|_, w| w.clk_en().bit(enable)); crate::peripherals::GPIO_SD::regs().sigmadelta_misc().modify(|_, w| w.sigmadelta_clk_en().bit(enable));", rst_template = "let _ = reset;" } }, { name = "Systimer", keep_enabled = true }, # can be clocked from XTAL_CLK or RC_FAST_CLK, the latter has no divider? { name = "ApbSarAdc", template_params = { peripheral = "saradc", clk_en_field = "saradc_reg_clk_en", rst_field = "saradc_reg_rst_en" }, keep_enabled = true }, { name = "ParlIo", template_params = { clk_en_field = "parl_clk_en", rst_field = "parl_rst_en" } }, @@ -658,7 +659,10 @@ support_status = { status = "not_supported", issue = 5164 } support_status = { status = "not_supported", issue = 884 } [device.sdm] -support_status = { status = "not_supported", issue = 2370 } +support_status = "partial" +channel_count = 4 +clock_sources = ["xtal", "pll_f80m"] +default_clock_source = "pll_f80m" [device.lp_uart] support_status = { status = "not_supported", issue = 5155 } diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 79e0ce5bcba..df4400d8ac7 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -299,6 +299,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "Hmac" }, #{ name = "Iomux" }, #{ name = "MemMonitor" }, + { name = "GpioSd", template_params = { clk_en_template = "crate::peripherals::GPIO_SD::regs().clock_gate().modify(|_, w| w.clk_en().bit(enable)); crate::peripherals::GPIO_SD::regs().sigmadelta_misc().modify(|_, w| w.function_clk_en().bit(enable));", rst_template = "let _ = reset;" } }, { name = "Trace0", template_params = { peripheral = "trace" } }, #{ name = "Assist" }, #{ name = "Cache" }, @@ -693,7 +694,10 @@ dma = true algo = { sha1 = 0, sha224 = 1, sha256 = 2 } [device.sdm] -support_status = { status = "not_supported", issue = 2370 } +support_status = "partial" +channel_count = 4 +clock_sources = ["xtal", "pll_f80m"] +default_clock_source = "pll_f80m" [device.spi_master] version = 3 diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index 4ebc5dc7c93..36a526f704c 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -252,6 +252,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "Ecdsa" }, #{ name = "Iomux" }, #{ name = "MemMonitor" }, + { name = "GpioSd", template_params = { clk_en_template = "crate::peripherals::GPIO_SD::regs().clock_gate().modify(|_, w| w.clk_en().bit(enable)); crate::peripherals::GPIO_SD::regs().sigmadelta_misc().modify(|_, w| w.function_clk_en().bit(enable));", rst_template = "let _ = reset;" } }, { name = "Trace0", template_params = { peripheral = "trace" } }, #{ name = "Assist" }, #{ name = "Cache" }, @@ -591,7 +592,10 @@ dma = true algo = { sha1 = 0, sha224 = 1, sha256 = 2 } [device.sdm] -support_status = { status = "not_supported", issue = 2370 } +support_status = "partial" +channel_count = 4 +clock_sources = ["xtal", "pll_f48m"] +default_clock_source = "pll_f48m" [device.ecdsa] support_status = { status = "not_supported", issue = 5444 } diff --git a/esp-metadata/devices/esp32p4.toml b/esp-metadata/devices/esp32p4.toml index 20163d98d4a..4a8024cfa3e 100644 --- a/esp-metadata/devices/esp32p4.toml +++ b/esp-metadata/devices/esp32p4.toml @@ -196,6 +196,7 @@ clocks = { system_clocks = { clock_tree = [ # PWM/Counter/RMT -- LCD/CAM clock gate lives in SOC_CLK_CTRL3 (not modelled in current PAC), keep stub. { name = "Ledc", template_params = { default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_ledc" } }, { name = "Pcnt", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "pcnt_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_pcnt" } }, + { name = "GpioSd", template_params = { clk_en_template = "crate::peripherals::GPIO_SD::regs().clock_gate().modify(|_, w| w.clk_en().bit(enable)); crate::peripherals::GPIO_SD::regs().sigmadelta_misc().modify(|_, w| w.function_clk_en().bit(enable));", rst_template = "let _ = reset;" } }, { name = "Mcpwm0", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "mcpwm0_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_pwm0" } }, { name = "Mcpwm1", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "mcpwm1_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_pwm1" } }, # NOTE: `rmt_sys_clk_en` despite the name lives on SOC_CLK_CTRL2, not CTRL1. @@ -247,6 +248,7 @@ peripherals = [ # Minimal set for esp-hal compilation { name = "EFUSE", hidden = true }, { name = "GPIO" }, + { name = "GPIO_SD" }, { name = "SYSTEM", pac = "HP_SYS" }, { name = "HP_SYS" }, { name = "HP_SYS_CLKRST" }, @@ -460,7 +462,10 @@ support_status = "not_supported" # SDIO host [device.sd_slave] support_status = "not_supported" [device.sdm] -support_status = { status = "not_supported", issue = 2370 } +support_status = "partial" +channel_count = 8 +clock_sources = ["xtal", "pll_f80m"] +default_clock_source = "pll_f80m" [device.sleep] support_status = "not_supported" # PMU eco5 sleep -- placeholder TODO in esp-hal [device.spi_slave] diff --git a/esp-metadata/devices/esp32s2.toml b/esp-metadata/devices/esp32s2.toml index 69b52a0c8e1..75c0df069eb 100644 --- a/esp-metadata/devices/esp32s2.toml +++ b/esp-metadata/devices/esp32s2.toml @@ -241,6 +241,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "Ledc" }, { name = "Pcnt" }, { name = "Rmt" }, + { name = "GpioSd", template_params = { clk_en_template = "crate::peripherals::GPIO_SD::regs().clock_gate().modify(|_, w| w.clk_en().bit(enable)); crate::peripherals::GPIO_SD::regs().sigmadelta_misc().modify(|_, w| w.function_clk_en().bit(enable));", rst_template = "let _ = reset;" } }, { name = "Uhci0" }, { name = "I2cExt0" }, { name = "Spi2" }, @@ -616,7 +617,10 @@ dma = true algo = { sha1 = 0, sha224 = 1, sha256 = 2, sha384 = 3, sha512 = 4, sha512_224 = 5, sha512_256 = 6, sha512_t = 7 } [device.sdm] -support_status = { status = "not_supported", issue = 2370 } +support_status = "partial" +channel_count = 8 +clock_sources = ["apb"] +default_clock_source = "apb" [device.spi_master] version = 2 diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index b2d1a37abc2..178630ef2d0 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -256,6 +256,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "Ledc" }, { name = "Pcnt" }, { name = "Rmt" }, + { name = "GpioSd", template_params = { clk_en_template = "crate::peripherals::GPIO_SD::regs().clock_gate().modify(|_, w| w.clk_en().bit(enable)); crate::peripherals::GPIO_SD::regs().sigmadelta_misc().modify(|_, w| w.function_clk_en().bit(enable));", rst_template = "let _ = reset;" } }, { name = "Uhci0" }, { name = "I2cExt0" }, { name = "Spi2" }, @@ -808,7 +809,10 @@ dma = true algo = { sha1 = 0, sha224 = 1, sha256 = 2, sha384 = 3, sha512 = 4, sha512_224 = 5, sha512_256 = 6, sha512_t = 7 } [device.sdm] -support_status = { status = "not_supported", issue = 2370 } +support_status = "partial" +channel_count = 8 +clock_sources = ["apb"] +default_clock_source = "apb" [device.spi_master] version = 3 diff --git a/esp-metadata/src/cfg.rs b/esp-metadata/src/cfg.rs index bf52e004e0e..a8da9d0d626 100644 --- a/esp-metadata/src/cfg.rs +++ b/esp-metadata/src/cfg.rs @@ -6,6 +6,7 @@ pub(crate) mod i2c_master; pub(crate) mod interrupt; pub(crate) mod rmt; pub(crate) mod rsa; +pub(crate) mod sdm; pub(crate) mod sha; pub(crate) mod soc; pub(crate) mod spi_master; @@ -20,6 +21,7 @@ pub(crate) use gpio::*; pub(crate) use i2c_master::*; pub(crate) use interrupt::*; pub(crate) use rmt::*; +pub(crate) use sdm::*; pub(crate) use sha::*; pub(crate) use soc::*; pub(crate) use spi_master::*; @@ -643,7 +645,15 @@ driver_configs![ SdmProperties { driver: sdm, name: "SDM", - properties: {} + properties: { + /// Number of sigma-delta channels. + channel_count: SdmChannels, + /// Supported source clocks for the shared SDM/IO_MUX clock. + #[serde(default)] + clock_sources: Vec, + /// Default source clock for the shared SDM/IO_MUX clock. + default_clock_source: String, + } }, SleepProperties { driver: sleep, diff --git a/esp-metadata/src/cfg/sdm.rs b/esp-metadata/src/cfg/sdm.rs new file mode 100644 index 00000000000..fcde4d1ea50 --- /dev/null +++ b/esp-metadata/src/cfg/sdm.rs @@ -0,0 +1,50 @@ +use proc_macro2::TokenStream; +use quote::format_ident; + +use crate::{cfg::GenericProperty, generate_for_each_macro, number}; + +#[derive(Clone, Debug)] +pub struct SdmChannels { + count: u32, +} + +impl<'de> serde::Deserialize<'de> for SdmChannels { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Ok(Self { + count: u32::deserialize(deserializer)?, + }) + } +} + +impl GenericProperty for SdmChannels { + fn macros(&self) -> Option { + let channels = (0..self.count) + .map(|channel| { + let channel = number(channel); + let signal = format_ident!("GPIO_SD{channel}"); + quote::quote! { #channel, #signal } + }) + .collect::>(); + + Some(generate_for_each_macro( + "sdm_channel", + &[("channels", &channels)], + )) + } + + fn property_macro_branches(&self) -> TokenStream { + let count = number(self.count); + + quote::quote! { + ("sdm.channel_count") => { + #count + }; + ("sdm.channel_count", str) => { + stringify!(#count) + }; + } + } +} diff --git a/examples/peripheral/sdm/.cargo/config.toml b/examples/peripheral/sdm/.cargo/config.toml new file mode 100644 index 00000000000..44dacc4278b --- /dev/null +++ b/examples/peripheral/sdm/.cargo/config.toml @@ -0,0 +1,24 @@ +[target.'cfg(target_arch = "riscv32")'] +runner = "espflash flash --monitor" +rustflags = [ + "-C", "link-arg=-Tlinkall.x", + "-C", "force-frame-pointers", +] + +[target.'cfg(target_arch = "xtensa")'] +runner = "espflash flash --monitor" +rustflags = [ + # GNU LD + "-C", "link-arg=-Wl,-Tlinkall.x", + "-C", "link-arg=-nostartfiles", + + # LLD + # "-C", "link-arg=-Tlinkall.x", + # "-C", "linker=rust-lld", +] + +[env] +ESP_LOG = "info" + +[unstable] +build-std = ["core", "alloc"] diff --git a/examples/peripheral/sdm/Cargo.toml b/examples/peripheral/sdm/Cargo.toml new file mode 100644 index 00000000000..ff94441bf35 --- /dev/null +++ b/examples/peripheral/sdm/Cargo.toml @@ -0,0 +1,62 @@ +[package] +name = "sdm" +version = "0.0.0" +edition = "2024" +publish = false + +[dependencies] +esp-backtrace = { path = "../../../esp-backtrace", features = [ + "panic-handler", + "println", +] } +esp-bootloader-esp-idf = { path = "../../../esp-bootloader-esp-idf" } +esp-hal = { path = "../../../esp-hal", features = ["log-04", "unstable"] } +esp-println = { path = "../../../esp-println", features = ["log-04"] } + +[features] +esp32 = [ + "esp-backtrace/esp32", + "esp-bootloader-esp-idf/esp32", + "esp-hal/esp32", +] +esp32c3 = [ + "esp-backtrace/esp32c3", + "esp-bootloader-esp-idf/esp32c3", + "esp-hal/esp32c3", +] +esp32c5 = [ + "esp-backtrace/esp32c5", + "esp-bootloader-esp-idf/esp32c5", + "esp-hal/esp32c5", +] +esp32c6 = [ + "esp-backtrace/esp32c6", + "esp-bootloader-esp-idf/esp32c6", + "esp-hal/esp32c6", +] +esp32h2 = [ + "esp-backtrace/esp32h2", + "esp-bootloader-esp-idf/esp32h2", + "esp-hal/esp32h2", +] +esp32p4 = [ + "esp-backtrace/esp32p4", + "esp-bootloader-esp-idf/esp32p4", + "esp-hal/esp32p4", +] +esp32s2 = [ + "esp-backtrace/esp32s2", + "esp-bootloader-esp-idf/esp32s2", + "esp-hal/esp32s2", +] +esp32s3 = [ + "esp-backtrace/esp32s3", + "esp-bootloader-esp-idf/esp32s3", + "esp-hal/esp32s3", +] + +[profile.release] +debug = true +debug-assertions = true +lto = "fat" +codegen-units = 1 diff --git a/examples/peripheral/sdm/src/main.rs b/examples/peripheral/sdm/src/main.rs new file mode 100644 index 00000000000..de6c0ff37e6 --- /dev/null +++ b/examples/peripheral/sdm/src/main.rs @@ -0,0 +1,39 @@ +//! This example shows how to generate a sigma-delta output signal. +//! +//! The following wiring is assumed: +//! - SDM output => GPIO2 + +#![no_std] +#![no_main] + +use esp_backtrace as _; +use esp_hal::{delay::Delay, main, sdm::Sdm, time::Rate}; +use esp_println::print; + +esp_bootloader_esp_idf::esp_app_desc!(); + +#[main] +fn main() -> ! { + esp_println::logger::init_logger_from_env(); + let peripherals = esp_hal::init(esp_hal::Config::default()); + + let sdm = Sdm::new(peripherals.GPIO_SD); + let mut channel = sdm + .channel0 + .with_frequency(Rate::from_khz(500)) + .unwrap() + .with_pulse_density(0) + .connect(peripherals.GPIO2) + .unwrap(); + + let delay = Delay::new(); + let mut duty = 0; + + loop { + channel.set_duty(duty); + print!("SDM duty: {duty:3}\r"); + + duty = duty.wrapping_add(1); + delay.delay_millis(100); + } +}