From 5b402d249bb0887bc2cfaafc3e9ba627245127b5 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Sat, 28 Mar 2026 12:34:22 -0600 Subject: [PATCH 01/37] Added capture channel and capture timer I will be testing these for any issures on my esp32-s3 --- esp-hal/src/mcpwm/capture.rs | 235 +++++++++++++++++++++++++++++++++++ esp-hal/src/mcpwm/mod.rs | 39 +++++- 2 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 esp-hal/src/mcpwm/capture.rs diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs new file mode 100644 index 00000000000..01b58d49d40 --- /dev/null +++ b/esp-hal/src/mcpwm/capture.rs @@ -0,0 +1,235 @@ +//! # MCPWM Capture Module +//! +//! ## Overview +//! The `Capture` is resposible for managing the recording of the +//! capture timer during specific software or hardware triggered +//! 'capture' events. +//! +//! Capture events can be triggered in 2 ways: +//! During a falling and/or Rising edge of a preconfigured GPIO pin. +//! Software triggered captures though the Capture::capture_time() function. +//! +//! ## Configuration +//! This module provides the flexiability of configuring any GPIO pin as an input +//! for capturing the rising and/or falling edge of a signal. This module allows +//! for the ability to trigger software captures, essentially capturing the current +//! time in the capture clock. + +use core::marker::PhantomData; +use core::panic; + +use esp_sync::RawMutex; + +use super::PeripheralGuard; +use crate::gpio::{InputSignal, interconnect::PeripheralInput}; +use crate::mcpwm::{PwmClockGuard, PwmPeripheral}; + +#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +enum EdgeCaptureEvent { + FallingEdge, + RisingEdge, + EitherEdge, +} + +#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +enum CapturedEdge { + FallingEdge, + RisingEdge, +} + +static MUTEX: RawMutex = RawMutex::new(); + +/// The MCPWM Capture Timer +/// This timer is specific to the 3 channels +pub struct CaptureTimer<'d, PWM> { + phantom: PhantomData<&'d PWM>, + _guard: PeripheralGuard, + _pwm_clock_guard: PwmClockGuard, +} + +impl CaptureTimer<'d, PWM> { + pub(super) fn new(guard: PeripheralGuard) -> Self { + Timer { + phantom: PhantomData, + _guard: guard, + _pwm_clock_guard: PwmClockGuard::new::(), + } + } + + pub fn start(&mut self) { + // SAFETY: + // We write to our MCPWM_CAP_TIMER_CFG_REG register + let block = unsafe { &*PWM::block() }; + + block.cap_timer_cfg().write(|w| w.cap_timer_en().set_bit()); + } + + pub fn pause(&mut self) { + // SAFETY: + // We write to our MCPWM_CAP_TIMER_CFG_REG register + let block = unsafe { &*PWM::block() }; + + block + .cap_timer_cfg() + .write(|w| w.cap_timer_en().clear_bit()); + } +} + +/// A MCPWM Capture Channel +/// +/// The MCPWM Capture Channel has the following functions: +/// * +pub struct CaptureChannel<'d, const CHAN: usize, PWM> { + phantom: PhantomData<&'d PWM>, + _guard: PeripheralGuard, + _pwm_clock_guard: PwmClockGuard, +} + +impl CaptureChannel { + pub(super) fn new(guard: PeripheralGuard) -> Self { + Timer { + phantom: PhantomData, + _guard: guard, + _pwm_clock_guard: PwmClockGuard::new::(), + } + } + + /// Enables capturing on this channel + pub fn enable(&mut self) { + // SAFETY: + // We only write to our MCPWM_CAP_CHx_CFG_REG register + let block = unsafe { &*PWM::block() }; + + block.cap_ch_cfg(CHAN).write(|w| w.en().set_bit()); + } + + /// Disable capturing on this channel + pub fn disable(&mut self) { + // SAFETY: + // We only write to our MCPWM_CAP_CHx_CFG_REG register + let block = unsafe { &*PWM::block() }; + + block.cap_ch_cfg(CHAN).write(|w| w.en().clear_bit()); + } + + /// Set the capture signal (pin/high/low) for this channel + pub fn set_capture_signal(&mut self, source: impl PeripheralInput<'d>) { + let signal = PWM::capture_input_signal::(); + + if signal as usize <= property!("gpio.input_signal_max") { + let source = source.into(); + source.set_input_enable(true); + signal.connect_to(&source); + } else { + warn!("Signal {:?} out of range", signal); + } + } + + /// Sets the capture channel to listen to captures on specific edge events + /// This channel can listen to Falling, and/or Rising edges on any of the GPIO pins. + pub fn listen(&mut self, edge_capture_event: EdgeCaptureEvent) { + // SAFETY: + // We write to our MCPWM_CAP_CHx_CFG_REG register + // And we are modifying a shared peripheral interrupt enable register + let block = unsafe { &*PWM::block() }; + + // Maps the edge capture event to the proper bits in the capture + // configuration register. + // + // In the MCPWM_CAP_CHx_CFG_REG register within the + // the MCPWM_CAP0_MODE field of the register Bits[1..=2] discribe + // the falling and/or rising edge capture + // + // The 2 bits within the MCPWM_CAPx_MODE field are as of the following + // Bits[0] -> Selects weather or not Falling Edges should be captured + // Bits[1] -> Selects weather or not Rising Edges should be captured + // + // Has been checked for the following chips: ESP32s3 + // + // Either of them can be on or off allowing for the 4 configurations seen below. + + // Note: would be nice to be able to set this via an enum like the PCNT register block :) + match edge_capture_event { + EdgeCaptureEvent::FallingEdge => unsafe { + // Bit0 set -> Falling edges + block.cap_ch_cfg(CHAN).write(|w| w.mode().bits(0b01)); + }, + EdgeCaptureEvent::RisingEdge => unsafe { + // Bit1 set -> Rising edges + block.cap_ch_cfg(CHAN).write(|w| w.mode().bits(0b10)); + }, + EdgeCaptureEvent::EitherEdge => unsafe { + // Bit0 and Bit1 set -> Either edge + block.cap_ch_cfg(CHAN).write(|w| w.mode().bits(0b11)); + }, + }; + + // Enable the capture interrupt + MUTEX.lock(|| { + // Note: would be nice to be able to get interrupts from channel number + match CHAN { + 0 => block.int_ena().modify(|r, w| w.cap0().set_bit()), + 1 => block.int_ena().modify(|r, w| w.cap1().set_bit()), + 2 => block.int_ena().modify(|r, w| w.cap2().set_bit()), + _ => unreachable!(), + }; + }); + } + + /// Stops listening to events on this channel + pub fn unlisten(&mut self) { + // SAFTEY: + // We are accessing a SHARED peripheral interrupt enable register + let _ = self._guard; + let block = unsafe { &*PWM::block() }; + + // We can unlisten from events simply by disabling the interrupt + MUTEX.lock(|| { + // Note: would be nice to be able to get interrupts from channel number + match CHAN { + 0 => block.int_ena().modify(|r, w| w.cap0().clear_bit()), + 1 => block.int_ena().modify(|r, w| w.cap1().clear_bit()), + 2 => block.int_ena().modify(|r, w| w.cap2().clear_bit()), + _ => unreachable!(), + }; + }); + } + + pub fn is_interupt_set(&mut self) -> bool { + let block = unsafe { &*PWM::block() }; + + // Note: would be nice to be able to get interrupts from channel number + match CHAN { + 0 => block.int_raw().read().cap0().bit(), + 1 => block.int_raw().read().cap1().bit(), + 2 => block.int_raw().read().cap2().bit(), + _ => unreachable!(), + } + } + + /// Gets the last captured edge on this channel + pub fn get_captured_edge(&mut self) -> CapturedEdge { + // SAFETY: + // We only read from our MCPWM_CAP_STATUS_REG register + let block = unsafe { &*PWM::block() }; + + // Read the last edge status from the either of the 3 channels + // the bit that we read will indicate if it was a faling edge. + + // Note: would be nice to be able to get the capture status from channel number + let is_falling_edge = match CHAN { + 0 => block.cap_status().read().cap0_edge().bit(), + 1 => block.cap_status().read().cap1_edge().bit(), + 2 => block.cap_status().read().cap2_edge().bit(), + _ => unreachable!(), + }; + + if is_falling_edge { + CapturedEdge::FallingEdge + } else { + CapturedEdge::RisingEdge + } + } +} diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index ab13e8b4d7e..d70ac382f9c 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -87,8 +87,11 @@ use operator::Operator; use timer::Timer; +#[cfg(soc_has_mcpwm0)] +use crate::gpio::InputSignal; use crate::{ gpio::OutputSignal, + mcpwm::capture::{CaptureChannel, CaptureTimer}, pac, private::OnDrop, soc::clocks::{self, ClockTree}, @@ -101,6 +104,8 @@ pub mod operator; /// MCPWM timers pub mod timer; +pub mod capture; + type RegisterBlock = pac::mcpwm0::RegisterBlock; #[allow(dead_code)] // Field is seemingly unused but we rely on its Drop impl @@ -141,6 +146,14 @@ pub struct McPwm<'d, PWM> { pub operator1: Operator<'d, 1, PWM>, /// Operator2 pub operator2: Operator<'d, 2, PWM>, + /// Capture Timer + pub capture_timer: CaptureTimer<'d, PWM>, + /// Capture0 + pub capture0: CaptureChannel<0, PWM>, + /// Capture1 + pub capture1: CaptureChannel<1, PWM>, + /// Capture2 + pub capture2: CaptureChannel<2, PWM>, } impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { @@ -165,7 +178,11 @@ impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { timer2: Timer::new(guard.clone()), operator0: Operator::new(guard.clone()), operator1: Operator::new(guard.clone()), - operator2: Operator::new(guard), + operator2: Operator::new(guard.clone()), + capture_timer: CaptureTimer::new(guard.clone()); + capture0: CaptureChannel::new(guard.clone()), + capture1: CaptureChannel::new(guard.clone()), + capture2: CaptureChannel::new(guard), } } } @@ -288,6 +305,8 @@ pub trait PwmPeripheral: crate::private::Sealed { fn block() -> *const RegisterBlock; /// Get operator GPIO mux output signal fn output_signal() -> OutputSignal; + // Get operator GPIO mux capture input signal + fn capture_input_signal() -> InputSignal; /// Peripheral fn peripheral() -> Peripheral; } @@ -310,6 +329,15 @@ impl PwmPeripheral for crate::peripherals::MCPWM0<'_> { } } + fn capture_input_signal() -> InputSignal { + match CHAN { + 0 => InputSignal::PWM0_CAP0, + 1 => InputSignal::PWM0_CAP1, + 2 => InputSignal::PWM0_CAP2, + _ => unreachable!(), + } + } + fn peripheral() -> Peripheral { Peripheral::Mcpwm0 } @@ -333,6 +361,15 @@ impl PwmPeripheral for crate::peripherals::MCPWM1<'_> { } } + fn capture_input_signal() -> InputSignal { + match CHAN { + 0 => InputSignal::PWM1_CAP0, + 1 => InputSignal::PWM1_CAP1, + 2 => InputSignal::PWM1_CAP2, + _ => unreachable!(), + } + } + fn peripheral() -> Peripheral { Peripheral::Mcpwm1 } From 01f878e7168a9f3ca09e9cecf5f0c715f43e7b35 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Sat, 28 Mar 2026 13:16:37 -0600 Subject: [PATCH 02/37] Update mod.rs --- esp-hal/src/mcpwm/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index d70ac382f9c..ea74ea56101 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -99,13 +99,13 @@ use crate::{ time::Rate, }; +/// MCPWM capture channels +pub mod capture; /// MCPWM operators pub mod operator; /// MCPWM timers pub mod timer; -pub mod capture; - type RegisterBlock = pac::mcpwm0::RegisterBlock; #[allow(dead_code)] // Field is seemingly unused but we rely on its Drop impl @@ -179,7 +179,7 @@ impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { operator0: Operator::new(guard.clone()), operator1: Operator::new(guard.clone()), operator2: Operator::new(guard.clone()), - capture_timer: CaptureTimer::new(guard.clone()); + capture_timer: CaptureTimer::new(guard.clone()), capture0: CaptureChannel::new(guard.clone()), capture1: CaptureChannel::new(guard.clone()), capture2: CaptureChannel::new(guard), From 74bfcad9b18a1034604c9b213c1ac814b65cecf0 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Sat, 28 Mar 2026 21:27:34 -0600 Subject: [PATCH 03/37] Capture update Cargo was updated to use the new updated pac that I needed to create. Cargo.toml can be reverted once the pac is in the main branch. --- esp-hal/Cargo.toml | 245 ++++++++++++++++++++++------------- esp-hal/src/mcpwm/capture.rs | 187 +++++++++++--------------- 2 files changed, 236 insertions(+), 196 deletions(-) diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 4dc177ec058..a6599d2b5ad 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -1,130 +1,199 @@ [package] -name = "esp-hal" -version = "1.0.0" -edition = "2024" -rust-version = "1.88.0" -description = "Bare-metal HAL for Espressif devices" +name = "esp-hal" +version = "1.0.0" +edition = "2024" +rust-version = "1.88.0" +description = "Bare-metal HAL for Espressif devices" documentation = "https://docs.espressif.com/projects/rust/esp-hal/latest/" -keywords = ["embedded", "embedded-hal", "esp32", "espressif", "hal"] -categories = ["embedded", "hardware-support", "no-std"] -repository = "https://github.com/esp-rs/esp-hal" -license = "MIT OR Apache-2.0" -exclude = [ "api-baseline", "MIGRATING-*", "CHANGELOG.md" ] +keywords = ["embedded", "embedded-hal", "esp32", "espressif", "hal"] +categories = ["embedded", "hardware-support", "no-std"] +repository = "https://github.com/esp-rs/esp-hal" +license = "MIT OR Apache-2.0" +exclude = ["api-baseline", "MIGRATING-*", "CHANGELOG.md"] [package.metadata.espressif] semver-checked = true -doc-config = { features = ["unstable", "rt"], append = [ - { if = 'chip_has("psram")', features = ["psram"] }, - { if = 'chip_has("usb_otg_driver_supported")', features = ["__usb_otg"] }, - { if = 'chip_has("bt_driver_supported")', features = ["__bluetooth"] }, +doc-config = { features = [ + "unstable", + "rt", +], append = [ + { if = 'chip_has("psram")', features = [ + "psram", + ] }, + { if = 'chip_has("usb_otg_driver_supported")', features = [ + "__usb_otg", + ] }, + { if = 'chip_has("bt_driver_supported")', features = [ + "__bluetooth", + ] }, ] } check-configs = [ - { features = [] }, - { features = ["rt"] }, - { features = ["unstable", "rt"] }, - { features = ["unstable", "rt", "psram"], if = 'chip_has("psram")' }, - { features = ["unstable", "rt", "__usb_otg"], if = 'chip_has("usb_otg_driver_supported")' }, - { features = ["unstable", "rt", "__bluetooth"], if = 'chip_has("bt_driver_supported")' }, + { features = [ + ] }, + { features = [ + "rt", + ] }, + { features = [ + "unstable", + "rt", + ] }, + { features = [ + "unstable", + "rt", + "psram", + ], if = 'chip_has("psram")' }, + { features = [ + "unstable", + "rt", + "__usb_otg", + ], if = 'chip_has("usb_otg_driver_supported")' }, + { features = [ + "unstable", + "rt", + "__bluetooth", + ], if = 'chip_has("bt_driver_supported")' }, ] # Prefer fewer, but more complex clippy rules. A clippy run should cover as much code as possible. clippy-configs = [ - { features = ["unstable", "rt"], append = [ - { if = 'chip_has("psram")', features = ["psram"] }, - { if = 'chip_has("usb_otg_driver_supported")', features = ["__usb_otg"] }, - { if = 'chip_has("bt_driver_supported")', features = ["__bluetooth"] }, + { features = [ + "unstable", + "rt", + ], append = [ + { if = 'chip_has("psram")', features = [ + "psram", + ] }, + { if = 'chip_has("usb_otg_driver_supported")', features = [ + "__usb_otg", + ] }, + { if = 'chip_has("bt_driver_supported")', features = [ + "__bluetooth", + ] }, ] }, ] [package.metadata.docs.rs] default-target = "riscv32imac-unknown-none-elf" -features = ["esp32c6", "unstable"] -rustdoc-args = ["--cfg", "docsrs"] +features = ["esp32c6", "unstable"] +rustdoc-args = ["--cfg", "docsrs"] [lib] bench = false -test = false +test = false [dependencies] -bitflags = "2.9" -bytemuck = "1.24" -cfg-if = "1" -critical-section = { version = "1", features = ["restore-state-u32"], optional = true } -embedded-hal = "1.0.0" -embedded-hal-async = "1.0.0" -enumset = "1.1" -paste = "1.0.15" -portable-atomic = { version = "1.11", default-features = false } - -esp-rom-sys = { version = "0.1.3", path = "../esp-rom-sys" } +bitflags = "2.9" +bytemuck = "1.24" +cfg-if = "1" +critical-section = { version = "1", features = [ + "restore-state-u32", +], optional = true } +embedded-hal = "1.0.0" +embedded-hal-async = "1.0.0" +enumset = "1.1" +paste = "1.0.15" +portable-atomic = { version = "1.11", default-features = false } + +esp-rom-sys = { version = "0.1.3", path = "../esp-rom-sys" } # Unstable dependencies that are not (strictly) part of the public API -bitfield = "0.19" -delegate = "0.13" -document-features = "0.2" -embassy-futures = "0.1" -embassy-sync = "0.7" -fugit = "0.3.7" -instability = "0.3.9" -strum = { version = "0.27.1", default-features = false, features = ["derive"] } - -esp-config = { version = "0.6.1", path = "../esp-config" } -esp-metadata-generated = { version = "0.3.0", path = "../esp-metadata-generated" } -esp-sync = { version = "0.1.1", path = "../esp-sync" } -procmacros = { version = "0.21.0", package = "esp-hal-procmacros", path = "../esp-hal-procmacros" } +bitfield = "0.19" +delegate = "0.13" +document-features = "0.2" +embassy-futures = "0.1" +embassy-sync = "0.7" +fugit = "0.3.7" +instability = "0.3.9" +strum = { version = "0.27.1", default-features = false, features = ["derive"] } + +esp-config = { version = "0.6.1", path = "../esp-config" } +esp-metadata-generated = { version = "0.3.0", path = "../esp-metadata-generated" } +esp-sync = { version = "0.1.1", path = "../esp-sync" } +procmacros = { version = "0.21.0", package = "esp-hal-procmacros", path = "../esp-hal-procmacros" } # Dependencies that are optional because they are used by unstable drivers. # They are needed when using the `unstable` feature. -digest = { version = "0.10.7", default-features = false, features = ["core-api"], optional = true } -embassy-usb-driver = { version = "0.2", optional = true } +digest = { version = "0.10.7", default-features = false, features = [ + "core-api", +], optional = true } +embassy-usb-driver = { version = "0.2", optional = true } embassy-usb-synopsys-otg = { version = "0.3", optional = true } -embedded-can = { version = "0.4.1", optional = true } -esp-synopsys-usb-otg = { version = "0.4.2", optional = true } -nb = { version = "1.1", optional = true } +embedded-can = { version = "0.4.1", optional = true } +esp-synopsys-usb-otg = { version = "0.4.2", optional = true } +nb = { version = "1.1", optional = true } # Logging interfaces, they are mutually exclusive so they need to be behind separate features. -defmt = { version = "1.0.1", optional = true } -log-04 = { package = "log", version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +log-04 = { package = "log", version = "0.4", optional = true } # ESP32-only fallback SHA algorithms -sha1 = { version = "0.10", default-features = false, optional = true } -sha2 = { version = "0.10", default-features = false, optional = true } +sha1 = { version = "0.10", default-features = false, optional = true } +sha2 = { version = "0.10", default-features = false, optional = true } # Optional dependencies that enable ecosystem support. # We could support individually enabling them, but there is no big downside to just # enabling them all via the `unstable` feature. -embassy-embedded-hal = { version = "0.5", optional = true } -embedded-io-06 = { package = "embedded-io", version = "0.6", optional = true } -embedded-io-async-06 = { package = "embedded-io-async", version = "0.6", optional = true } -embedded-io-07 = { package = "embedded-io", version = "0.7", optional = true } -embedded-io-async-07 = { package = "embedded-io-async", version = "0.7", optional = true } -rand_core-06 = { package = "rand_core", version = "0.6", optional = true } -rand_core-09 = { package = "rand_core", version = "0.9", optional = true } -ufmt-write = { version = "0.1", optional = true } +embassy-embedded-hal = { version = "0.5", optional = true } +embedded-io-06 = { package = "embedded-io", version = "0.6", optional = true } +embedded-io-async-06 = { package = "embedded-io-async", version = "0.6", optional = true } +embedded-io-07 = { package = "embedded-io", version = "0.7", optional = true } +embedded-io-async-07 = { package = "embedded-io-async", version = "0.7", optional = true } +rand_core-06 = { package = "rand_core", version = "0.6", optional = true } +rand_core-09 = { package = "rand_core", version = "0.9", optional = true } +ufmt-write = { version = "0.1", optional = true } # IMPORTANT: # Each supported device MUST have its PAC included below along with a # corresponding feature. -esp32 = { version = "0.39", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } -esp32c2 = { version = "0.28", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } -esp32c3 = { version = "0.31", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } -esp32c5 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } -esp32c6 = { version = "0.22", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } -esp32c61 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } -esp32h2 = { version = "0.18", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } -esp32s2 = { version = "0.30", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } -esp32s3 = { version = "0.34", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +esp32 = { features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "4d71085" } +esp32c2 = { version = "0.28", features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +esp32c3 = { version = "0.31", features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +esp32c5 = { version = "0.1", features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +esp32c6 = { features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "4d71085" } +esp32c61 = { version = "0.1", features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +esp32h2 = { version = "0.18", features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +esp32s2 = { version = "0.30", features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +esp32s3 = { features = [ + "critical-section", + "rt", +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "4d71085" } [target.'cfg(target_arch = "riscv32")'.dependencies] -riscv = { version = "0.15.0" } -esp-riscv-rt = { version = "0.13.0", path = "../esp-riscv-rt", optional = true } +riscv = { version = "0.15.0" } +esp-riscv-rt = { version = "0.13.0", path = "../esp-riscv-rt", optional = true } [target.'cfg(target_arch = "xtensa")'.dependencies] -xtensa-lx = { version = "0.13.0", path = "../xtensa-lx" } -xtensa-lx-rt = { version = "0.21.0", path = "../xtensa-lx-rt", optional = true } +xtensa-lx = { version = "0.13.0", path = "../xtensa-lx" } +xtensa-lx-rt = { version = "0.21.0", path = "../xtensa-lx-rt", optional = true } [build-dependencies] -esp-metadata-generated = { version = "0.3.0", path = "../esp-metadata-generated", features = ["build-script"] } -esp-config = { version = "0.6.1", path = "../esp-config", features = ["build"] } +esp-metadata-generated = { version = "0.3.0", path = "../esp-metadata-generated", features = [ + "build-script", +] } +esp-config = { version = "0.6.1", path = "../esp-config", features = ["build"] } [dev-dependencies] crypto-bigint = { version = "0.5.5", default-features = false } @@ -182,14 +251,14 @@ float-save-restore = ["xtensa-lx-rt/float-save-restore"] #! One of the following features must be enabled to select the target chip: ## -esp32 = [ +esp32 = [ "dep:esp32", "procmacros/rtc-slow", "esp-rom-sys/esp32", "esp-sync/esp32", "esp-metadata-generated/esp32", "dep:sha1", - "dep:sha2" + "dep:sha2", ] ## esp32c2 = [ @@ -294,7 +363,7 @@ defmt = [ "fugit/defmt", "esp-riscv-rt?/defmt", "xtensa-lx-rt?/defmt", - "esp-sync/defmt" + "esp-sync/defmt", ] #DOC_IF has("psram") @@ -336,4 +405,6 @@ requires-unstable = [] mixed_attributes_style = "allow" [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(host_os, values("windows"))'] } +unexpected_cfgs = { level = "warn", check-cfg = [ + 'cfg(host_os, values("windows"))', +] } diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 01b58d49d40..248d758fb84 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -7,37 +7,29 @@ //! //! Capture events can be triggered in 2 ways: //! During a falling and/or Rising edge of a preconfigured GPIO pin. -//! Software triggered captures though the Capture::capture_time() function. +//! Software triggered captures though the CaptureChannel::trigger() function. //! //! ## Configuration //! This module provides the flexiability of configuring any GPIO pin as an input //! for capturing the rising and/or falling edge of a signal. This module allows -//! for the ability to trigger software captures, essentially capturing the current -//! time in the capture clock. - -use core::marker::PhantomData; -use core::panic; +//! for the ability to trigger software captures. +//! +//! Capture timer can be configured to sync with a PWM timer during specific events +//! either when the PWM timer sync out event, or a sync in from an external GPIO pin. +//! +use core::{marker::PhantomData, panic}; use esp_sync::RawMutex; use super::PeripheralGuard; -use crate::gpio::{InputSignal, interconnect::PeripheralInput}; -use crate::mcpwm::{PwmClockGuard, PwmPeripheral}; - -#[derive(Copy, Clone, Debug, Default, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -enum EdgeCaptureEvent { - FallingEdge, - RisingEdge, - EitherEdge, -} - -#[derive(Copy, Clone, Debug, Default, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -enum CapturedEdge { - FallingEdge, - RisingEdge, -} +pub use crate::pac::mcpwm0::{ + cap_ch_cfg::CAP0_MODE as CaptureMode, + cap_status::CAP0_EDGE as CaptureEdge, +}; +use crate::{ + gpio::{InputSignal, interconnect::PeripheralInput}, + mcpwm::{PwmClockGuard, PwmPeripheral}, +}; static MUTEX: RawMutex = RawMutex::new(); @@ -49,6 +41,11 @@ pub struct CaptureTimer<'d, PWM> { _pwm_clock_guard: PwmClockGuard, } +//! Capture timer inside MCPWM +//! +//! ## Overview +//! +//! This is a capture timer with the clock source of APB_CLK. impl CaptureTimer<'d, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { Timer { @@ -58,6 +55,7 @@ impl CaptureTimer<'d, PWM> { } } + /// Start the capture timer counting at APB_CLK pub fn start(&mut self) { // SAFETY: // We write to our MCPWM_CAP_TIMER_CFG_REG register @@ -80,7 +78,10 @@ impl CaptureTimer<'d, PWM> { /// A MCPWM Capture Channel /// /// The MCPWM Capture Channel has the following functions: -/// * +/// * Enable/Disable capturing on this channel +/// * Setting the capture input GPIO pin +/// * Weather to trigger capture events on rising and/or falling edges +/// * Read the last capture edge, and the last capture time pub struct CaptureChannel<'d, const CHAN: usize, PWM> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, @@ -96,26 +97,24 @@ impl CaptureChannel { } } - /// Enables capturing on this channel + /// Enables this capture channel pub fn enable(&mut self) { // SAFETY: // We only write to our MCPWM_CAP_CHx_CFG_REG register let block = unsafe { &*PWM::block() }; - - block.cap_ch_cfg(CHAN).write(|w| w.en().set_bit()); + block.cap_ch_cfg(CHAN).modify(|_, w| w.en().set_bit()); } - /// Disable capturing on this channel + /// Disable this capture channel pub fn disable(&mut self) { // SAFETY: // We only write to our MCPWM_CAP_CHx_CFG_REG register let block = unsafe { &*PWM::block() }; - - block.cap_ch_cfg(CHAN).write(|w| w.en().clear_bit()); + block.cap_ch_cfg(CHAN).modify(|_, w| w.en().clear_bit()); } /// Set the capture signal (pin/high/low) for this channel - pub fn set_capture_signal(&mut self, source: impl PeripheralInput<'d>) { + pub fn set_signal_capture(&mut self, source: impl PeripheralInput<'d>) { let signal = PWM::capture_input_signal::(); if signal as usize <= property!("gpio.input_signal_max") { @@ -127,109 +126,79 @@ impl CaptureChannel { } } + /// Sets the capture prescaler for the channel. + /// Although the function of the prescaler on capture channels + /// is better though of as a capture rate. + /// + /// The prescaler determines how often a capture event is generated + /// from incoming edges. Instead of capturing every valid edge, + /// the hardware will generate a capture event once every `capture_rate` + /// edges. + /// + /// The edges counted are those selected by the channel's edge configuration + /// (rising, falling, or both). For example: + /// + /// - If configured for rising edges only, captures occur every Nth rising edge + /// - If configured for both edges, captures occur every Nth edge (rising + falling combined) + /// + /// This is useful for reducing interrupt load or effectively averaging + /// measurements over multiple signal periods. + /// + /// Passing in a value of capture_rate = 0 into this function will set the capture_rate value of 1 + pub fn set_capture_rate(&mut self, capture_rate : u8) { + // SAFETY: + // We only write to our MCPWM_CAP_CHx_CFG_REG register + let block = unsafe { &*PWM::block() }; + unsafe { + block.cap_ch_cfg(CHAN).modify(|_, w| w.prescale().bits(capture_rate)); + } + } + /// Sets the capture channel to listen to captures on specific edge events /// This channel can listen to Falling, and/or Rising edges on any of the GPIO pins. - pub fn listen(&mut self, edge_capture_event: EdgeCaptureEvent) { + pub fn listen(&mut self, capture_mode: CaptureMode) { // SAFETY: // We write to our MCPWM_CAP_CHx_CFG_REG register - // And we are modifying a shared peripheral interrupt enable register + // We are modifying a shared peripheral interrupt enable register let block = unsafe { &*PWM::block() }; - - // Maps the edge capture event to the proper bits in the capture - // configuration register. - // - // In the MCPWM_CAP_CHx_CFG_REG register within the - // the MCPWM_CAP0_MODE field of the register Bits[1..=2] discribe - // the falling and/or rising edge capture - // - // The 2 bits within the MCPWM_CAPx_MODE field are as of the following - // Bits[0] -> Selects weather or not Falling Edges should be captured - // Bits[1] -> Selects weather or not Rising Edges should be captured - // - // Has been checked for the following chips: ESP32s3 - // - // Either of them can be on or off allowing for the 4 configurations seen below. - - // Note: would be nice to be able to set this via an enum like the PCNT register block :) - match edge_capture_event { - EdgeCaptureEvent::FallingEdge => unsafe { - // Bit0 set -> Falling edges - block.cap_ch_cfg(CHAN).write(|w| w.mode().bits(0b01)); - }, - EdgeCaptureEvent::RisingEdge => unsafe { - // Bit1 set -> Rising edges - block.cap_ch_cfg(CHAN).write(|w| w.mode().bits(0b10)); - }, - EdgeCaptureEvent::EitherEdge => unsafe { - // Bit0 and Bit1 set -> Either edge - block.cap_ch_cfg(CHAN).write(|w| w.mode().bits(0b11)); - }, - }; + block + .cap_ch_cfg(CHAN) + .write(|w| w.mode().variant(capture_mode)); // Enable the capture interrupt - MUTEX.lock(|| { - // Note: would be nice to be able to get interrupts from channel number - match CHAN { - 0 => block.int_ena().modify(|r, w| w.cap0().set_bit()), - 1 => block.int_ena().modify(|r, w| w.cap1().set_bit()), - 2 => block.int_ena().modify(|r, w| w.cap2().set_bit()), - _ => unreachable!(), - }; - }); + block.int_ena().modify(|_, w| w.cap(CHAN as u8).set_bit()); } /// Stops listening to events on this channel pub fn unlisten(&mut self) { // SAFTEY: - // We are accessing a SHARED peripheral interrupt enable register - let _ = self._guard; + // We are writing to a SHARED peripheral interrupt enable register + // Tldr lowk don't know if I should use a mutex or not?? let block = unsafe { &*PWM::block() }; // We can unlisten from events simply by disabling the interrupt - MUTEX.lock(|| { - // Note: would be nice to be able to get interrupts from channel number - match CHAN { - 0 => block.int_ena().modify(|r, w| w.cap0().clear_bit()), - 1 => block.int_ena().modify(|r, w| w.cap1().clear_bit()), - 2 => block.int_ena().modify(|r, w| w.cap2().clear_bit()), - _ => unreachable!(), - }; - }); + block.int_ena().modify(|_, w| w.cap(CHAN as u8).clear_bit()); } pub fn is_interupt_set(&mut self) -> bool { + // SAFTEY: + // We only read from our MCPWM_INT_ST_REG register let block = unsafe { &*PWM::block() }; + block.int_st().read().cap(CHAN as u8).bit() + } - // Note: would be nice to be able to get interrupts from channel number - match CHAN { - 0 => block.int_raw().read().cap0().bit(), - 1 => block.int_raw().read().cap1().bit(), - 2 => block.int_raw().read().cap2().bit(), - _ => unreachable!(), - } + pub fn last_captured_time(&mut self) -> u32 { + // SAFTEY: + // We only read from our MCPWM_INT_ST_REG register + let block = unsafe { &*PWM::block() }; + block.cap_ch(CHAN).read().value().bits() } /// Gets the last captured edge on this channel - pub fn get_captured_edge(&mut self) -> CapturedEdge { + pub fn get_captured_edge(&mut self) -> CaptureEdge { // SAFETY: // We only read from our MCPWM_CAP_STATUS_REG register let block = unsafe { &*PWM::block() }; - - // Read the last edge status from the either of the 3 channels - // the bit that we read will indicate if it was a faling edge. - - // Note: would be nice to be able to get the capture status from channel number - let is_falling_edge = match CHAN { - 0 => block.cap_status().read().cap0_edge().bit(), - 1 => block.cap_status().read().cap1_edge().bit(), - 2 => block.cap_status().read().cap2_edge().bit(), - _ => unreachable!(), - }; - - if is_falling_edge { - CapturedEdge::FallingEdge - } else { - CapturedEdge::RisingEdge - } + block.cap_status().read().cap_edge(CHAN as u8).variant() } } From ce58b750ee16861241239bd526f508e4a30aaf69 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Sun, 29 Mar 2026 17:12:14 -0600 Subject: [PATCH 04/37] Updated timer sync configurations --- esp-hal/src/mcpwm/capture.rs | 142 +++++++++++++++++++++++++---------- esp-hal/src/mcpwm/mod.rs | 24 +++++- esp-hal/src/mcpwm/sync.rs | 134 +++++++++++++++++++++++++++++++++ esp-hal/src/mcpwm/timer.rs | 130 +++++++++++++++++++++++++++++--- 4 files changed, 379 insertions(+), 51 deletions(-) create mode 100644 esp-hal/src/mcpwm/sync.rs diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 248d758fb84..c8c25cf715b 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -28,24 +28,35 @@ pub use crate::pac::mcpwm0::{ }; use crate::{ gpio::{InputSignal, interconnect::PeripheralInput}, - mcpwm::{PwmClockGuard, PwmPeripheral}, + mcpwm::{PwmClockGuard, PwmPeripheral, sync::{SyncKind, SyncSource, InternalSyncSource, SyncSelectionRegister}}, }; static MUTEX: RawMutex = RawMutex::new(); -/// The MCPWM Capture Timer -/// This timer is specific to the 3 channels +//! The MCPWM Capture Timer +//! +//! ## Overview +//! - This timer is shared by all instances of [`CaptureChannel`] for a MCPWM. +//! During capture events on any of the channels the time stored in this timer will be +//! loaded into the [`CaptureEvent`]'s time. +//! - This is a timer has the clock source of APB_CLK. +//! - A sync source can be selected by calling [`CaptureTimer::set_sync`] with a sync source. +//! - A sync source can be removed by calling [`CaptureTimer::clear_sync`]. +//! +//! During a sync event on this capture timer the counter of the timer is reset. +//! The value that the timer reset to depends on the sync source: +//! - If the sync source came from a timer with [`super::Timer::get_sync_out`] +//! the value that it is reset to the phase value for the given timer. +//! +//! - If the sync sorce came from a sync line in [`super::McPwm`] then the timer +//! is reset with a value of 0. +//! pub struct CaptureTimer<'d, PWM> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } - -//! Capture timer inside MCPWM -//! -//! ## Overview -//! -//! This is a capture timer with the clock source of APB_CLK. + impl CaptureTimer<'d, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { Timer { @@ -58,20 +69,82 @@ impl CaptureTimer<'d, PWM> { /// Start the capture timer counting at APB_CLK pub fn start(&mut self) { // SAFETY: - // We write to our MCPWM_CAP_TIMER_CFG_REG register + // We modify our MCPWM_CAP_TIMER_CFG_REG register let block = unsafe { &*PWM::block() }; - block.cap_timer_cfg().write(|w| w.cap_timer_en().set_bit()); + block.cap_timer_cfg().modify(|w| w.cap_timer_en().set_bit()); } + /// Pauses the capture timer pub fn pause(&mut self) { // SAFETY: - // We write to our MCPWM_CAP_TIMER_CFG_REG register + // We modify our MCPWM_CAP_TIMER_CFG_REG register let block = unsafe { &*PWM::block() }; block .cap_timer_cfg() - .write(|w| w.cap_timer_en().clear_bit()); + .modify(|w| w.cap_timer_en().clear_bit()); + } + + /// Clears the captures timer sync source + pub fn clear_sync_in(&mut self) { + // SAFETY: + // We modify our MCPWM_CAP_TIMER_CFG_REG register + let block = unsafe { &*PWM::block() }; + unsafe { + block.cap_timer_cfg().modify(|_r, w| { + w.cap_synci_en().clear_bit(); // Disable sync inputs + w.cap_synci_sel().bits(CaptureSyncSelection::None as u8) // No sync input + }) + }; + } + + /// ## Overview + /// Sets the capture timers sync source. Refer to how sync events are + /// handled in the [`CaptureTimer`] documentation. + /// + pub fn set_sync_in(&mut self, sync_source : impl SyncSource) { + // SAFETY: + // We modify our MCPWM_CAP_TIMER_CFG_REG register + let block = unsafe { &*PWM::block() }; + + let sync_kind = sync_source.get_kind(); + let sync_selection : SyncSelectionRegister = sync_kind.into(); + unsafe { + block.cap_timer_cfg().modify(|_r, w| { + w.cap_synci_en().set_bit(); // Enable sync input + w.cap_synci_sel().bits(sync_selection as u8) // Set the sync selection + }) + }; + } + + /// ## Overview + /// This triggers a software sync event on the capture timer + /// Refer to how sync events are handled in the [`CaptureTimer`] documentation. + /// + pub fn trigger_sync(&mut self) { + // SAFETY: + // We modify our MCPWM_CAP_TIMER_CFG_REG register + let block = unsafe { &*PWM::block() }; + // Trigger a software sync + block.cap_timer_cfg().modify(|_r, w| w.cap_sync_sw().set_bit()); + } +} + +/// Repersents the capture event +/// Contains the capture time and the captured edge +pub struct CaptureEvent { + time : u32, + edge : CaptureEdge +} + +impl CaptureEvent { + pub fn get_time(&self) -> u32 { + self.time + } + + pub fn get_edge(&self) -> CaptureEdge { + self.edge } } @@ -98,19 +171,11 @@ impl CaptureChannel { } /// Enables this capture channel - pub fn enable(&mut self) { - // SAFETY: - // We only write to our MCPWM_CAP_CHx_CFG_REG register - let block = unsafe { &*PWM::block() }; - block.cap_ch_cfg(CHAN).modify(|_, w| w.en().set_bit()); - } - - /// Disable this capture channel - pub fn disable(&mut self) { + pub fn set_enable(&mut self, enable : bool) { // SAFETY: // We only write to our MCPWM_CAP_CHx_CFG_REG register let block = unsafe { &*PWM::block() }; - block.cap_ch_cfg(CHAN).modify(|_, w| w.en().clear_bit()); + block.cap_ch_cfg(CHAN).modify(|_, w| w.en().variant(enable)); } /// Set the capture signal (pin/high/low) for this channel @@ -128,7 +193,6 @@ impl CaptureChannel { /// Sets the capture prescaler for the channel. /// Although the function of the prescaler on capture channels - /// is better though of as a capture rate. /// /// The prescaler determines how often a capture event is generated /// from incoming edges. Instead of capturing every valid edge, @@ -141,16 +205,13 @@ impl CaptureChannel { /// - If configured for rising edges only, captures occur every Nth rising edge /// - If configured for both edges, captures occur every Nth edge (rising + falling combined) /// - /// This is useful for reducing interrupt load or effectively averaging - /// measurements over multiple signal periods. - /// - /// Passing in a value of capture_rate = 0 into this function will set the capture_rate value of 1 - pub fn set_capture_rate(&mut self, capture_rate : u8) { + /// Passing in a value of prescaler = 0 into this function will set the prescaler value of 1 + pub fn set_prescaler(&mut self, prescaler : u8) { // SAFETY: // We only write to our MCPWM_CAP_CHx_CFG_REG register let block = unsafe { &*PWM::block() }; unsafe { - block.cap_ch_cfg(CHAN).modify(|_, w| w.prescale().bits(capture_rate)); + block.cap_ch_cfg(CHAN).modify(|_, w| w.prescale().bits(prescaler)); } } @@ -180,6 +241,7 @@ impl CaptureChannel { block.int_ena().modify(|_, w| w.cap(CHAN as u8).clear_bit()); } + // Checks if the interrupt was set for this channel pub fn is_interupt_set(&mut self) -> bool { // SAFTEY: // We only read from our MCPWM_INT_ST_REG register @@ -187,18 +249,16 @@ impl CaptureChannel { block.int_st().read().cap(CHAN as u8).bit() } - pub fn last_captured_time(&mut self) -> u32 { + // Gets the captured event + pub fn get_event(&mut self) -> CaptureEvent { // SAFTEY: - // We only read from our MCPWM_INT_ST_REG register + // We only read from our MCPWM_INT_ST_REG & MCPWM_CAP_STATUS_REG register let block = unsafe { &*PWM::block() }; - block.cap_ch(CHAN).read().value().bits() - } - - /// Gets the last captured edge on this channel - pub fn get_captured_edge(&mut self) -> CaptureEdge { - // SAFETY: - // We only read from our MCPWM_CAP_STATUS_REG register - let block = unsafe { &*PWM::block() }; - block.cap_status().read().cap_edge(CHAN as u8).variant() + let time = block.cap_ch(CHAN).read().value().bits(); + let edge = block.cap_status().read().cap_edge(CHAN as u8).variant(); + CaptureEvent { + time, + edge + } } } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index ea74ea56101..29e5c80897d 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -90,7 +90,7 @@ use timer::Timer; #[cfg(soc_has_mcpwm0)] use crate::gpio::InputSignal; use crate::{ - gpio::OutputSignal, + gpio::{Input, OutputSignal}, mcpwm::capture::{CaptureChannel, CaptureTimer}, pac, private::OnDrop, @@ -103,6 +103,8 @@ use crate::{ pub mod capture; /// MCPWM operators pub mod operator; +/// Sync +pub mod sync; /// MCPWM timers pub mod timer; @@ -307,6 +309,8 @@ pub trait PwmPeripheral: crate::private::Sealed { fn output_signal() -> OutputSignal; // Get operator GPIO mux capture input signal fn capture_input_signal() -> InputSignal; + // Get operator GPIO mux sync input signal + fn sync_input_signal() -> InputSignal; /// Peripheral fn peripheral() -> Peripheral; } @@ -338,6 +342,15 @@ impl PwmPeripheral for crate::peripherals::MCPWM0<'_> { } } + fn sync_input_signal() -> InputSignal { + match SYNC { + 0 => InputSignal::PWM0_SYNC0, + 1 => InputSignal::PWM0_SYNC1, + 2 => InputSignal::PWM0_SYNC2, + _ => unreachable!(), + } + } + fn peripheral() -> Peripheral { Peripheral::Mcpwm0 } @@ -370,6 +383,15 @@ impl PwmPeripheral for crate::peripherals::MCPWM1<'_> { } } + fn sync_input_signal() -> InputSignal { + match SYNC { + 0 => InputSignal::PWM1_SYNC0, + 1 => InputSignal::PWM1_SYNC1, + 2 => InputSignal::PWM1_SYNC2, + _ => unreachable!(), + } + } + fn peripheral() -> Peripheral { Peripheral::Mcpwm1 } diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs new file mode 100644 index 00000000000..7d3b8ac4a52 --- /dev/null +++ b/esp-hal/src/mcpwm/sync.rs @@ -0,0 +1,134 @@ +//! # MCPWM Sync Module +//! +//! ## Overview +//! The `Sync` is resposible for managing the different ways +//! MCPWM can listen to sync events. There are 2 different +//! sync sources one that can come from a Timer's sync_out +//! or from a Sync line that can be triggered by an external signal. +//! +//! This module provides the flexability to map any of the sync line +//! to any GPIO signal. Aswell to repersent any timer's sync_out source. +use core::{marker::PhantomData, panic}; + +use esp_sync::RawMutex; + +use super::PeripheralGuard; +use crate::{ + gpio::{InputSignal, interconnect::PeripheralInput}, + mcpwm::{PwmClockGuard, PwmPeripheral}, +}; + +/// Must hide the get kind from public facing API +/// prevents users from creating any sync kind +mod sealed { + /// Repersents the different types of sync sources + /// Either from sync lines or from timers sync out + #[derive(Clone, Copy)] + pub enum SyncKind { + SyncLine(u8), + TimerSyncOut(u8), + } + + pub trait InternalSyncSource { + fn get_kind(&self) -> SyncKind; + } +} +// Give our crate access to the internal sync source +// and sync kind +pub(crate) use sealed::{InternalSyncSource, SyncKind}; + +/// Public trait to repersent a sync source +pub trait SyncSource: sealed::InternalSyncSource {} + +/// Sync out for timers +#[derive(Clone, Copy)] +pub struct SyncOut<'d, PWM> { + timer: u8, + _phantom: PhantomData<'d, PWM>, +} + +impl<'d, PWM: PwmPeripheral> SyncOut<'d, PWM> { + pub(crate) fn new() -> Self { + Self { + timer: TIM, + _phantom: PhantomData, + } + } +} + +impl<'d, PWM: PwmPeripheral> sealed::InternalSyncSource for SyncOut<'d, PWM> { + fn get_kind(&self) -> SyncKind { + SyncKind::TimerSyncOut(self.timer) + } +} + +/// There are only a limited number sync lines for the MCPWM unit +#[derive(Clone, Copy)] +pub struct SyncLine { + _phantom: PhantomData, +} + +impl sealed::InternalSyncSource for SyncLine { + fn get_kind(&self) -> SyncKind { + SyncKind::SyncLine(SYNC) + } +} + +impl<'d, const SYNC: u8, PWM: PwmPeripheral> SyncLine<'d, SYNC, PWM> { + /// Create a new sync line + pub(super) fn new() -> Self { + Self { + _phantom: PhantomData, + } + } + + /// Set the input signal for the sync line + pub fn set_signal(&mut self, source: impl PeripheralInput<'d>) { + // configure GPIO matrix → SYNC + let signal = PWM::sync_input_signal::(); + + if signal as usize <= property!("gpio.input_signal_max") { + let source = source.into(); + source.set_input_enable(true); + signal.connect_to(&source); + } else { + warn!("Signal {:?} out of range", signal); + } + } +} + +// Values for any of the sync selection registers +#[repr(u8)] +#[derive(Copy, Clone)] +pub(crate) enum SyncSelectionRegister { + // Select no sync input for the capture timer + None = 0, + // Select the timers sync source for a timer's sync out, + Timer0SyncOut = 1, + Timer1SyncOut = 2, + Timer2SyncOut = 3, + // Select the timers sync source from a sync line + SyncLine0 = 4, + SyncLine1 = 5, + SyncLine2 = 6, +} + +// Provides a simple way of translating the internal SyncKind +impl From for SyncSelectionRegister { + fn from(value: SyncKind) -> Self { + match value { + SyncKind::SyncLine(line) => match line { + 0 => SyncSelectionRegister::SyncLine0, + 1 => SyncSelectionRegister::SyncLine1, + 2 => SyncSelectionRegister::SyncLine2, + _ => unreachable!(), + }, + SyncKind::TimerSyncOut(timer) => match timer { + 0 => SyncSelectionRegister::Timer0SyncOut, + 1 => SyncSelectionRegister::Timer1SyncOut, + 2 => SyncSelectionRegister::Timer2SyncOut, + _ => unreachable!(), + }, + } + } +} diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 98475e71b85..726cef6cd54 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -8,7 +8,13 @@ use core::marker::PhantomData; use super::PeripheralGuard; use crate::{ - mcpwm::{FrequencyError, PeripheralClockConfig, PwmClockGuard, PwmPeripheral}, + mcpwm::{ + FrequencyError, + PeripheralClockConfig, + PwmClockGuard, + PwmPeripheral, + sync::{SyncOut, SyncSource}, + }, pac, time::Rate, }; @@ -60,9 +66,9 @@ impl Timer { .bits(timer_config.period_updating_method as u8) }); - // set timer to continuously run and set the timer working mode + // set timer to run with a stop condition self.cfg1().write(|w| unsafe { - w.start().bits(2); + w.start().bits(timer_config.stop_condition as u8); w.mod_().bits(timer_config.mode as u8) }); } @@ -73,18 +79,55 @@ impl Timer { self.cfg1().write(|w| unsafe { w.mod_().bits(0) }); } - /// Set the timer counter to the provided value + //! Set the timer counter to the provided value + //! + //! ## Overview + //! Internally we set the timers phase and direction + //! Then trigger a software sync event. + //! + //! Note: This triggers a sync out event. If a timer is listening + //! to this timers sync out source a sync event will be triggered. + //! Refer to how sync events are handled for [`super::CaptureTimer`] or [`Timer`] + //! in the their respective documentation. pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { + self.set_sync_phase(phase); + self.set_sync_counter_direction(direction); + self.trigger_sync(); + } + + /// Set the timers sync phase + pub fn set_sync_phase(&mut self, phase: u16) { // SAFETY: // We only write to our TIMERx_SYNC register let tmr = unsafe { Self::tmr() }; - let sw = tmr.sync().read().sw().bit_is_set(); - tmr.sync().write(|w| { - w.phase_direction().bit(direction as u8 != 0); + tmr.sync().modify(|_r, w| { unsafe { - w.phase().bits(phase); + w.phase().bits(phase) } - w.sw().bit(!sw) + }); + } + + /// Set the timers sync counter direction + /// This specifies how the counter direction will be updated + /// during a sync event. + pub fn set_sync_counter_direction(&mut self, direction: CounterDirection) { + // SAFETY: + // We only write to our TIMERx_SYNC register + let tmr = unsafe { Self::tmr() }; + tmr.sync().modify(|_r, w| { + w.phase_direction().bit(direction as u8 != 0) + }); + } + + /// Trigger a software sync event + /// Note: This always triggers a sync out event even if the + /// sync out select is set to when + pub fn trigger_sync(&mut self) { + // SAFETY: + // We only write to our TIMERx_SYNC register + let tmr = unsafe { Self::tmr() }; + tmr.sync().modify(|r, w| { + w.sw().bit(!r.sw().bit()) }); } @@ -96,6 +139,32 @@ impl Timer { (reg.value().bits(), reg.direction().bit_is_set().into()) } + pub fn set_sync_out_selection(&mut self, ) + + /// Returns the timers sync_out source + pub fn get_sync_out(&self) -> SyncOut<'d, PWM> { + SyncOut::new::() + } + + /// Sets the timer sync in source + pub fn set_sync_in(&mut self, sync: impl SyncSource) { + // SAFETY: + // We only modify the PWM TIMER_SYNCI_CFG register + let pwm = unsafe { &*PWM::block() }; + pwm.timer_synci_cfg().modify(|_r, w| { + w.timer0_syncisel() + }) + + let sync_kind = sync_source.get_kind(); + let sync_selection : SyncSelectionRegister = sync_kind.into(); + unsafe { + block.cap_timer_cfg().modify(|_r, w| { + w.cap_synci_en().set_bit(); // Enable sync input + w.cap_synci_sel().bits(sync_selection as u8) // Set the sync selection + }) + }; + } + fn cfg0(&mut self) -> &pac::mcpwm0::timer::CFG0 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self @@ -114,6 +183,24 @@ impl Timer { } } +/// Sync out selection for the timer +/// +/// Note: +/// During a software sync event triggered by [`Timer::trigger_sync`] or +/// [`Timer::set_counter`] a sync out is always triggered regardless if +/// if the timer was configured with [`SyncOutSelection::SyncWhenEqualZero`] or +/// [`SyncOutSelection::SyncWhenEqualPeriod`]. +#[derive(Clone, Copy)] +#[repr(u8)] +pub enum SyncOutSelection { + /// Sync out is triggered when a timer receives a sync in + SyncIn = 0, + // Sync out is triggered when the timer equals zero + SyncWhenEqualZero = 1, + // Sync out is triggered when the timer equals the period + SyncWhenEqualPeriod = 2, +} + /// Clock configuration of a MCPWM timer /// /// Use [`PeripheralClockConfig::timer_clock_with_prescaler`](super::PeripheralClockConfig::timer_clock_with_prescaler) or @@ -123,6 +210,7 @@ pub struct TimerClockConfig { frequency: Rate, period: u16, period_updating_method: PeriodUpdatingMethod, + stop_condition: StopCondition, prescaler: u8, mode: PwmWorkingMode, } @@ -146,6 +234,7 @@ impl TimerClockConfig { prescaler, period, period_updating_method: PeriodUpdatingMethod::Immediately, + stop_condition: StopCondition::RunContinuously, mode, } } @@ -179,6 +268,7 @@ impl TimerClockConfig { prescaler: prescaler as u8, period, period_updating_method: PeriodUpdatingMethod::Immediately, + stop_condition: StopCondition::RunContinuously, mode, }) } @@ -191,6 +281,14 @@ impl TimerClockConfig { } } + // Sets the stop timer conditions + pub fn with_stop_conditions(self, condition: StopCondition) -> Self { + Self { + stop_condition: condition, + ..self + } + } + /// Get the timer clock frequency. /// /// ### Note: @@ -215,6 +313,20 @@ pub enum PeriodUpdatingMethod { TimerEqualsZeroOrSync = 3, } +/// Method for stop conditions for timers +#[derive(Clone, Copy)] +#[repr(u8)] +pub enum StopCondition { + /// Defines to start the timer now and run till [`Timer::stop`] is called. + RunContinuously = 2, + /// Defines to start the timer now and run till the + /// next time the timers counts equal zeros + StopAtZero = 3, + /// Defines to start the timer now and run till the + /// next time the timers counts equals period + StopAtPeriod = 4, +} + /// PWM working mode #[derive(Copy, Clone)] #[repr(u8)] From e580a8afd52c96a45e507701b889ad2ba80eb9d2 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Sun, 29 Mar 2026 17:54:16 -0600 Subject: [PATCH 05/37] Finished sync implementation Finished the sync implementation time to test the code! --- esp-hal/Cargo.toml | 6 +++--- esp-hal/src/mcpwm/timer.rs | 40 +++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index a6599d2b5ad..4150016d12c 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -147,7 +147,7 @@ ufmt-write = { version = "0.1", optional = true } esp32 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "4d71085" } +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc794983b" } esp32c2 = { version = "0.28", features = [ "critical-section", "rt", @@ -163,7 +163,7 @@ esp32c5 = { version = "0.1", features = [ esp32c6 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "4d71085" } +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc794983b" } esp32c61 = { version = "0.1", features = [ "critical-section", "rt", @@ -179,7 +179,7 @@ esp32s2 = { version = "0.30", features = [ esp32s3 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "4d71085" } +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc794983b" } [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { version = "0.15.0" } diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 726cef6cd54..f2ef5927b19 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -139,7 +139,15 @@ impl Timer { (reg.value().bits(), reg.direction().bit_is_set().into()) } - pub fn set_sync_out_selection(&mut self, ) + pub fn set_sync_out_selection(&mut self, sync_out : SyncOutSelection) { + // SAFETY: + // We only modify our TIMERx_SYNC register + let timer = unsafe { Self::tmr() }; + // Disable sync input on our timer + timer.sync().modify(|_r, w| unsafe { + w.synco_sel.bits(sync_out as u8) + }); + } /// Returns the timers sync_out source pub fn get_sync_out(&self) -> SyncOut<'d, PWM> { @@ -151,18 +159,28 @@ impl Timer { // SAFETY: // We only modify the PWM TIMER_SYNCI_CFG register let pwm = unsafe { &*PWM::block() }; + // SAFETY: + // We only modify our TIMERx_SYNC register + let timer = unsafe { Self::tmr() }; + + // Update sync select first + let sync_select : SyncSelectionRegister = sync.get_kind().into(); pwm.timer_synci_cfg().modify(|_r, w| { - w.timer0_syncisel() - }) + unsafe { + w.timer_syncisel(TIM).bits(sync_select as u8) // Update timer input sync selection + } + }); - let sync_kind = sync_source.get_kind(); - let sync_selection : SyncSelectionRegister = sync_kind.into(); - unsafe { - block.cap_timer_cfg().modify(|_r, w| { - w.cap_synci_en().set_bit(); // Enable sync input - w.cap_synci_sel().bits(sync_selection as u8) // Set the sync selection - }) - }; + // Enable sync input on our timer + timer.sync().modify(|_r, w| w.synci_en().set_bit()); + } + + pub fn clear_sync_in(&mut self) { + // SAFETY: + // We only modify our TIMERx_SYNC register + let timer = unsafe { Self::tmr() }; + // Disable sync input on our timer + timer.sync().modify(|_r, w| w.synci_en().clear_bit()); } fn cfg0(&mut self) -> &pac::mcpwm0::timer::CFG0 { From cf9442912bfa1f0fb444b8206e79afadca85c4a6 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Sun, 29 Mar 2026 19:25:00 -0600 Subject: [PATCH 06/37] Fixed uncompilable code Forgot to compile with unstable so last commit contained uncompilable code. This compiles with no warnings. --- esp-hal/src/mcpwm/capture.rs | 121 +++++++++++++++++----------------- esp-hal/src/mcpwm/mod.rs | 33 ++++++---- esp-hal/src/mcpwm/operator.rs | 2 +- esp-hal/src/mcpwm/sync.rs | 60 ++++++++--------- esp-hal/src/mcpwm/timer.rs | 79 +++++++++++----------- 5 files changed, 150 insertions(+), 145 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index c8c25cf715b..afb84c4e350 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -13,13 +13,10 @@ //! This module provides the flexiability of configuring any GPIO pin as an input //! for capturing the rising and/or falling edge of a signal. This module allows //! for the ability to trigger software captures. -//! +//! //! Capture timer can be configured to sync with a PWM timer during specific events //! either when the PWM timer sync out event, or a sync in from an external GPIO pin. -//! -use core::{marker::PhantomData, panic}; - -use esp_sync::RawMutex; +use core::marker::PhantomData; use super::PeripheralGuard; pub use crate::pac::mcpwm0::{ @@ -27,39 +24,40 @@ pub use crate::pac::mcpwm0::{ cap_status::CAP0_EDGE as CaptureEdge, }; use crate::{ - gpio::{InputSignal, interconnect::PeripheralInput}, - mcpwm::{PwmClockGuard, PwmPeripheral, sync::{SyncKind, SyncSource, InternalSyncSource, SyncSelectionRegister}}, + gpio::interconnect::PeripheralInput, + mcpwm::{ + PwmClockGuard, + PwmPeripheral, + sync::{SyncSelection, SyncSource}, + }, }; -static MUTEX: RawMutex = RawMutex::new(); - -//! The MCPWM Capture Timer -//! -//! ## Overview -//! - This timer is shared by all instances of [`CaptureChannel`] for a MCPWM. -//! During capture events on any of the channels the time stored in this timer will be -//! loaded into the [`CaptureEvent`]'s time. -//! - This is a timer has the clock source of APB_CLK. -//! - A sync source can be selected by calling [`CaptureTimer::set_sync`] with a sync source. -//! - A sync source can be removed by calling [`CaptureTimer::clear_sync`]. -//! -//! During a sync event on this capture timer the counter of the timer is reset. -//! The value that the timer reset to depends on the sync source: -//! - If the sync source came from a timer with [`super::Timer::get_sync_out`] -//! the value that it is reset to the phase value for the given timer. -//! -//! - If the sync sorce came from a sync line in [`super::McPwm`] then the timer -//! is reset with a value of 0. -//! +/// The MCPWM Capture Timer +/// +/// ## Overview +/// - This timer is shared by all instances of [`CaptureChannel`] for a MCPWM. +/// During capture events on any of the channels the time stored in this timer will be +/// loaded into the [`CaptureEvent`]'s time. +/// - This is a timer has the clock source of APB_CLK. +/// - A sync source can be selected by calling [`CaptureTimer::set_sync`] with a sync source. +/// - A sync source can be removed by calling [`CaptureTimer::clear_sync`]. +/// +/// During a sync event on this capture timer the counter of the timer is reset. +/// The value that the timer reset to depends on the sync source: +/// - If the sync source came from a timer with [`super::Timer::get_sync_out`] +/// the value that it is reset to the phase value for the given timer. +/// +/// - If the sync sorce came from a sync line in [`super::McPwm`] then the timer +/// is reset with a value of 0. pub struct CaptureTimer<'d, PWM> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } - -impl CaptureTimer<'d, PWM> { + +impl<'d, PWM: PwmPeripheral> CaptureTimer<'d, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { - Timer { + Self { phantom: PhantomData, _guard: guard, _pwm_clock_guard: PwmClockGuard::new::(), @@ -72,7 +70,9 @@ impl CaptureTimer<'d, PWM> { // We modify our MCPWM_CAP_TIMER_CFG_REG register let block = unsafe { &*PWM::block() }; - block.cap_timer_cfg().modify(|w| w.cap_timer_en().set_bit()); + block + .cap_timer_cfg() + .modify(|_r, w| w.cap_timer_en().set_bit()); } /// Pauses the capture timer @@ -83,7 +83,7 @@ impl CaptureTimer<'d, PWM> { block .cap_timer_cfg() - .modify(|w| w.cap_timer_en().clear_bit()); + .modify(|_r, w| w.cap_timer_en().clear_bit()); } /// Clears the captures timer sync source @@ -94,7 +94,7 @@ impl CaptureTimer<'d, PWM> { unsafe { block.cap_timer_cfg().modify(|_r, w| { w.cap_synci_en().clear_bit(); // Disable sync inputs - w.cap_synci_sel().bits(CaptureSyncSelection::None as u8) // No sync input + w.cap_synci_sel().bits(SyncSelection::None as u8) // No sync input }) }; } @@ -102,14 +102,13 @@ impl CaptureTimer<'d, PWM> { /// ## Overview /// Sets the capture timers sync source. Refer to how sync events are /// handled in the [`CaptureTimer`] documentation. - /// - pub fn set_sync_in(&mut self, sync_source : impl SyncSource) { + pub fn set_sync_in(&mut self, sync_source: impl SyncSource) { // SAFETY: // We modify our MCPWM_CAP_TIMER_CFG_REG register let block = unsafe { &*PWM::block() }; let sync_kind = sync_source.get_kind(); - let sync_selection : SyncSelectionRegister = sync_kind.into(); + let sync_selection: SyncSelection = sync_kind.into(); unsafe { block.cap_timer_cfg().modify(|_r, w| { w.cap_synci_en().set_bit(); // Enable sync input @@ -121,28 +120,31 @@ impl CaptureTimer<'d, PWM> { /// ## Overview /// This triggers a software sync event on the capture timer /// Refer to how sync events are handled in the [`CaptureTimer`] documentation. - /// pub fn trigger_sync(&mut self) { // SAFETY: // We modify our MCPWM_CAP_TIMER_CFG_REG register let block = unsafe { &*PWM::block() }; // Trigger a software sync - block.cap_timer_cfg().modify(|_r, w| w.cap_sync_sw().set_bit()); + block + .cap_timer_cfg() + .modify(|_r, w| w.cap_sync_sw().set_bit()); } } /// Repersents the capture event /// Contains the capture time and the captured edge pub struct CaptureEvent { - time : u32, - edge : CaptureEdge + time: u32, + edge: CaptureEdge, } impl CaptureEvent { + /// Gets the captured time pub fn get_time(&self) -> u32 { self.time } + /// Gets the captured edge pub fn get_edge(&self) -> CaptureEdge { self.edge } @@ -154,16 +156,16 @@ impl CaptureEvent { /// * Enable/Disable capturing on this channel /// * Setting the capture input GPIO pin /// * Weather to trigger capture events on rising and/or falling edges -/// * Read the last capture edge, and the last capture time -pub struct CaptureChannel<'d, const CHAN: usize, PWM> { +/// * Read the last capture edge, and the last capture time +pub struct CaptureChannel<'d, const CHAN: u8, PWM> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } -impl CaptureChannel { - pub(super) fn new(guard: PeripheralGuard) -> Self { - Timer { +impl<'d, const CHAN: u8, PWM: PwmPeripheral> CaptureChannel<'d, CHAN, PWM> { + pub(super) fn new(guard: PeripheralGuard) -> Self { + Self { phantom: PhantomData, _guard: guard, _pwm_clock_guard: PwmClockGuard::new::(), @@ -171,11 +173,13 @@ impl CaptureChannel { } /// Enables this capture channel - pub fn set_enable(&mut self, enable : bool) { + pub fn set_enable(&mut self, enable: bool) { // SAFETY: // We only write to our MCPWM_CAP_CHx_CFG_REG register let block = unsafe { &*PWM::block() }; - block.cap_ch_cfg(CHAN).modify(|_, w| w.en().variant(enable)); + block + .cap_ch_cfg(CHAN as usize) + .modify(|_, w| w.en().variant(enable)); } /// Set the capture signal (pin/high/low) for this channel @@ -206,12 +210,14 @@ impl CaptureChannel { /// - If configured for both edges, captures occur every Nth edge (rising + falling combined) /// /// Passing in a value of prescaler = 0 into this function will set the prescaler value of 1 - pub fn set_prescaler(&mut self, prescaler : u8) { + pub fn set_prescaler(&mut self, prescaler: u8) { // SAFETY: // We only write to our MCPWM_CAP_CHx_CFG_REG register let block = unsafe { &*PWM::block() }; unsafe { - block.cap_ch_cfg(CHAN).modify(|_, w| w.prescale().bits(prescaler)); + block + .cap_ch_cfg(CHAN as usize) + .modify(|_, w| w.prescale().bits(prescaler)); } } @@ -223,7 +229,7 @@ impl CaptureChannel { // We are modifying a shared peripheral interrupt enable register let block = unsafe { &*PWM::block() }; block - .cap_ch_cfg(CHAN) + .cap_ch_cfg(CHAN as usize) .write(|w| w.mode().variant(capture_mode)); // Enable the capture interrupt @@ -241,24 +247,21 @@ impl CaptureChannel { block.int_ena().modify(|_, w| w.cap(CHAN as u8).clear_bit()); } - // Checks if the interrupt was set for this channel - pub fn is_interupt_set(&mut self) -> bool { + /// If the interrupt was set for this channel + pub fn is_interupt_set(&mut self) -> bool { // SAFTEY: // We only read from our MCPWM_INT_ST_REG register let block = unsafe { &*PWM::block() }; block.int_st().read().cap(CHAN as u8).bit() } - // Gets the captured event - pub fn get_event(&mut self) -> CaptureEvent { + /// Gets the last captured event + pub fn get_event(&mut self) -> CaptureEvent { // SAFTEY: // We only read from our MCPWM_INT_ST_REG & MCPWM_CAP_STATUS_REG register let block = unsafe { &*PWM::block() }; - let time = block.cap_ch(CHAN).read().value().bits(); + let time = block.cap_ch(CHAN as usize).read().value().bits(); let edge = block.cap_status().read().cap_edge(CHAN as u8).variant(); - CaptureEvent { - time, - edge - } + CaptureEvent { time, edge } } } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index 29e5c80897d..a8575964005 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -88,10 +88,12 @@ use operator::Operator; use timer::Timer; #[cfg(soc_has_mcpwm0)] -use crate::gpio::InputSignal; use crate::{ - gpio::{Input, OutputSignal}, - mcpwm::capture::{CaptureChannel, CaptureTimer}, + gpio::{InputSignal, OutputSignal}, + mcpwm::{ + capture::{CaptureChannel, CaptureTimer}, + sync::SyncLine, + }, pac, private::OnDrop, soc::clocks::{self, ClockTree}, @@ -137,11 +139,11 @@ impl PwmClockGuard { pub struct McPwm<'d, PWM> { _inner: PWM, /// Timer0 - pub timer0: Timer<0, PWM>, + pub timer0: Timer<'d, 0, PWM>, /// Timer1 - pub timer1: Timer<1, PWM>, + pub timer1: Timer<'d, 1, PWM>, /// Timer2 - pub timer2: Timer<2, PWM>, + pub timer2: Timer<'d, 2, PWM>, /// Operator0 pub operator0: Operator<'d, 0, PWM>, /// Operator1 @@ -151,11 +153,17 @@ pub struct McPwm<'d, PWM> { /// Capture Timer pub capture_timer: CaptureTimer<'d, PWM>, /// Capture0 - pub capture0: CaptureChannel<0, PWM>, + pub capture0: CaptureChannel<'d, 0, PWM>, /// Capture1 - pub capture1: CaptureChannel<1, PWM>, + pub capture1: CaptureChannel<'d, 1, PWM>, /// Capture2 - pub capture2: CaptureChannel<2, PWM>, + pub capture2: CaptureChannel<'d, 2, PWM>, + /// Sync0 + pub sync0: SyncLine<'d, 0, PWM>, + /// Sync1 + pub sync1: SyncLine<'d, 1, PWM>, + /// Sync2 + pub sync2: SyncLine<'d, 2, PWM>, } impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { @@ -185,6 +193,9 @@ impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { capture0: CaptureChannel::new(guard.clone()), capture1: CaptureChannel::new(guard.clone()), capture2: CaptureChannel::new(guard), + sync0: SyncLine::new(), + sync1: SyncLine::new(), + sync2: SyncLine::new(), } } } @@ -307,9 +318,9 @@ pub trait PwmPeripheral: crate::private::Sealed { fn block() -> *const RegisterBlock; /// Get operator GPIO mux output signal fn output_signal() -> OutputSignal; - // Get operator GPIO mux capture input signal + /// Get operator GPIO mux capture input signal fn capture_input_signal() -> InputSignal; - // Get operator GPIO mux sync input signal + /// Get operator GPIO mux sync input signal fn sync_input_signal() -> InputSignal; /// Peripheral fn peripheral() -> Peripheral; diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 2cd22874077..13c2137fe06 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -192,7 +192,7 @@ impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> { /// /// ### Note: /// By default TIMER0 is used - pub fn set_timer(&mut self, timer: &Timer) { + pub fn set_timer(&mut self, timer: &Timer<'d, TIM, PWM>) { let _ = timer; // SAFETY: // We only write to our OPERATORx_TIMERSEL register diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index 7d3b8ac4a52..1c6c5c2379b 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -8,15 +8,9 @@ //! //! This module provides the flexability to map any of the sync line //! to any GPIO signal. Aswell to repersent any timer's sync_out source. -use core::{marker::PhantomData, panic}; +use core::marker::PhantomData; -use esp_sync::RawMutex; - -use super::PeripheralGuard; -use crate::{ - gpio::{InputSignal, interconnect::PeripheralInput}, - mcpwm::{PwmClockGuard, PwmPeripheral}, -}; +use crate::{gpio::interconnect::PeripheralInput, mcpwm::PwmPeripheral}; /// Must hide the get kind from public facing API /// prevents users from creating any sync kind @@ -30,24 +24,23 @@ mod sealed { } pub trait InternalSyncSource { - fn get_kind(&self) -> SyncKind; + fn get_kind(&self) -> super::SyncKind; } } -// Give our crate access to the internal sync source -// and sync kind +/// Give our crate access to the internal sync source and sync kind pub(crate) use sealed::{InternalSyncSource, SyncKind}; /// Public trait to repersent a sync source -pub trait SyncSource: sealed::InternalSyncSource {} +pub trait SyncSource: InternalSyncSource {} /// Sync out for timers #[derive(Clone, Copy)] -pub struct SyncOut<'d, PWM> { +pub struct SyncOut<'d> { timer: u8, - _phantom: PhantomData<'d, PWM>, + _phantom: PhantomData<&'d u8>, } -impl<'d, PWM: PwmPeripheral> SyncOut<'d, PWM> { +impl<'d> SyncOut<'d> { pub(crate) fn new() -> Self { Self { timer: TIM, @@ -56,7 +49,7 @@ impl<'d, PWM: PwmPeripheral> SyncOut<'d, PWM> { } } -impl<'d, PWM: PwmPeripheral> sealed::InternalSyncSource for SyncOut<'d, PWM> { +impl<'d> sealed::InternalSyncSource for SyncOut<'d> { fn get_kind(&self) -> SyncKind { SyncKind::TimerSyncOut(self.timer) } @@ -64,11 +57,13 @@ impl<'d, PWM: PwmPeripheral> sealed::InternalSyncSource for SyncOut<'d, PWM> { /// There are only a limited number sync lines for the MCPWM unit #[derive(Clone, Copy)] -pub struct SyncLine { - _phantom: PhantomData, +pub struct SyncLine<'d, const SYNC: u8, PWM> { + _phantom: PhantomData<&'d PWM>, } -impl sealed::InternalSyncSource for SyncLine { +impl<'d, const SYNC: u8, PWM: PwmPeripheral> sealed::InternalSyncSource + for SyncLine<'d, SYNC, PWM> +{ fn get_kind(&self) -> SyncKind { SyncKind::SyncLine(SYNC) } @@ -97,36 +92,37 @@ impl<'d, const SYNC: u8, PWM: PwmPeripheral> SyncLine<'d, SYNC, PWM> { } } -// Values for any of the sync selection registers +/// Values for any of the sync selection registers #[repr(u8)] #[derive(Copy, Clone)] -pub(crate) enum SyncSelectionRegister { - // Select no sync input for the capture timer +pub(crate) enum SyncSelection { + /// Select no sync input for the capture timer None = 0, - // Select the timers sync source for a timer's sync out, + /// Select the timers sync source for a timer's sync out, Timer0SyncOut = 1, Timer1SyncOut = 2, Timer2SyncOut = 3, - // Select the timers sync source from a sync line + /// Select the timers sync source from a sync line SyncLine0 = 4, SyncLine1 = 5, SyncLine2 = 6, } -// Provides a simple way of translating the internal SyncKind -impl From for SyncSelectionRegister { +/// Provides a simple way of translating the internal SyncKind to +/// the value for sync selection used in SYNCI_SEL register fields +impl From for SyncSelection { fn from(value: SyncKind) -> Self { match value { SyncKind::SyncLine(line) => match line { - 0 => SyncSelectionRegister::SyncLine0, - 1 => SyncSelectionRegister::SyncLine1, - 2 => SyncSelectionRegister::SyncLine2, + 0 => SyncSelection::SyncLine0, + 1 => SyncSelection::SyncLine1, + 2 => SyncSelection::SyncLine2, _ => unreachable!(), }, SyncKind::TimerSyncOut(timer) => match timer { - 0 => SyncSelectionRegister::Timer0SyncOut, - 1 => SyncSelectionRegister::Timer1SyncOut, - 2 => SyncSelectionRegister::Timer2SyncOut, + 0 => SyncSelection::Timer0SyncOut, + 1 => SyncSelection::Timer1SyncOut, + 2 => SyncSelection::Timer2SyncOut, _ => unreachable!(), }, } diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index f2ef5927b19..999d821facc 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -13,7 +13,7 @@ use crate::{ PeripheralClockConfig, PwmClockGuard, PwmPeripheral, - sync::{SyncOut, SyncSource}, + sync::{SyncOut, SyncSelection, SyncSource}, }, pac, time::Rate, @@ -24,13 +24,13 @@ use crate::{ /// Every timer of a particular [`MCPWM`](super::McPwm) peripheral can be used /// as a timing reference for every /// [`Operator`](super::operator::Operator) of that peripheral -pub struct Timer { - pub(super) phantom: PhantomData, +pub struct Timer<'d, const TIM: u8, PWM> { + pub(super) phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } -impl Timer { +impl<'d, const TIM: u8, PWM: PwmPeripheral> Timer<'d, TIM, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { Timer { phantom: PhantomData, @@ -79,16 +79,16 @@ impl Timer { self.cfg1().write(|w| unsafe { w.mod_().bits(0) }); } - //! Set the timer counter to the provided value - //! - //! ## Overview - //! Internally we set the timers phase and direction - //! Then trigger a software sync event. - //! - //! Note: This triggers a sync out event. If a timer is listening - //! to this timers sync out source a sync event will be triggered. - //! Refer to how sync events are handled for [`super::CaptureTimer`] or [`Timer`] - //! in the their respective documentation. + /// Set the timer counter to the provided value + /// + /// ## Overview + /// Internally we set the timers phase and direction + /// Then trigger a software sync event. + /// + /// Note: This triggers a sync out event. If a timer is listening + /// to this timers sync out source a sync event will be triggered. + /// Refer to how sync events are handled for [`super::CaptureTimer`] or [`Timer`] + /// in the their respective documentation. pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { self.set_sync_phase(phase); self.set_sync_counter_direction(direction); @@ -100,11 +100,7 @@ impl Timer { // SAFETY: // We only write to our TIMERx_SYNC register let tmr = unsafe { Self::tmr() }; - tmr.sync().modify(|_r, w| { - unsafe { - w.phase().bits(phase) - } - }); + tmr.sync().modify(|_r, w| unsafe { w.phase().bits(phase) }); } /// Set the timers sync counter direction @@ -114,21 +110,18 @@ impl Timer { // SAFETY: // We only write to our TIMERx_SYNC register let tmr = unsafe { Self::tmr() }; - tmr.sync().modify(|_r, w| { - w.phase_direction().bit(direction as u8 != 0) - }); + tmr.sync() + .modify(|_r, w| w.phase_direction().bit(direction as u8 != 0)); } /// Trigger a software sync event /// Note: This always triggers a sync out event even if the - /// sync out select is set to when + /// sync out select is set to when pub fn trigger_sync(&mut self) { // SAFETY: // We only write to our TIMERx_SYNC register let tmr = unsafe { Self::tmr() }; - tmr.sync().modify(|r, w| { - w.sw().bit(!r.sw().bit()) - }); + tmr.sync().modify(|r, w| w.sw().bit(!r.sw().bit())); } /// Read the counter value and counter direction of the timer @@ -139,18 +132,19 @@ impl Timer { (reg.value().bits(), reg.direction().bit_is_set().into()) } - pub fn set_sync_out_selection(&mut self, sync_out : SyncOutSelection) { + /// Selects the how the timer fires sync events + pub fn set_sync_out_selection(&mut self, sync_out: SyncOutSelection) { // SAFETY: // We only modify our TIMERx_SYNC register let timer = unsafe { Self::tmr() }; // Disable sync input on our timer - timer.sync().modify(|_r, w| unsafe { - w.synco_sel.bits(sync_out as u8) - }); + timer + .sync() + .modify(|_r, w| unsafe { w.synco_sel().bits(sync_out as u8) }); } /// Returns the timers sync_out source - pub fn get_sync_out(&self) -> SyncOut<'d, PWM> { + pub fn get_sync_out(&self) -> SyncOut<'d> { SyncOut::new::() } @@ -162,9 +156,9 @@ impl Timer { // SAFETY: // We only modify our TIMERx_SYNC register let timer = unsafe { Self::tmr() }; - + // Update sync select first - let sync_select : SyncSelectionRegister = sync.get_kind().into(); + let sync_select: SyncSelection = sync.get_kind().into(); pwm.timer_synci_cfg().modify(|_r, w| { unsafe { w.timer_syncisel(TIM).bits(sync_select as u8) // Update timer input sync selection @@ -175,6 +169,7 @@ impl Timer { timer.sync().modify(|_r, w| w.synci_en().set_bit()); } + /// Clears the sync in for the timer and disables sync input pub fn clear_sync_in(&mut self) { // SAFETY: // We only modify our TIMERx_SYNC register @@ -202,8 +197,8 @@ impl Timer { } /// Sync out selection for the timer -/// -/// Note: +/// +/// Note: /// During a software sync event triggered by [`Timer::trigger_sync`] or /// [`Timer::set_counter`] a sync out is always triggered regardless if /// if the timer was configured with [`SyncOutSelection::SyncWhenEqualZero`] or @@ -212,10 +207,10 @@ impl Timer { #[repr(u8)] pub enum SyncOutSelection { /// Sync out is triggered when a timer receives a sync in - SyncIn = 0, - // Sync out is triggered when the timer equals zero - SyncWhenEqualZero = 1, - // Sync out is triggered when the timer equals the period + SyncIn = 0, + /// Sync out is triggered when the timer equals zero + SyncWhenEqualZero = 1, + /// Sync out is triggered when the timer equals the period SyncWhenEqualPeriod = 2, } @@ -299,7 +294,7 @@ impl TimerClockConfig { } } - // Sets the stop timer conditions + /// Sets the stop timer conditions pub fn with_stop_conditions(self, condition: StopCondition) -> Self { Self { stop_condition: condition, @@ -339,10 +334,10 @@ pub enum StopCondition { RunContinuously = 2, /// Defines to start the timer now and run till the /// next time the timers counts equal zeros - StopAtZero = 3, + StopAtZero = 3, /// Defines to start the timer now and run till the /// next time the timers counts equals period - StopAtPeriod = 4, + StopAtPeriod = 4, } /// PWM working mode From 7387a2805001063f8f239a1f3ca41a359694bba6 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Mon, 30 Mar 2026 00:45:55 -0600 Subject: [PATCH 07/37] Update Cargo.toml Lastest PAC version --- esp-hal/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 4150016d12c..34aae1c7168 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -147,7 +147,7 @@ ufmt-write = { version = "0.1", optional = true } esp32 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc794983b" } +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc79498" } esp32c2 = { version = "0.28", features = [ "critical-section", "rt", @@ -163,7 +163,7 @@ esp32c5 = { version = "0.1", features = [ esp32c6 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc794983b" } +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc79498" } esp32c61 = { version = "0.1", features = [ "critical-section", "rt", @@ -179,7 +179,7 @@ esp32s2 = { version = "0.30", features = [ esp32s3 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc794983b" } +], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc79498" } [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { version = "0.15.0" } From 47058eb02b83aee2f34a7c14f28a25a755cf10fc Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Mon, 30 Mar 2026 03:03:04 -0600 Subject: [PATCH 08/37] Update sync.rs --- esp-hal/src/mcpwm/sync.rs | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index 1c6c5c2379b..a05c26ee09e 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -12,23 +12,17 @@ use core::marker::PhantomData; use crate::{gpio::interconnect::PeripheralInput, mcpwm::PwmPeripheral}; -/// Must hide the get kind from public facing API -/// prevents users from creating any sync kind -mod sealed { - /// Repersents the different types of sync sources - /// Either from sync lines or from timers sync out - #[derive(Clone, Copy)] - pub enum SyncKind { - SyncLine(u8), - TimerSyncOut(u8), - } +/// Repersents the different types of sync sources +/// Either from sync lines or from timers sync out +#[derive(Clone, Copy)] +pub(crate) enum SyncKind { + SyncLine(u8), + TimerSyncOut(u8), +} - pub trait InternalSyncSource { - fn get_kind(&self) -> super::SyncKind; - } +pub(crate) trait InternalSyncSource: crate::private::Sealed { + fn get_kind(&self) -> SyncKind; } -/// Give our crate access to the internal sync source and sync kind -pub(crate) use sealed::{InternalSyncSource, SyncKind}; /// Public trait to repersent a sync source pub trait SyncSource: InternalSyncSource {} @@ -49,7 +43,8 @@ impl<'d> SyncOut<'d> { } } -impl<'d> sealed::InternalSyncSource for SyncOut<'d> { +impl<'d> crate::private::Sealed for SyncOut<'d> {} +impl<'d> InternalSyncSource for SyncOut<'d> { fn get_kind(&self) -> SyncKind { SyncKind::TimerSyncOut(self.timer) } @@ -61,9 +56,9 @@ pub struct SyncLine<'d, const SYNC: u8, PWM> { _phantom: PhantomData<&'d PWM>, } -impl<'d, const SYNC: u8, PWM: PwmPeripheral> sealed::InternalSyncSource - for SyncLine<'d, SYNC, PWM> -{ +impl<'d, const SYNC: u8, PWM: PwmPeripheral> crate::private::Sealed for SyncLine<'d, SYNC, PWM> {} + +impl<'d, const SYNC: u8, PWM: PwmPeripheral> InternalSyncSource for SyncLine<'d, SYNC, PWM> { fn get_kind(&self) -> SyncKind { SyncKind::SyncLine(SYNC) } From 848a5e8c4444c34af0de1abb3a234586c61a0a2e Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Mon, 30 Mar 2026 03:14:26 -0600 Subject: [PATCH 09/37] Interrupt Handler --- esp-hal/src/mcpwm/capture.rs | 7 +++++++ esp-hal/src/mcpwm/mod.rs | 32 ++++++++++++++++++++++++++++++++ esp-hal/src/mcpwm/sync.rs | 4 ++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index afb84c4e350..f2306946af6 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -255,6 +255,13 @@ impl<'d, const CHAN: u8, PWM: PwmPeripheral> CaptureChannel<'d, CHAN, PWM> { block.int_st().read().cap(CHAN as u8).bit() } + pub fn clear_interrupt(&mut self) { + // SAFTEY: + // We only read from our MCPWM_INT_CLR_REG register + let block = unsafe { &*PWM::block() }; + block.int_clr().write(|w| w.cap(CHAN).bit(true)); + } + /// Gets the last captured event pub fn get_event(&mut self) -> CaptureEvent { // SAFTEY: diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index a8575964005..1f1bc759d1d 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -90,11 +90,13 @@ use timer::Timer; #[cfg(soc_has_mcpwm0)] use crate::{ gpio::{InputSignal, OutputSignal}, + interrupt::{self, InterruptHandler}, mcpwm::{ capture::{CaptureChannel, CaptureTimer}, sync::SyncLine, }, pac, + peripherals::Interrupt, private::OnDrop, soc::clocks::{self, ClockTree}, system::{Peripheral, PeripheralGuard}, @@ -198,6 +200,18 @@ impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { sync2: SyncLine::new(), } } + + /// Set the interrupt handler for the MCPWM peripheral. + /// + /// Note that this will replace any previously registered interrupt + /// handlers. + #[instability::unstable] + pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { + for core in crate::system::Cpu::other() { + crate::interrupt::disable(core, PWM::interrupt()); + } + interrupt::bind_handler(PWM::interrupt(), handler); + } } /// Clock configuration of the MCPWM peripheral @@ -322,6 +336,8 @@ pub trait PwmPeripheral: crate::private::Sealed { fn capture_input_signal() -> InputSignal; /// Get operator GPIO mux sync input signal fn sync_input_signal() -> InputSignal; + /// Interrupt + fn interrupt() -> Interrupt; /// Peripheral fn peripheral() -> Peripheral; } @@ -332,6 +348,10 @@ impl PwmPeripheral for crate::peripherals::MCPWM0<'_> { Self::regs() } + fn interrupt() -> Interrupt { + Interrupt::MCPWM0 + } + fn output_signal() -> OutputSignal { match (OP, IS_A) { (0, true) => OutputSignal::PWM0_0A, @@ -373,6 +393,10 @@ impl PwmPeripheral for crate::peripherals::MCPWM1<'_> { Self::regs() } + fn interrupt() -> Interrupt { + Interrupt::MCPWM1 + } + fn output_signal() -> OutputSignal { match (OP, IS_A) { (0, true) => OutputSignal::PWM1_0A, @@ -407,3 +431,11 @@ impl PwmPeripheral for crate::peripherals::MCPWM1<'_> { Peripheral::Mcpwm1 } } + +impl<'d, PWM: PwmPeripheral + 'd> crate::private::Sealed for McPwm<'d, PWM> {} +#[instability::unstable] +impl<'d, PWM: PwmPeripheral + 'd> crate::interrupt::InterruptConfigurable for McPwm<'d, PWM> { + fn set_interrupt_handler(&mut self, handler: InterruptHandler) { + self.set_interrupt_handler(handler); + } +} diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index a05c26ee09e..d80c17531c3 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -42,7 +42,7 @@ impl<'d> SyncOut<'d> { } } } - +impl<'d> SyncSource for SyncOut<'d> {} impl<'d> crate::private::Sealed for SyncOut<'d> {} impl<'d> InternalSyncSource for SyncOut<'d> { fn get_kind(&self) -> SyncKind { @@ -56,8 +56,8 @@ pub struct SyncLine<'d, const SYNC: u8, PWM> { _phantom: PhantomData<&'d PWM>, } +impl<'d, const SYNC: u8, PWM: PwmPeripheral> SyncSource for SyncLine<'d, SYNC, PWM> {} impl<'d, const SYNC: u8, PWM: PwmPeripheral> crate::private::Sealed for SyncLine<'d, SYNC, PWM> {} - impl<'d, const SYNC: u8, PWM: PwmPeripheral> InternalSyncSource for SyncLine<'d, SYNC, PWM> { fn get_kind(&self) -> SyncKind { SyncKind::SyncLine(SYNC) From 0c92475533a77b05b50a03eb805b46a1db7e677a Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Tue, 31 Mar 2026 16:11:41 -0600 Subject: [PATCH 10/37] Updated documentation added some new feactures --- esp-hal/src/mcpwm/capture.rs | 281 +++++++++++++++++++++++-------- esp-hal/src/mcpwm/mod.rs | 309 +++++++++++++++++++--------------- esp-hal/src/mcpwm/operator.rs | 39 +++-- esp-hal/src/mcpwm/sync.rs | 157 +++++++++++------ esp-hal/src/mcpwm/timer.rs | 126 +++++++++++--- 5 files changed, 614 insertions(+), 298 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index f2306946af6..185d17bd793 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -1,3 +1,15 @@ +#![cfg_attr(docsrs, procmacros::doc_replace( + "mcpwm_freq" => { + cfg(not(esp32h2)) => "40", + cfg(esp32h2) => "32" + }, + "clock_src" => { + cfg(esp32) => "PLL_F160M (160 MHz)", + cfg(esp32s3) => "CRYPTO_PWM_CLK (160 MHz)", + cfg(esp32c6) => "PLL_F160M (160 MHz)", + cfg(esp32h2) => "PLL_F96M_CLK (96 MHz)", + } +))] //! # MCPWM Capture Module //! //! ## Overview @@ -14,8 +26,17 @@ //! for capturing the rising and/or falling edge of a signal. This module allows //! for the ability to trigger software captures. //! +//! ### Capture Timer //! Capture timer can be configured to sync with a PWM timer during specific events //! either when the PWM timer sync out event, or a sync in from an external GPIO pin. +//! Note: Capture timer has a default source of __clock_src__ +//! +//! ## Example +//! +//! This example shows configuring MCPWM for receiving +//! rising and falling edges from a GPIO pin. +//! +//! TODO Write code for this use core::marker::PhantomData; use super::PeripheralGuard; @@ -26,8 +47,8 @@ pub use crate::pac::mcpwm0::{ use crate::{ gpio::interconnect::PeripheralInput, mcpwm::{ + Instance, PwmClockGuard, - PwmPeripheral, sync::{SyncSelection, SyncSource}, }, }; @@ -38,24 +59,19 @@ use crate::{ /// - This timer is shared by all instances of [`CaptureChannel`] for a MCPWM. /// During capture events on any of the channels the time stored in this timer will be /// loaded into the [`CaptureEvent`]'s time. -/// - This is a timer has the clock source of APB_CLK. -/// - A sync source can be selected by calling [`CaptureTimer::set_sync`] with a sync source. -/// - A sync source can be removed by calling [`CaptureTimer::clear_sync`]. -/// -/// During a sync event on this capture timer the counter of the timer is reset. -/// The value that the timer reset to depends on the sync source: -/// - If the sync source came from a timer with [`super::Timer::get_sync_out`] -/// the value that it is reset to the phase value for the given timer. +/// - A sync source can be set by calling [`CaptureTimer::set_sync_in`] with a sync source. +/// - A sync source can be removed by calling [`CaptureTimer::clear_sync_in`]. /// -/// - If the sync sorce came from a sync line in [`super::McPwm`] then the timer -/// is reset with a value of 0. -pub struct CaptureTimer<'d, PWM> { +/// When this timer receives a capture event the counter of the timer is reset. +/// The value that the timer is set to is dependent on [`CaptureTimer::set_sync_phase`] +/// This timer always counts up towards a the positive direction +pub struct CaptureTimer<'d, PWM: Instance> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } -impl<'d, PWM: PwmPeripheral> CaptureTimer<'d, PWM> { +impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { Self { phantom: PhantomData, @@ -68,7 +84,7 @@ impl<'d, PWM: PwmPeripheral> CaptureTimer<'d, PWM> { pub fn start(&mut self) { // SAFETY: // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); block .cap_timer_cfg() @@ -79,18 +95,47 @@ impl<'d, PWM: PwmPeripheral> CaptureTimer<'d, PWM> { pub fn pause(&mut self) { // SAFETY: // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); block .cap_timer_cfg() .modify(|_r, w| w.cap_timer_en().clear_bit()); } + /// Stops the timer and resets the timers counter to 0 + /// Warning: This sets the timers sync phase to 0 + pub fn reset(&mut self) { + self.pause(); + self.set_sync_phase(0); + self.trigger_sync(); + } + + /// Set the sync phase + pub fn set_sync_phase(&mut self, phase: u32) { + // SAFETY: + // We write to our MCPWM_CAP_TIMER_PHASE register + let block = PWM::info().regs(); + + block + .cap_timer_phase() + .write(|w| unsafe { w.cap_phase().bits(phase) }); + } + + /// Get the sync phase + pub fn get_sync_phase(&mut self) -> u32 { + // SAFETY: + // We read from our MCPWM_CAP_TIMER_PHASE register + let block = PWM::info().regs(); + + block.cap_timer_phase().read().cap_phase().bits() + } + /// Clears the captures timer sync source pub fn clear_sync_in(&mut self) { // SAFETY: // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); + unsafe { block.cap_timer_cfg().modify(|_r, w| { w.cap_synci_en().clear_bit(); // Disable sync inputs @@ -102,10 +147,10 @@ impl<'d, PWM: PwmPeripheral> CaptureTimer<'d, PWM> { /// ## Overview /// Sets the capture timers sync source. Refer to how sync events are /// handled in the [`CaptureTimer`] documentation. - pub fn set_sync_in(&mut self, sync_source: impl SyncSource) { + pub fn set_sync_in(&mut self, sync_source: impl SyncSource) { // SAFETY: // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); let sync_kind = sync_source.get_kind(); let sync_selection: SyncSelection = sync_kind.into(); @@ -123,7 +168,8 @@ impl<'d, PWM: PwmPeripheral> CaptureTimer<'d, PWM> { pub fn trigger_sync(&mut self) { // SAFETY: // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); + // Trigger a software sync block .cap_timer_cfg() @@ -150,125 +196,214 @@ impl CaptureEvent { } } -/// A MCPWM Capture Channel +/// Configuration for a capture channel /// -/// The MCPWM Capture Channel has the following functions: -/// * Enable/Disable capturing on this channel -/// * Setting the capture input GPIO pin -/// * Weather to trigger capture events on rising and/or falling edges -/// * Read the last capture edge, and the last capture time -pub struct CaptureChannel<'d, const CHAN: u8, PWM> { +/// ## Overview +/// +/// Capture channel can be configured with a signal input, +/// a invert signal boolean, a capture mode, and a prescaler. +/// +/// The signal input is what the capture channel listens too for +/// rising and or falling edge events, which is configured in capture mode. +/// +/// The invert describes if the input signal is inverted before +/// being sent to the capture channel. If your signal originally had +/// rising edges they are replaced with falling edges and vise versa. +/// Invert signal is useful if the polarity of your signal matters for your code. +/// +/// The prescaler determines how often a capture event is generated +/// from incoming edges. Instead of capturing every valid edge, +/// the hardware will generate a capture event once every `prescale` +/// edges. +/// Note: passing in a value of prescaler = 0 will set a prescaler value of 1. +/// +/// Prescaler rather then scaling the clock speed, can be thought of as a 'capture rate.' +/// The edges counted are those selected by the channel's edge configuration. +/// (rising, falling, or both). For example: +/// - If configured for rising edges only, captures occur every Nth rising edge +/// - If configured for both edges, captures occur every Nth edge (rising + falling combined) +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +// Hash cannot be implemented for CaptureMode +pub struct CaptureChannelConfig { + invert: bool, + capture_mode: CaptureMode, + prescaler: u8, +} + +impl CaptureChannelConfig { + /// Sets the invert value for the config + pub fn with_invert(self, invert: bool) -> Self { + Self { invert, ..self } + } + + /// Sets the capture mode for the config + pub fn with_capture_mode(self, capture_mode: CaptureMode) -> Self { + Self { + capture_mode, + ..self + } + } + + /// Sets the prescaler for the config + pub fn with_prescaler(self, prescaler: u8) -> Self { + Self { prescaler, ..self } + } +} + +impl Default for CaptureChannelConfig { + fn default() -> Self { + Self { + invert: false, + capture_mode: CaptureMode::None, + prescaler: 0, + } + } +} + +/// Capture channel creator +pub struct CaptureChannelCreator<'d, const CHAN: u8, PWM: Instance> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, - _pwm_clock_guard: PwmClockGuard, } -impl<'d, const CHAN: u8, PWM: PwmPeripheral> CaptureChannel<'d, CHAN, PWM> { +impl<'d, const CHAN: u8, PWM: Instance> CaptureChannelCreator<'d, CHAN, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { Self { phantom: PhantomData, _guard: guard, - _pwm_clock_guard: PwmClockGuard::new::(), } } - /// Enables this capture channel - pub fn set_enable(&mut self, enable: bool) { + /// Configure a new capture channel from a config + pub fn configure(self, config: CaptureChannelConfig) -> CaptureChannel<'d, CHAN, PWM> { + let mut new_channel = CaptureChannel { + phantom: PhantomData, + _guard: self._guard, + _pwm_clock_guard: PwmClockGuard::new::(), + }; + new_channel.configure(config); + + new_channel + } +} + +/// A MCPWM Capture Channel +/// +/// The MCPWM Capture Channel has the following functions: +/// * Enable/Disable capturing on this channel +/// * Setting the capture input GPIO pin +/// * Weather to trigger capture events on rising and/or falling edges +/// * Read the last capture edge, and the last capture time +pub struct CaptureChannel<'d, const CHAN: u8, PWM: Instance> { + phantom: PhantomData<&'d PWM>, + _guard: PeripheralGuard, + _pwm_clock_guard: PwmClockGuard, +} + +impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { + pub(super) fn configure(&mut self, config: CaptureChannelConfig) { // SAFETY: // We only write to our MCPWM_CAP_CHx_CFG_REG register - let block = unsafe { &*PWM::block() }; - block - .cap_ch_cfg(CHAN as usize) - .modify(|_, w| w.en().variant(enable)); + let block = PWM::info().regs(); + + let enabled = block.cap_ch_cfg(CHAN as usize).read().en().bit(); + block.cap_ch_cfg(CHAN as usize).write(|w| { + w.mode().variant(config.capture_mode); + w.in_invert().variant(config.invert); + unsafe { + w.prescale().bits(config.prescaler); + } + w.en().variant(enabled) + }); } - /// Set the capture signal (pin/high/low) for this channel - pub fn set_signal_capture(&mut self, source: impl PeripheralInput<'d>) { - let signal = PWM::capture_input_signal::(); + /// Assign the input signal for the capture + pub fn with_signal_input<'a>(self, input: impl PeripheralInput<'a>) -> Self { + let input_signal = PWM::info().capture_input_signal::(); - if signal as usize <= property!("gpio.input_signal_max") { - let source = source.into(); + if input_signal as usize <= property!("gpio.input_signal_max") { + let source = input.into(); source.set_input_enable(true); - signal.connect_to(&source); + input_signal.connect_to(&source); } else { - warn!("Signal {:?} out of range", signal); + warn!("Signal {:?} out of range", input_signal); } + + self } - /// Sets the capture prescaler for the channel. - /// Although the function of the prescaler on capture channels - /// - /// The prescaler determines how often a capture event is generated - /// from incoming edges. Instead of capturing every valid edge, - /// the hardware will generate a capture event once every `capture_rate` - /// edges. - /// - /// The edges counted are those selected by the channel's edge configuration - /// (rising, falling, or both). For example: - /// - /// - If configured for rising edges only, captures occur every Nth rising edge - /// - If configured for both edges, captures occur every Nth edge (rising + falling combined) - /// - /// Passing in a value of prescaler = 0 into this function will set the prescaler value of 1 - pub fn set_prescaler(&mut self, prescaler: u8) { + /// Enable or disables this capture channel + pub fn set_enable(&mut self, enable: bool) { // SAFETY: // We only write to our MCPWM_CAP_CHx_CFG_REG register - let block = unsafe { &*PWM::block() }; - unsafe { - block - .cap_ch_cfg(CHAN as usize) - .modify(|_, w| w.prescale().bits(prescaler)); - } + let block = PWM::info().regs(); + block + .cap_ch_cfg(CHAN as usize) + .modify(|_, w| w.en().variant(enable)); + } + + /// Set the config + pub fn set_config(&mut self, config: CaptureChannelConfig) { + self.configure(config); } /// Sets the capture channel to listen to captures on specific edge events /// This channel can listen to Falling, and/or Rising edges on any of the GPIO pins. + #[instability::unstable] pub fn listen(&mut self, capture_mode: CaptureMode) { // SAFETY: // We write to our MCPWM_CAP_CHx_CFG_REG register // We are modifying a shared peripheral interrupt enable register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); block .cap_ch_cfg(CHAN as usize) .write(|w| w.mode().variant(capture_mode)); // Enable the capture interrupt - block.int_ena().modify(|_, w| w.cap(CHAN as u8).set_bit()); + block.int_ena().modify(|_, w| w.cap(CHAN).set_bit()); } /// Stops listening to events on this channel + #[instability::unstable] pub fn unlisten(&mut self) { // SAFTEY: // We are writing to a SHARED peripheral interrupt enable register // Tldr lowk don't know if I should use a mutex or not?? - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); // We can unlisten from events simply by disabling the interrupt - block.int_ena().modify(|_, w| w.cap(CHAN as u8).clear_bit()); + block.int_ena().modify(|_, w| w.cap(CHAN).clear_bit()); } /// If the interrupt was set for this channel + #[instability::unstable] pub fn is_interupt_set(&mut self) -> bool { // SAFTEY: // We only read from our MCPWM_INT_ST_REG register - let block = unsafe { &*PWM::block() }; - block.int_st().read().cap(CHAN as u8).bit() + let block = PWM::info().regs(); + + block.int_st().read().cap(CHAN).bit() } + /// Clear the interrupt + #[instability::unstable] pub fn clear_interrupt(&mut self) { // SAFTEY: // We only read from our MCPWM_INT_CLR_REG register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); + block.int_clr().write(|w| w.cap(CHAN).bit(true)); } /// Gets the last captured event + #[instability::unstable] pub fn get_event(&mut self) -> CaptureEvent { // SAFTEY: // We only read from our MCPWM_INT_ST_REG & MCPWM_CAP_STATUS_REG register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); + let time = block.cap_ch(CHAN as usize).read().value().bits(); - let edge = block.cap_status().read().cap_edge(CHAN as u8).variant(); + let edge = block.cap_status().read().cap_edge(CHAN).variant(); CaptureEvent { time, edge } } } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index 1f1bc759d1d..84297803c22 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -84,6 +84,8 @@ //! # {after_snippet} //! ``` +use core::marker::PhantomData; + use operator::Operator; use timer::Timer; @@ -92,11 +94,10 @@ use crate::{ gpio::{InputSignal, OutputSignal}, interrupt::{self, InterruptHandler}, mcpwm::{ - capture::{CaptureChannel, CaptureTimer}, + capture::{CaptureChannelCreator, CaptureTimer}, sync::SyncLine, }, pac, - peripherals::Interrupt, private::OnDrop, soc::clocks::{self, ClockTree}, system::{Peripheral, PeripheralGuard}, @@ -114,52 +115,175 @@ pub mod timer; type RegisterBlock = pac::mcpwm0::RegisterBlock; -#[allow(dead_code)] // Field is seemingly unused but we rely on its Drop impl -struct PwmClockGuard(OnDrop); +/// Repersents info for MCPWM peripheral +#[doc(hidden)] +#[derive(Debug)] +#[non_exhaustive] +#[allow(private_interfaces, reason = "Unstable details")] +pub struct Info { + /// Register block + register_block: *const RegisterBlock, + /// System peripheral marker. + _peripheral: crate::system::Peripheral, + /// Interrupt marker + _interrupt: crate::peripherals::Interrupt, + /// Sync inputs + sync_input: [InputSignal; 3], + /// Capture inputs + capture_input: [InputSignal; 3], + /// Operator A outputs + operator_a_output: [OutputSignal; 3], + /// Operator B outputs + operator_b_output: [OutputSignal; 3], +} -impl PwmClockGuard { - fn instance() -> clocks::McpwmInstance { - match PWM::peripheral() { - Peripheral::Mcpwm0 => clocks::McpwmInstance::Mcpwm0, - #[cfg(soc_has_mcpwm1)] - Peripheral::Mcpwm1 => clocks::McpwmInstance::Mcpwm1, - _ => unreachable!(), +impl Info { + /// Returns the register block for this PWM instance. + pub fn regs(&self) -> &RegisterBlock { + unsafe { &*self.register_block } + } + + pub fn peripheral(&self) -> crate::system::Peripheral { + self._peripheral + } + + pub fn interrupt(&self) -> crate::peripherals::Interrupt { + self._interrupt + } + + pub fn operator_output_signal(&self) -> OutputSignal { + match IS_A { + true => self.operator_a_output[OP as usize], + false => self.operator_b_output[OP as usize], } } - pub fn new() -> Self { - ClockTree::with(move |clocks| Self::instance::().request_function_clock(clocks)); + pub fn sync_input_signal(&self) -> InputSignal { + self.sync_input[SYNC as usize] + } - Self(OnDrop::new(|| { - ClockTree::with(move |clocks| Self::instance::().release_function_clock(clocks)); - })) + pub fn capture_input_signal(&self) -> InputSignal { + self.capture_input[CHAN as usize] + } +} + +impl PartialEq for Info { + fn eq(&self, other: &Self) -> bool { + core::ptr::eq(self.register_block, other.register_block) + } +} + +unsafe impl Sync for Info {} + +/// Repersents a MCPWM peripheral +pub trait Instance { + /// Repersents the ID + const ID: u8 = 0; + + #[doc(hidden)] + /// Returns the peripheral data. + fn info() -> &'static Info; +} + +#[cfg(soc_has_mcpwm0)] +impl Instance for crate::peripherals::MCPWM0<'_> { + const ID: u8 = 0; + + /// Returns peripheral data for MCPWM 0 + fn info() -> &'static Info { + static INFO: Info = Info { + register_block: crate::peripherals::MCPWM0::regs(), + _peripheral: crate::system::Peripheral::Mcpwm0, + _interrupt: crate::peripherals::Interrupt::MCPWM0, + sync_input: [ + InputSignal::PWM0_SYNC0, + InputSignal::PWM0_SYNC1, + InputSignal::PWM0_SYNC2, + ], + capture_input: [ + InputSignal::PWM0_CAP0, + InputSignal::PWM0_CAP1, + InputSignal::PWM0_CAP2, + ], + operator_a_output: [ + OutputSignal::PWM0_0A, + OutputSignal::PWM0_1A, + OutputSignal::PWM0_2A, + ], + operator_b_output: [ + OutputSignal::PWM0_0B, + OutputSignal::PWM0_1B, + OutputSignal::PWM0_2B, + ], + }; + + &INFO + } +} + +#[cfg(soc_has_mcpwm1)] +impl Instance for crate::peripherals::MCPWM1<'_> { + const ID: u8 = 1; + + fn info() -> &'static Info { + static INFO: Info = Info { + register_block: crate::peripherals::MCPWM1::regs(), + _peripheral: crate::system::Peripheral::Mcpwm1, + _interrupt: crate::peripherals::Interrupt::MCPWM1, + sync_input: [ + InputSignal::PWM1_SYNC0, + InputSignal::PWM1_SYNC1, + InputSignal::PWM1_SYNC2, + ], + capture_input: [ + InputSignal::PWM1_CAP0, + InputSignal::PWM1_CAP1, + InputSignal::PWM1_CAP2, + ], + operator_a_output: [ + OutputSignal::PWM1_0A, + OutputSignal::PWM1_1A, + OutputSignal::PWM1_2A, + ], + operator_b_output: [ + OutputSignal::PWM1_0B, + OutputSignal::PWM1_1B, + OutputSignal::PWM1_2B, + ], + }; + + &INFO } } /// The MCPWM peripheral #[non_exhaustive] -pub struct McPwm<'d, PWM> { - _inner: PWM, +pub struct McPwm<'d, PWM: Instance> { + _phantom: PhantomData<&'d PWM>, + /// Timer0 pub timer0: Timer<'d, 0, PWM>, /// Timer1 pub timer1: Timer<'d, 1, PWM>, /// Timer2 pub timer2: Timer<'d, 2, PWM>, + /// Capture Timer + pub capture_timer: CaptureTimer<'d, PWM>, + /// Operator0 pub operator0: Operator<'d, 0, PWM>, /// Operator1 pub operator1: Operator<'d, 1, PWM>, /// Operator2 pub operator2: Operator<'d, 2, PWM>, - /// Capture Timer - pub capture_timer: CaptureTimer<'d, PWM>, + /// Capture0 - pub capture0: CaptureChannel<'d, 0, PWM>, + pub capture0: CaptureChannelCreator<'d, 0, PWM>, /// Capture1 - pub capture1: CaptureChannel<'d, 1, PWM>, + pub capture1: CaptureChannelCreator<'d, 1, PWM>, /// Capture2 - pub capture2: CaptureChannel<'d, 2, PWM>, + pub capture2: CaptureChannelCreator<'d, 2, PWM>, + /// Sync0 pub sync0: SyncLine<'d, 0, PWM>, /// Sync1 @@ -168,14 +292,13 @@ pub struct McPwm<'d, PWM> { pub sync2: SyncLine<'d, 2, PWM>, } -impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { +impl<'d, PWM: Instance> McPwm<'d, PWM> { /// `pwm_clk = clocks.crypto_pwm_clock / (prescaler + 1)` - pub fn new(peripheral: PWM, peripheral_clock: PeripheralClockConfig) -> Self { - let guard = PeripheralGuard::new(PWM::peripheral()); - - let register_block = unsafe { &*PWM::block() }; + pub fn new(_peripheral: PWM, peripheral_clock: PeripheralClockConfig) -> Self { + let guard = PeripheralGuard::new(PWM::info().peripheral()); + let register_block = PWM::info().regs(); - // set prescaler + // set prescaler for timer (0-2) register_block .clk_cfg() .write(|w| unsafe { w.clk_prescale().bits(peripheral_clock.prescaler) }); @@ -184,7 +307,7 @@ impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { register_block.clk().write(|w| w.en().set_bit()); Self { - _inner: peripheral, + _phantom: PhantomData, timer0: Timer::new(guard.clone()), timer1: Timer::new(guard.clone()), timer2: Timer::new(guard.clone()), @@ -192,9 +315,9 @@ impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { operator1: Operator::new(guard.clone()), operator2: Operator::new(guard.clone()), capture_timer: CaptureTimer::new(guard.clone()), - capture0: CaptureChannel::new(guard.clone()), - capture1: CaptureChannel::new(guard.clone()), - capture2: CaptureChannel::new(guard), + capture0: CaptureChannelCreator::new(guard.clone()), + capture1: CaptureChannelCreator::new(guard.clone()), + capture2: CaptureChannelCreator::new(guard), sync0: SyncLine::new(), sync1: SyncLine::new(), sync2: SyncLine::new(), @@ -207,10 +330,12 @@ impl<'d, PWM: PwmPeripheral + 'd> McPwm<'d, PWM> { /// handlers. #[instability::unstable] pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { + let interrupt = PWM::info().interrupt(); + for core in crate::system::Cpu::other() { - crate::interrupt::disable(core, PWM::interrupt()); + crate::interrupt::disable(core, interrupt); } - interrupt::bind_handler(PWM::interrupt(), handler); + interrupt::bind_handler(interrupt, handler); } } @@ -326,115 +451,31 @@ impl PeripheralClockConfig { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FrequencyError; -/// A MCPWM peripheral -pub trait PwmPeripheral: crate::private::Sealed { - /// Get a pointer to the peripheral RegisterBlock - fn block() -> *const RegisterBlock; - /// Get operator GPIO mux output signal - fn output_signal() -> OutputSignal; - /// Get operator GPIO mux capture input signal - fn capture_input_signal() -> InputSignal; - /// Get operator GPIO mux sync input signal - fn sync_input_signal() -> InputSignal; - /// Interrupt - fn interrupt() -> Interrupt; - /// Peripheral - fn peripheral() -> Peripheral; -} - -#[cfg(soc_has_mcpwm0)] -impl PwmPeripheral for crate::peripherals::MCPWM0<'_> { - fn block() -> *const RegisterBlock { - Self::regs() - } - - fn interrupt() -> Interrupt { - Interrupt::MCPWM0 - } - - fn output_signal() -> OutputSignal { - match (OP, IS_A) { - (0, true) => OutputSignal::PWM0_0A, - (1, true) => OutputSignal::PWM0_1A, - (2, true) => OutputSignal::PWM0_2A, - (0, false) => OutputSignal::PWM0_0B, - (1, false) => OutputSignal::PWM0_1B, - (2, false) => OutputSignal::PWM0_2B, - _ => unreachable!(), - } - } - - fn capture_input_signal() -> InputSignal { - match CHAN { - 0 => InputSignal::PWM0_CAP0, - 1 => InputSignal::PWM0_CAP1, - 2 => InputSignal::PWM0_CAP2, - _ => unreachable!(), - } - } - - fn sync_input_signal() -> InputSignal { - match SYNC { - 0 => InputSignal::PWM0_SYNC0, - 1 => InputSignal::PWM0_SYNC1, - 2 => InputSignal::PWM0_SYNC2, - _ => unreachable!(), - } - } - - fn peripheral() -> Peripheral { - Peripheral::Mcpwm0 - } -} - -#[cfg(soc_has_mcpwm1)] -impl PwmPeripheral for crate::peripherals::MCPWM1<'_> { - fn block() -> *const RegisterBlock { - Self::regs() - } - - fn interrupt() -> Interrupt { - Interrupt::MCPWM1 - } - - fn output_signal() -> OutputSignal { - match (OP, IS_A) { - (0, true) => OutputSignal::PWM1_0A, - (1, true) => OutputSignal::PWM1_1A, - (2, true) => OutputSignal::PWM1_2A, - (0, false) => OutputSignal::PWM1_0B, - (1, false) => OutputSignal::PWM1_1B, - (2, false) => OutputSignal::PWM1_2B, - _ => unreachable!(), - } - } +#[allow(dead_code)] // Field is seemingly unused but we rely on its Drop impl +struct PwmClockGuard(OnDrop); - fn capture_input_signal() -> InputSignal { - match CHAN { - 0 => InputSignal::PWM1_CAP0, - 1 => InputSignal::PWM1_CAP1, - 2 => InputSignal::PWM1_CAP2, +impl PwmClockGuard { + fn instance() -> clocks::McpwmInstance { + match PWM::info().peripheral() { + Peripheral::Mcpwm0 => clocks::McpwmInstance::Mcpwm0, + #[cfg(soc_has_mcpwm1)] + Peripheral::Mcpwm1 => clocks::McpwmInstance::Mcpwm1, _ => unreachable!(), } } - fn sync_input_signal() -> InputSignal { - match SYNC { - 0 => InputSignal::PWM1_SYNC0, - 1 => InputSignal::PWM1_SYNC1, - 2 => InputSignal::PWM1_SYNC2, - _ => unreachable!(), - } - } + pub fn new() -> Self { + ClockTree::with(move |clocks| Self::instance::().request_function_clock(clocks)); - fn peripheral() -> Peripheral { - Peripheral::Mcpwm1 + Self(OnDrop::new(|| { + ClockTree::with(move |clocks| Self::instance::().release_function_clock(clocks)); + })) } } -impl<'d, PWM: PwmPeripheral + 'd> crate::private::Sealed for McPwm<'d, PWM> {} +impl<'d, PWM: Instance + 'd> crate::private::Sealed for McPwm<'d, PWM> {} #[instability::unstable] -impl<'d, PWM: PwmPeripheral + 'd> crate::interrupt::InterruptConfigurable for McPwm<'d, PWM> { +impl<'d, PWM: Instance + 'd> crate::interrupt::InterruptConfigurable for McPwm<'d, PWM> { fn set_interrupt_handler(&mut self, handler: InterruptHandler) { self.set_interrupt_handler(handler); } diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 13c2137fe06..0bdc71ce8b2 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -14,7 +14,7 @@ use core::marker::PhantomData; use super::PeripheralGuard; use crate::{ gpio::interconnect::{OutputSignal, PeripheralOutput}, - mcpwm::{PwmClockGuard, PwmPeripheral, timer::Timer}, + mcpwm::{Instance, PwmClockGuard, timer::Timer}, pac, }; @@ -167,13 +167,16 @@ impl DeadTimeCfg { /// implemented) /// * 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<'d, const OP: u8, PWM> { - phantom: PhantomData<&'d PWM>, +pub struct Operator<'d, const OP: u8, PWM> +where + PWM: Instance, +{ + _phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } -impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> { +impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { // Side note: // It would have been nice to deselect any timer reference on peripheral @@ -182,7 +185,7 @@ impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> { // will not disable the timer reference but instead act as though `2` was // written. Operator { - phantom: PhantomData, + _phantom: PhantomData, _guard: guard, _pwm_clock_guard: PwmClockGuard::new::(), } @@ -196,7 +199,7 @@ impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> { let _ = timer; // SAFETY: // We only write to our OPERATORx_TIMERSEL register - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); block.operator_timersel().modify(|_, w| match OP { 0 => unsafe { w.operator0_timersel().bits(TIM) }, 1 => unsafe { w.operator1_timersel().bits(TIM) }, @@ -284,17 +287,16 @@ impl PwmPinConfig { } /// A pin driven by an MCPWM operator -pub struct PwmPin<'d, PWM, const OP: u8, const IS_A: bool> { +pub struct PwmPin<'d, PWM: Instance, const OP: u8, const IS_A: bool> { pin: OutputSignal<'d>, phantom: PhantomData, _guard: PeripheralGuard, } -impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A> { +impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A> { fn new(pin: impl PeripheralOutput<'d>, config: PwmPinConfig) -> Self { let pin = pin.into(); - - let guard = PeripheralGuard::new(PWM::peripheral()); + let guard = PeripheralGuard::new(PWM::info().peripheral()); let mut pin = PwmPin { pin, @@ -304,7 +306,8 @@ impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, pin.set_actions(config.actions); pin.set_update_method(config.update_method); - PWM::output_signal::().connect_to(&pin.pin); + let signal = PWM::info().operator_output_signal::(); + signal.connect_to(&pin.pin); pin.pin.set_output_enable(true); pin @@ -393,7 +396,7 @@ impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, pub fn period(&self) -> u16 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); let tim_select = block.operator_timersel().read(); let tim = match OP { @@ -412,20 +415,20 @@ impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, } unsafe fn ch() -> &'static pac::mcpwm0::CH { - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); block.ch(OP as usize) } } /// Implement no error type for the PwmPin because the method are infallible -impl embedded_hal::pwm::ErrorType +impl embedded_hal::pwm::ErrorType for PwmPin<'_, PWM, OP, IS_A> { type Error = core::convert::Infallible; } /// Implement the trait SetDutyCycle for PwmPin -impl embedded_hal::pwm::SetDutyCycle +impl embedded_hal::pwm::SetDutyCycle for PwmPin<'_, PWM, OP, IS_A> { /// Get the max duty of the PwmPin @@ -486,12 +489,12 @@ impl embedded_hal::pwm::SetD /// // pin_b: ------_________-----------_________----- /// # {after_snippet} /// ``` -pub struct LinkedPins<'d, PWM, const OP: u8> { +pub struct LinkedPins<'d, PWM: Instance, const OP: u8> { pin_a: PwmPin<'d, PWM, OP, true>, pin_b: PwmPin<'d, PWM, OP, false>, } -impl<'d, PWM: PwmPeripheral, const OP: u8> LinkedPins<'d, PWM, OP> { +impl<'d, PWM: Instance, const OP: u8> LinkedPins<'d, PWM, OP> { fn new( pin_a: impl PeripheralOutput<'d>, config_a: PwmPinConfig, @@ -570,7 +573,7 @@ impl<'d, PWM: PwmPeripheral, const OP: u8> LinkedPins<'d, PWM, OP> { } unsafe fn ch() -> &'static pac::mcpwm0::CH { - let block = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); block.ch(OP as usize) } } diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index d80c17531c3..3fc2642f9dc 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -1,71 +1,97 @@ +#![cfg_attr(docsrs, procmacros::doc_replace( + "mcpwm_freq" => { + cfg(not(esp32h2)) => "40", + cfg(esp32h2) => "32" + }, + "clock_src" => { + cfg(esp32) => "PLL_F160M (160 MHz)", + cfg(esp32s3) => "CRYPTO_PWM_CLK (160 MHz)", + cfg(esp32c6) => "PLL_F160M (160 MHz)", + cfg(esp32h2) => "PLL_F96M_CLK (96 MHz)", + } +))] //! # MCPWM Sync Module //! //! ## Overview //! The `Sync` is resposible for managing the different ways -//! MCPWM can listen to sync events. There are 2 different -//! sync sources one that can come from a Timer's sync_out -//! or from a Sync line that can be triggered by an external signal. +//! MCPWM can listen to sync events. There are 2 different types of +//! sync sources. One is a [`SyncOut`] that comes from [`super::Timer::get_sync_out`], +//! or from a [`SyncLine`]. +//! +//! This module provides the flexability to map any of the +//! MCPWM's [`SyncLine`] to any GPIO signal. +//! +//! ## Example +//! +//! ### Configuring a SyncLine signal +//! For configuring a [`SyncLine`] input signal, and then connecting +//! it to timer 0's sync in event. This is useful when you need to sync +//! the timers phase from an external signal such as a zero-cross event +//! for 3 phase PWM. +//! +//! ```rust, no_run +//! use esp_hal::mcpwm::{McPwm, PeripheralClockConfig, Sync::SyncLine}; +//! +//! // initialize peripheral +//! let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(__mcpwm_freq__))?; +//! let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg); +//! +//! // connect sync line 0 to take input from `pin` +//! mcpwm.sync0.set_signal(pin); +//! // connecting sync line 0 for a timer0's sync in +//! mcpwm.timer0.set_sync_in(mcpwm.sync0); +//! ``` //! -//! This module provides the flexability to map any of the sync line -//! to any GPIO signal. Aswell to repersent any timer's sync_out source. +//! ### Chaining 2 or more timers sync events +//! This shows how to configure timer 1 and timer 2 to take in +//! sync events from timer 0. This is useful when many timers require +//! to be phase aligned for proper timing. +//! +//! ```rust, no_run +//! use esp_hal::mcpwm::{McPwm, PeripheralClockConfig}; +//! +//! // initialize peripheral +//! let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(__mcpwm_freq__))?; +//! let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg); +//! +//! // get timer0's sync out +//! let sync_out = mcpwm.timer0.get_sync_out(); +//! // set timer1's sync in source from timer0's sync out +//! mcpwm.timer1.set_sync_in(sync_out); +//! // Optionally set timer2's sync in +//! mcpwm.timer2.set_sync_in(sync_out); +//! ``` use core::marker::PhantomData; -use crate::{gpio::interconnect::PeripheralInput, mcpwm::PwmPeripheral}; - -/// Repersents the different types of sync sources -/// Either from sync lines or from timers sync out -#[derive(Clone, Copy)] -pub(crate) enum SyncKind { - SyncLine(u8), - TimerSyncOut(u8), -} - -pub(crate) trait InternalSyncSource: crate::private::Sealed { - fn get_kind(&self) -> SyncKind; -} +use crate::{gpio::interconnect::PeripheralInput, mcpwm::Instance}; -/// Public trait to repersent a sync source -pub trait SyncSource: InternalSyncSource {} +#[allow(private_bounds)] +/// Public trait to repersent a sync source for a PWM +pub trait SyncSource: InternalSyncSource {} -/// Sync out for timers +/// Sync out created by timers #[derive(Clone, Copy)] -pub struct SyncOut<'d> { - timer: u8, - _phantom: PhantomData<&'d u8>, +pub struct SyncOut<'d, const TIM: u8, PWM: Instance> { + _phantom: PhantomData<&'d PWM>, } -impl<'d> SyncOut<'d> { - pub(crate) fn new() -> Self { +impl<'d, const TIM: u8, PWM: Instance> SyncSource for SyncOut<'d, TIM, PWM> {} +impl<'d, const TIM: u8, PWM: Instance> SyncOut<'d, TIM, PWM> { + pub(super) fn new() -> Self { Self { - timer: TIM, _phantom: PhantomData, } } } -impl<'d> SyncSource for SyncOut<'d> {} -impl<'d> crate::private::Sealed for SyncOut<'d> {} -impl<'d> InternalSyncSource for SyncOut<'d> { - fn get_kind(&self) -> SyncKind { - SyncKind::TimerSyncOut(self.timer) - } -} /// There are only a limited number sync lines for the MCPWM unit #[derive(Clone, Copy)] -pub struct SyncLine<'d, const SYNC: u8, PWM> { +pub struct SyncLine<'d, const SYNC: u8, PWM: Instance> { _phantom: PhantomData<&'d PWM>, } -impl<'d, const SYNC: u8, PWM: PwmPeripheral> SyncSource for SyncLine<'d, SYNC, PWM> {} -impl<'d, const SYNC: u8, PWM: PwmPeripheral> crate::private::Sealed for SyncLine<'d, SYNC, PWM> {} -impl<'d, const SYNC: u8, PWM: PwmPeripheral> InternalSyncSource for SyncLine<'d, SYNC, PWM> { - fn get_kind(&self) -> SyncKind { - SyncKind::SyncLine(SYNC) - } -} - -impl<'d, const SYNC: u8, PWM: PwmPeripheral> SyncLine<'d, SYNC, PWM> { - /// Create a new sync line +impl<'d, const SYNC: u8, PWM: Instance> SyncSource for SyncLine<'d, SYNC, PWM> {} +impl<'d, const SYNC: u8, PWM: Instance> SyncLine<'d, SYNC, PWM> { pub(super) fn new() -> Self { Self { _phantom: PhantomData, @@ -75,7 +101,7 @@ impl<'d, const SYNC: u8, PWM: PwmPeripheral> SyncLine<'d, SYNC, PWM> { /// Set the input signal for the sync line pub fn set_signal(&mut self, source: impl PeripheralInput<'d>) { // configure GPIO matrix → SYNC - let signal = PWM::sync_input_signal::(); + let signal = PWM::info().sync_input_signal::(); if signal as usize <= property!("gpio.input_signal_max") { let source = source.into(); @@ -87,7 +113,39 @@ impl<'d, const SYNC: u8, PWM: PwmPeripheral> SyncLine<'d, SYNC, PWM> { } } +/// Repersents the different types of sync sources +/// Either from sync lines or from timers sync out. +/// +/// Shall only be created from this file +#[derive(Clone, Copy)] +pub(crate) enum SyncKind { + SyncLine(u8), + TimerSyncOut(u8), +} + +/// Internal trait to repersent which pwm unit and +/// sync out it came from. Broadly repersents sync lines, +/// and timer sync out. +pub(crate) trait InternalSyncSource: crate::private::Sealed { + fn get_kind(&self) -> SyncKind; +} + +impl<'d, const TIM: u8, PWM: Instance> crate::private::Sealed for SyncOut<'d, TIM, PWM> {} +impl<'d, const TIM: u8, PWM: Instance> InternalSyncSource for SyncOut<'d, TIM, PWM> { + fn get_kind(&self) -> SyncKind { + SyncKind::TimerSyncOut(TIM) + } +} + +impl<'d, const SYNC: u8, PWM: Instance> crate::private::Sealed for SyncLine<'d, SYNC, PWM> {} +impl<'d, const SYNC: u8, PWM: Instance> InternalSyncSource for SyncLine<'d, SYNC, PWM> { + fn get_kind(&self) -> SyncKind { + SyncKind::SyncLine(SYNC) + } +} + /// Values for any of the sync selection registers +/// This is the internal value used by capture timer, and timers #[repr(u8)] #[derive(Copy, Clone)] pub(crate) enum SyncSelection { @@ -108,17 +166,20 @@ pub(crate) enum SyncSelection { impl From for SyncSelection { fn from(value: SyncKind) -> Self { match value { + // SAFTEY for panic: + // Runtime values for line, and timer are only created + // from generic constants SyncKind::SyncLine(line) => match line { 0 => SyncSelection::SyncLine0, 1 => SyncSelection::SyncLine1, 2 => SyncSelection::SyncLine2, - _ => unreachable!(), + _ => panic!("Invalid sync line"), }, SyncKind::TimerSyncOut(timer) => match timer { 0 => SyncSelection::Timer0SyncOut, 1 => SyncSelection::Timer1SyncOut, 2 => SyncSelection::Timer2SyncOut, - _ => unreachable!(), + _ => panic!("Invalid timer for sync out"), }, } } diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 999d821facc..531fee672bf 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -6,31 +6,46 @@ use core::marker::PhantomData; +use enumset::{EnumSet, EnumSetType}; + use super::PeripheralGuard; use crate::{ mcpwm::{ FrequencyError, + Instance, PeripheralClockConfig, PwmClockGuard, - PwmPeripheral, sync::{SyncOut, SyncSelection, SyncSource}, }, pac, time::Rate, }; +#[derive(Debug, EnumSetType)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +#[instability::unstable] +pub enum TimerEvent { + /// Event for when a timer stops + TimerStop, + /// Event for when a timer equals zero + TimerEqualZero, + /// Event for when a timer equals period + TimerEqualPeriod, +} + /// A MCPWM timer /// /// Every timer of a particular [`MCPWM`](super::McPwm) peripheral can be used /// as a timing reference for every /// [`Operator`](super::operator::Operator) of that peripheral -pub struct Timer<'d, const TIM: u8, PWM> { +pub struct Timer<'d, const TIM: u8, PWM: Instance> { pub(super) phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } -impl<'d, const TIM: u8, PWM: PwmPeripheral> Timer<'d, TIM, PWM> { +impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { Timer { phantom: PhantomData, @@ -86,9 +101,9 @@ impl<'d, const TIM: u8, PWM: PwmPeripheral> Timer<'d, TIM, PWM> { /// Then trigger a software sync event. /// /// Note: This triggers a sync out event. If a timer is listening - /// to this timers sync out source a sync event will be triggered. - /// Refer to how sync events are handled for [`super::CaptureTimer`] or [`Timer`] - /// in the their respective documentation. + /// to this timers sync out. Then a sync event will be propagated. + /// Refer to how sync events are handled for [`super::CaptureTimer`] + /// or [`Timer`] in the their respective documentation. pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { self.set_sync_phase(phase); self.set_sync_counter_direction(direction); @@ -99,7 +114,7 @@ impl<'d, const TIM: u8, PWM: PwmPeripheral> Timer<'d, TIM, PWM> { pub fn set_sync_phase(&mut self, phase: u16) { // SAFETY: // We only write to our TIMERx_SYNC register - let tmr = unsafe { Self::tmr() }; + let tmr = Self::tmr(); tmr.sync().modify(|_r, w| unsafe { w.phase().bits(phase) }); } @@ -109,18 +124,18 @@ impl<'d, const TIM: u8, PWM: PwmPeripheral> Timer<'d, TIM, PWM> { pub fn set_sync_counter_direction(&mut self, direction: CounterDirection) { // SAFETY: // We only write to our TIMERx_SYNC register - let tmr = unsafe { Self::tmr() }; + let tmr = Self::tmr(); tmr.sync() .modify(|_r, w| w.phase_direction().bit(direction as u8 != 0)); } /// Trigger a software sync event - /// Note: This always triggers a sync out event even if the - /// sync out select is set to when + /// Note: This always triggers a sync out event from + /// its [`Timer::get_sync_out`] source. pub fn trigger_sync(&mut self) { // SAFETY: // We only write to our TIMERx_SYNC register - let tmr = unsafe { Self::tmr() }; + let tmr = Self::tmr(); tmr.sync().modify(|r, w| w.sw().bit(!r.sw().bit())); } @@ -128,15 +143,15 @@ impl<'d, const TIM: u8, PWM: PwmPeripheral> Timer<'d, TIM, PWM> { pub fn status(&self) -> (u16, CounterDirection) { // SAFETY: // We only read from our TIMERx_STATUS register - let reg = unsafe { Self::tmr() }.status().read(); + let reg = Self::tmr().status().read(); (reg.value().bits(), reg.direction().bit_is_set().into()) } - /// Selects the how the timer fires sync events + /// Selects the how the timer fires sync out events pub fn set_sync_out_selection(&mut self, sync_out: SyncOutSelection) { // SAFETY: // We only modify our TIMERx_SYNC register - let timer = unsafe { Self::tmr() }; + let timer = Self::tmr(); // Disable sync input on our timer timer .sync() @@ -144,22 +159,23 @@ impl<'d, const TIM: u8, PWM: PwmPeripheral> Timer<'d, TIM, PWM> { } /// Returns the timers sync_out source - pub fn get_sync_out(&self) -> SyncOut<'d> { - SyncOut::new::() + pub fn get_sync_out(&self) -> SyncOut<'d, TIM, PWM> { + SyncOut::new() } /// Sets the timer sync in source - pub fn set_sync_in(&mut self, sync: impl SyncSource) { + pub fn set_sync_in(&mut self, sync: impl SyncSource) { // SAFETY: // We only modify the PWM TIMER_SYNCI_CFG register - let pwm = unsafe { &*PWM::block() }; + let block = PWM::info().regs(); + // SAFETY: // We only modify our TIMERx_SYNC register - let timer = unsafe { Self::tmr() }; + let timer = Self::tmr(); // Update sync select first let sync_select: SyncSelection = sync.get_kind().into(); - pwm.timer_synci_cfg().modify(|_r, w| { + block.timer_synci_cfg().modify(|_r, w| { unsafe { w.timer_syncisel(TIM).bits(sync_select as u8) // Update timer input sync selection } @@ -173,25 +189,85 @@ impl<'d, const TIM: u8, PWM: PwmPeripheral> Timer<'d, TIM, PWM> { pub fn clear_sync_in(&mut self) { // SAFETY: // We only modify our TIMERx_SYNC register - let timer = unsafe { Self::tmr() }; + let timer = Self::tmr(); // Disable sync input on our timer timer.sync().modify(|_r, w| w.synci_en().clear_bit()); } + #[instability::unstable] + pub fn listen(&mut self, events: EnumSet) { + self.enable_interrupts(events, true); + } + + #[instability::unstable] + pub fn unlisten(&mut self, events: EnumSet) { + self.enable_interrupts(events, false); + } + + #[instability::unstable] + pub fn interrupts(&self) -> EnumSet { + let mut res = EnumSet::new(); + let reg_block = PWM::info().regs(); + + let ints = reg_block.int_st().read(); + if ints.timer_stop(TIM).bit() { + res.insert(TimerEvent::TimerStop); + } + if ints.timer_tep(TIM).bit() { + res.insert(TimerEvent::TimerEqualPeriod); + } + if ints.timer_tez(TIM).bit() { + res.insert(TimerEvent::TimerEqualZero); + } + + res + } + + #[instability::unstable] + pub fn clear_interrupts(&mut self, events: EnumSet) { + let reg_block = PWM::info().regs(); + + reg_block.int_clr().write(|w| { + for event in events { + match event { + TimerEvent::TimerStop => w.timer_stop(TIM).variant(true), + TimerEvent::TimerEqualPeriod => w.timer_tep(TIM).variant(true), + TimerEvent::TimerEqualZero => w.timer_tez(TIM).variant(true), + }; + } + w + }); + } + + fn enable_interrupts(&mut self, events: EnumSet, value: bool) { + let reg_block = PWM::info().regs(); + + reg_block.int_ena().modify(|_, w| { + for event in events { + match event { + TimerEvent::TimerStop => w.timer_stop(TIM).variant(value), + TimerEvent::TimerEqualPeriod => w.timer_tep(TIM).variant(value), + TimerEvent::TimerEqualZero => w.timer_tez(TIM).variant(value), + }; + } + w + }); + } + fn cfg0(&mut self) -> &pac::mcpwm0::timer::CFG0 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self - unsafe { Self::tmr() }.cfg0() + Self::tmr().cfg0() } fn cfg1(&mut self) -> &pac::mcpwm0::timer::CFG1 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self - unsafe { Self::tmr() }.cfg1() + Self::tmr().cfg1() } - unsafe fn tmr() -> &'static pac::mcpwm0::TIMER { - let block = unsafe { &*PWM::block() }; + fn tmr() -> &'static pac::mcpwm0::TIMER { + let block = PWM::info().regs(); block.timer(TIM as usize) } } From ddd7bb25cdf3945005140433bab1a1b5fdd32e02 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Wed, 1 Apr 2026 22:17:02 -0600 Subject: [PATCH 11/37] More changes --- esp-hal/src/mcpwm/capture.rs | 264 +++++-------- esp-hal/src/mcpwm/mod.rs | 461 ++++++++++++++-------- esp-hal/src/mcpwm/operator.rs | 30 +- esp-hal/src/mcpwm/sync.rs | 19 +- esp-hal/src/mcpwm/timer.rs | 105 ++--- esp-metadata/devices/esp32c5.toml | 488 ++++++++++++----------- esp-metadata/devices/esp32c6.toml | 620 ++++++++++++++++-------------- esp-metadata/devices/esp32h2.toml | 509 ++++++++++++------------ 8 files changed, 1363 insertions(+), 1133 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 185d17bd793..a82340d4b69 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -4,42 +4,39 @@ cfg(esp32h2) => "32" }, "clock_src" => { - cfg(esp32) => "PLL_F160M (160 MHz)", - cfg(esp32s3) => "CRYPTO_PWM_CLK (160 MHz)", - cfg(esp32c6) => "PLL_F160M (160 MHz)", - cfg(esp32h2) => "PLL_F96M_CLK (96 MHz)", + cfg(esp32) => "ADB-CLK (80 MHz)", + cfg(esp32s3) => "ADB-CLK (80 MHz)", + cfg(esp32c6) => "ADB-CLK (80 MHz)", + cfg(esp32h2) => "ADB-CLK (80 MHz)", } ))] //! # MCPWM Capture Module //! //! ## Overview -//! The `Capture` is resposible for managing the recording of the +//! The `Capture` is responsible for managing the recording of the //! capture timer during specific software or hardware triggered //! 'capture' events. //! -//! Capture events can be triggered in 2 ways: -//! During a falling and/or Rising edge of a preconfigured GPIO pin. -//! Software triggered captures though the CaptureChannel::trigger() function. +//! ### Capture events can be triggered in 2 ways: +//! 1. During a falling and/or Rising edge of a preconfigured GPIO pin. +//! 2. Software triggered captures though [`CaptureChannel::trigger_capture`]. //! -//! ## Configuration -//! This module provides the flexiability of configuring any GPIO pin as an input +//! ### Configuration +//! This module provides the flexibility of configuring any GPIO pin as an input //! for capturing the rising and/or falling edge of a signal. This module allows //! for the ability to trigger software captures. //! -//! ### Capture Timer -//! Capture timer can be configured to sync with a PWM timer during specific events -//! either when the PWM timer sync out event, or a sync in from an external GPIO pin. -//! Note: Capture timer has a default source of __clock_src__ -//! //! ## Example //! //! This example shows configuring MCPWM for receiving //! rising and falling edges from a GPIO pin. //! -//! TODO Write code for this +//! TODO Write code example for this use core::marker::PhantomData; -use super::PeripheralGuard; +use enumset::EnumSet; + +use super::{Event, PeripheralGuard}; pub use crate::pac::mcpwm0::{ cap_ch_cfg::CAP0_MODE as CaptureMode, cap_status::CAP0_EDGE as CaptureEdge, @@ -51,20 +48,20 @@ use crate::{ PwmClockGuard, sync::{SyncSelection, SyncSource}, }, + pac, }; /// The MCPWM Capture Timer /// /// ## Overview -/// - This timer is shared by all instances of [`CaptureChannel`] for a MCPWM. -/// During capture events on any of the channels the time stored in this timer will be -/// loaded into the [`CaptureEvent`]'s time. -/// - A sync source can be set by calling [`CaptureTimer::set_sync_in`] with a sync source. -/// - A sync source can be removed by calling [`CaptureTimer::clear_sync_in`]. +/// This timer is used for all [`CaptureChannel`]'s for a given MCPWM instance. +/// * This timer can be configured with a sync source by calling [`CaptureTimer::set_sync`], and +/// cleared by calling [`CaptureTimer::clear_sync_in`]. /// -/// When this timer receives a capture event the counter of the timer is reset. +/// ### Sync Events +/// When this timer receives a sync event the counter of the timer is reset. /// The value that the timer is set to is dependent on [`CaptureTimer::set_sync_phase`] -/// This timer always counts up towards a the positive direction +/// This timer always counts up towards a the positive direction. pub struct CaptureTimer<'d, PWM: Instance> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, @@ -82,30 +79,18 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { /// Start the capture timer counting at APB_CLK pub fn start(&mut self) { - // SAFETY: - // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = PWM::info().regs(); - - block - .cap_timer_cfg() - .modify(|_r, w| w.cap_timer_en().set_bit()); + self.set_enable(true); } /// Pauses the capture timer pub fn pause(&mut self) { - // SAFETY: - // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = PWM::info().regs(); - - block - .cap_timer_cfg() - .modify(|_r, w| w.cap_timer_en().clear_bit()); + self.set_enable(false); } /// Stops the timer and resets the timers counter to 0 - /// Warning: This sets the timers sync phase to 0 + /// **Warning**: This sets the timers sync phase to 0 pub fn reset(&mut self) { - self.pause(); + self.set_enable(false); self.set_sync_phase(0); self.trigger_sync(); } @@ -114,70 +99,59 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { pub fn set_sync_phase(&mut self, phase: u32) { // SAFETY: // We write to our MCPWM_CAP_TIMER_PHASE register - let block = PWM::info().regs(); - - block - .cap_timer_phase() - .write(|w| unsafe { w.cap_phase().bits(phase) }); + Self::phase().write(|w| unsafe { w.cap_phase().bits(phase) }); } /// Get the sync phase pub fn get_sync_phase(&mut self) -> u32 { - // SAFETY: - // We read from our MCPWM_CAP_TIMER_PHASE register - let block = PWM::info().regs(); - - block.cap_timer_phase().read().cap_phase().bits() + Self::phase().read().cap_phase().bits() } /// Clears the captures timer sync source - pub fn clear_sync_in(&mut self) { - // SAFETY: - // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = PWM::info().regs(); - - unsafe { - block.cap_timer_cfg().modify(|_r, w| { - w.cap_synci_en().clear_bit(); // Disable sync inputs - w.cap_synci_sel().bits(SyncSelection::None as u8) // No sync input - }) - }; + pub fn clear_sync(&mut self) { + self.set_sync_enable(SyncSelection::None, false); } /// ## Overview /// Sets the capture timers sync source. Refer to how sync events are /// handled in the [`CaptureTimer`] documentation. - pub fn set_sync_in(&mut self, sync_source: impl SyncSource) { - // SAFETY: - // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = PWM::info().regs(); - + pub fn set_sync(&mut self, sync_source: &impl SyncSource) { let sync_kind = sync_source.get_kind(); - let sync_selection: SyncSelection = sync_kind.into(); - unsafe { - block.cap_timer_cfg().modify(|_r, w| { - w.cap_synci_en().set_bit(); // Enable sync input - w.cap_synci_sel().bits(sync_selection as u8) // Set the sync selection - }) - }; + self.set_sync_enable(sync_kind.into(), false); } /// ## Overview /// This triggers a software sync event on the capture timer /// Refer to how sync events are handled in the [`CaptureTimer`] documentation. pub fn trigger_sync(&mut self) { - // SAFETY: - // We modify our MCPWM_CAP_TIMER_CFG_REG register - let block = PWM::info().regs(); + Self::cfg().modify(|_r, w| w.cap_sync_sw().set_bit()); + } + + fn set_enable(&mut self, enable: bool) { + Self::cfg().modify(|_r, w| w.cap_timer_en().bit(enable)); + } + + fn set_sync_enable(&mut self, selection: SyncSelection, enable: bool) { + unsafe { + Self::cfg().modify(|_r, w| { + w.cap_synci_en().bit(enable); // Disable sync inputs + w.cap_synci_sel().bits(selection as u8) // No sync input + }) + }; + } + + fn cfg() -> &'static crate::Reg { + let (info, _) = PWM::split(); + info.regs().cap_timer_cfg() + } - // Trigger a software sync - block - .cap_timer_cfg() - .modify(|_r, w| w.cap_sync_sw().set_bit()); + fn phase() -> &'static crate::Reg { + let (info, _) = PWM::split(); + info.regs().cap_timer_phase() } } -/// Repersents the capture event +/// Represents the capture event /// Contains the capture time and the captured edge pub struct CaptureEvent { time: u32, @@ -196,32 +170,7 @@ impl CaptureEvent { } } -/// Configuration for a capture channel -/// -/// ## Overview -/// -/// Capture channel can be configured with a signal input, -/// a invert signal boolean, a capture mode, and a prescaler. -/// -/// The signal input is what the capture channel listens too for -/// rising and or falling edge events, which is configured in capture mode. -/// -/// The invert describes if the input signal is inverted before -/// being sent to the capture channel. If your signal originally had -/// rising edges they are replaced with falling edges and vise versa. -/// Invert signal is useful if the polarity of your signal matters for your code. -/// -/// The prescaler determines how often a capture event is generated -/// from incoming edges. Instead of capturing every valid edge, -/// the hardware will generate a capture event once every `prescale` -/// edges. -/// Note: passing in a value of prescaler = 0 will set a prescaler value of 1. -/// -/// Prescaler rather then scaling the clock speed, can be thought of as a 'capture rate.' -/// The edges counted are those selected by the channel's edge configuration. -/// (rising, falling, or both). For example: -/// - If configured for rising edges only, captures occur every Nth rising edge -/// - If configured for both edges, captures occur every Nth edge (rising + falling combined) +/// Configuration for capture channel #[derive(Debug, PartialEq, Eq, Clone, Copy)] // Hash cannot be implemented for CaptureMode pub struct CaptureChannelConfig { @@ -276,14 +225,7 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannelCreator<'d, CHAN, PWM> { /// Configure a new capture channel from a config pub fn configure(self, config: CaptureChannelConfig) -> CaptureChannel<'d, CHAN, PWM> { - let mut new_channel = CaptureChannel { - phantom: PhantomData, - _guard: self._guard, - _pwm_clock_guard: PwmClockGuard::new::(), - }; - new_channel.configure(config); - - new_channel + CaptureChannel::new(self._guard, config) } } @@ -292,7 +234,7 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannelCreator<'d, CHAN, PWM> { /// The MCPWM Capture Channel has the following functions: /// * Enable/Disable capturing on this channel /// * Setting the capture input GPIO pin -/// * Weather to trigger capture events on rising and/or falling edges +/// * Whether to trigger capture events on rising and/or falling edges /// * Read the last capture edge, and the last capture time pub struct CaptureChannel<'d, const CHAN: u8, PWM: Instance> { phantom: PhantomData<&'d PWM>, @@ -301,25 +243,30 @@ pub struct CaptureChannel<'d, const CHAN: u8, PWM: Instance> { } impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { - pub(super) fn configure(&mut self, config: CaptureChannelConfig) { - // SAFETY: - // We only write to our MCPWM_CAP_CHx_CFG_REG register - let block = PWM::info().regs(); + pub(super) fn new(guard: PeripheralGuard, config: CaptureChannelConfig) -> Self { + let mut channel = Self { + phantom: PhantomData, + _guard: guard, + _pwm_clock_guard: PwmClockGuard::new::(), + }; + channel.configure(config); + channel + } - let enabled = block.cap_ch_cfg(CHAN as usize).read().en().bit(); - block.cap_ch_cfg(CHAN as usize).write(|w| { + pub(super) fn configure(&mut self, config: CaptureChannelConfig) { + Self::cfg().modify(|_, w| { w.mode().variant(config.capture_mode); w.in_invert().variant(config.invert); unsafe { w.prescale().bits(config.prescaler); } - w.en().variant(enabled) }); } /// Assign the input signal for the capture pub fn with_signal_input<'a>(self, input: impl PeripheralInput<'a>) -> Self { - let input_signal = PWM::info().capture_input_signal::(); + let (info, _) = PWM::split(); + let input_signal = info.capture_input_signal::(); if input_signal as usize <= property!("gpio.input_signal_max") { let source = input.into(); @@ -334,12 +281,7 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// Enable or disables this capture channel pub fn set_enable(&mut self, enable: bool) { - // SAFETY: - // We only write to our MCPWM_CAP_CHx_CFG_REG register - let block = PWM::info().regs(); - block - .cap_ch_cfg(CHAN as usize) - .modify(|_, w| w.en().variant(enable)); + Self::cfg().modify(|_, w| w.en().variant(enable)); } /// Set the config @@ -347,63 +289,51 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { self.configure(config); } + /// Triggers a software capture on the current capture channel + pub fn trigger_capture(&mut self) { + Self::cfg().modify(|_, w| w.sw().set_bit()); + } + /// Sets the capture channel to listen to captures on specific edge events /// This channel can listen to Falling, and/or Rising edges on any of the GPIO pins. #[instability::unstable] - pub fn listen(&mut self, capture_mode: CaptureMode) { - // SAFETY: - // We write to our MCPWM_CAP_CHx_CFG_REG register - // We are modifying a shared peripheral interrupt enable register - let block = PWM::info().regs(); - block - .cap_ch_cfg(CHAN as usize) - .write(|w| w.mode().variant(capture_mode)); - - // Enable the capture interrupt - block.int_ena().modify(|_, w| w.cap(CHAN).set_bit()); + pub fn listen(&mut self) { + let (info, state) = PWM::split(); + state.enable_listen::(info, EnumSet::only(Event::Capture), true); } /// Stops listening to events on this channel #[instability::unstable] pub fn unlisten(&mut self) { - // SAFTEY: - // We are writing to a SHARED peripheral interrupt enable register - // Tldr lowk don't know if I should use a mutex or not?? - let block = PWM::info().regs(); - - // We can unlisten from events simply by disabling the interrupt - block.int_ena().modify(|_, w| w.cap(CHAN).clear_bit()); + let (info, state) = PWM::split(); + state.enable_listen::(info, EnumSet::only(Event::Capture), false); } /// If the interrupt was set for this channel #[instability::unstable] - pub fn is_interupt_set(&mut self) -> bool { - // SAFTEY: - // We only read from our MCPWM_INT_ST_REG register - let block = PWM::info().regs(); - - block.int_st().read().cap(CHAN).bit() + pub fn is_interrupt_set(&self) -> bool { + let (info, state) = PWM::split(); + state.interrupt_set::(info, Event::Capture) } /// Clear the interrupt #[instability::unstable] - pub fn clear_interrupt(&mut self) { - // SAFTEY: - // We only read from our MCPWM_INT_CLR_REG register - let block = PWM::info().regs(); - - block.int_clr().write(|w| w.cap(CHAN).bit(true)); + pub fn clear_interrupt(&self) { + let (info, state) = PWM::split(); + state.clear_interrupt::(info, Event::Capture); } /// Gets the last captured event #[instability::unstable] - pub fn get_event(&mut self) -> CaptureEvent { - // SAFTEY: - // We only read from our MCPWM_INT_ST_REG & MCPWM_CAP_STATUS_REG register - let block = PWM::info().regs(); - - let time = block.cap_ch(CHAN as usize).read().value().bits(); - let edge = block.cap_status().read().cap_edge(CHAN).variant(); + pub fn get_event(&self) -> CaptureEvent { + let (info, _) = PWM::split(); + let time = info.regs().cap_ch(CHAN as usize).read().value().bits(); + let edge = info.regs().cap_status().read().cap_edge(CHAN).variant(); CaptureEvent { time, edge } } + + fn cfg() -> &'static crate::Reg { + let (info, _) = PWM::split(); + info.regs().cap_ch_cfg(CHAN as usize) + } } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index 84297803c22..8cbecc73550 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -8,7 +8,7 @@ cfg(esp32s3) => "CRYPTO_PWM_CLK (160 MHz)", cfg(esp32c6) => "PLL_F160M (160 MHz)", cfg(esp32h2) => "PLL_F96M_CLK (96 MHz)", - } + }, ))] //! # Motor Control Pulse Width Modulator (MCPWM) //! @@ -31,7 +31,12 @@ //! * The 16-bit counter in the PWM timer can work in count-up mode, count-down mode or //! count-up-down mode. //! * A hardware sync or software sync can trigger a reload on the PWM timer with a phase -//! register (Not yet implemented) +//! register. +//! * Timers run until a perconfigured [`timer::StopCondition`], this enum also specifies +//! running continuously. +//! * Timers can generate [`timer::TimerEvent`] during specific conditions. +//! * Timers [`sync::SyncOut`] can be configured to fire at specific conditions configured by +//! [`timer::SyncOutSelect`] //! * PWM Operators 0, 1 and 2 //! * Every PWM operator has two PWM outputs: PWMxA and PWMxB. They can work independently, in //! symmetric and asymmetric configuration. @@ -43,10 +48,32 @@ //! insulated with a transformer. (Not yet implemented) //! * Period, time stamps and important control registers have shadow registers with flexible //! updating methods. +//! * Capture Channels 0, 1 and 2 +//! * Every capture channel has one signal input. With an optional invert filter +//! * Each capture module can be configured to detect rising and (or), falling edges on an +//! external signal. +//! * Each capture channel can trigger software capture event recoding the capture counter. The +//! edge that is captured is UNSPECIFIED for software captures. +//! * Each capture channel can be configured with a 8-bit pre-scaler. Which only triggers +//! capture events every Nth edge captured. ( Useful for high frequencies ) +//! * Capture Timer: +//! * Capture timer can be configured with a sync in source. +//! * A hardware sync or software sync can trigger a reload on the capture timer with the set +//! phase. +#![cfg_attr( + soc_has_mcpwm_capture_clk_from_group, + doc = " * Capture timer's clock source is the same as the PWM timers clock source" +)] +#![cfg_attr( + not(soc_has_mcpwm_capture_clk_from_group), + doc = " * Capture timer's has it's own independent clock source from the MCPWM peripheral." +)] //! * Fault Detection Module (Not yet implemented) -//! * Capture Module (Not yet implemented) -//! -//! Clock source is __clock_src__ by default. +#![cfg_attr( + not(soc_has_mcpwm_capture_clk_from_group), + doc = "\nCapture clock source is `ADB-CLK (80 MHz)` by default.\n" +)] +//! Clock source is `__clock_src__`` by default. //! //! ## Examples //! @@ -84,19 +111,21 @@ //! # {after_snippet} //! ``` -use core::marker::PhantomData; +use core::{cell::Cell, marker::PhantomData}; -use operator::Operator; -use timer::Timer; +use critical_section::Mutex; +use enumset::{EnumSet, EnumSetType}; #[cfg(soc_has_mcpwm0)] +use crate::mcpwm::{ + capture::{CaptureChannelCreator, CaptureTimer}, + operator::Operator, + sync::SyncLine, + timer::Timer, +}; use crate::{ gpio::{InputSignal, OutputSignal}, interrupt::{self, InterruptHandler}, - mcpwm::{ - capture::{CaptureChannelCreator, CaptureTimer}, - sync::SyncLine, - }, pac, private::OnDrop, soc::clocks::{self, ClockTree}, @@ -113,149 +142,6 @@ pub mod sync; /// MCPWM timers pub mod timer; -type RegisterBlock = pac::mcpwm0::RegisterBlock; - -/// Repersents info for MCPWM peripheral -#[doc(hidden)] -#[derive(Debug)] -#[non_exhaustive] -#[allow(private_interfaces, reason = "Unstable details")] -pub struct Info { - /// Register block - register_block: *const RegisterBlock, - /// System peripheral marker. - _peripheral: crate::system::Peripheral, - /// Interrupt marker - _interrupt: crate::peripherals::Interrupt, - /// Sync inputs - sync_input: [InputSignal; 3], - /// Capture inputs - capture_input: [InputSignal; 3], - /// Operator A outputs - operator_a_output: [OutputSignal; 3], - /// Operator B outputs - operator_b_output: [OutputSignal; 3], -} - -impl Info { - /// Returns the register block for this PWM instance. - pub fn regs(&self) -> &RegisterBlock { - unsafe { &*self.register_block } - } - - pub fn peripheral(&self) -> crate::system::Peripheral { - self._peripheral - } - - pub fn interrupt(&self) -> crate::peripherals::Interrupt { - self._interrupt - } - - pub fn operator_output_signal(&self) -> OutputSignal { - match IS_A { - true => self.operator_a_output[OP as usize], - false => self.operator_b_output[OP as usize], - } - } - - pub fn sync_input_signal(&self) -> InputSignal { - self.sync_input[SYNC as usize] - } - - pub fn capture_input_signal(&self) -> InputSignal { - self.capture_input[CHAN as usize] - } -} - -impl PartialEq for Info { - fn eq(&self, other: &Self) -> bool { - core::ptr::eq(self.register_block, other.register_block) - } -} - -unsafe impl Sync for Info {} - -/// Repersents a MCPWM peripheral -pub trait Instance { - /// Repersents the ID - const ID: u8 = 0; - - #[doc(hidden)] - /// Returns the peripheral data. - fn info() -> &'static Info; -} - -#[cfg(soc_has_mcpwm0)] -impl Instance for crate::peripherals::MCPWM0<'_> { - const ID: u8 = 0; - - /// Returns peripheral data for MCPWM 0 - fn info() -> &'static Info { - static INFO: Info = Info { - register_block: crate::peripherals::MCPWM0::regs(), - _peripheral: crate::system::Peripheral::Mcpwm0, - _interrupt: crate::peripherals::Interrupt::MCPWM0, - sync_input: [ - InputSignal::PWM0_SYNC0, - InputSignal::PWM0_SYNC1, - InputSignal::PWM0_SYNC2, - ], - capture_input: [ - InputSignal::PWM0_CAP0, - InputSignal::PWM0_CAP1, - InputSignal::PWM0_CAP2, - ], - operator_a_output: [ - OutputSignal::PWM0_0A, - OutputSignal::PWM0_1A, - OutputSignal::PWM0_2A, - ], - operator_b_output: [ - OutputSignal::PWM0_0B, - OutputSignal::PWM0_1B, - OutputSignal::PWM0_2B, - ], - }; - - &INFO - } -} - -#[cfg(soc_has_mcpwm1)] -impl Instance for crate::peripherals::MCPWM1<'_> { - const ID: u8 = 1; - - fn info() -> &'static Info { - static INFO: Info = Info { - register_block: crate::peripherals::MCPWM1::regs(), - _peripheral: crate::system::Peripheral::Mcpwm1, - _interrupt: crate::peripherals::Interrupt::MCPWM1, - sync_input: [ - InputSignal::PWM1_SYNC0, - InputSignal::PWM1_SYNC1, - InputSignal::PWM1_SYNC2, - ], - capture_input: [ - InputSignal::PWM1_CAP0, - InputSignal::PWM1_CAP1, - InputSignal::PWM1_CAP2, - ], - operator_a_output: [ - OutputSignal::PWM1_0A, - OutputSignal::PWM1_1A, - OutputSignal::PWM1_2A, - ], - operator_b_output: [ - OutputSignal::PWM1_0B, - OutputSignal::PWM1_1B, - OutputSignal::PWM1_2B, - ], - }; - - &INFO - } -} - /// The MCPWM peripheral #[non_exhaustive] pub struct McPwm<'d, PWM: Instance> { @@ -295,16 +181,16 @@ pub struct McPwm<'d, PWM: Instance> { impl<'d, PWM: Instance> McPwm<'d, PWM> { /// `pwm_clk = clocks.crypto_pwm_clock / (prescaler + 1)` pub fn new(_peripheral: PWM, peripheral_clock: PeripheralClockConfig) -> Self { - let guard = PeripheralGuard::new(PWM::info().peripheral()); - let register_block = PWM::info().regs(); + let (info, _) = PWM::split(); + let guard = PeripheralGuard::new(info.peripheral()); // set prescaler for timer (0-2) - register_block + info.regs() .clk_cfg() .write(|w| unsafe { w.clk_prescale().bits(peripheral_clock.prescaler) }); // enable clock - register_block.clk().write(|w| w.en().set_bit()); + info.regs().clk().write(|w| w.en().set_bit()); Self { _phantom: PhantomData, @@ -330,7 +216,8 @@ impl<'d, PWM: Instance> McPwm<'d, PWM> { /// handlers. #[instability::unstable] pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { - let interrupt = PWM::info().interrupt(); + let (info, _) = PWM::split(); + let interrupt = info.interrupt(); for core in crate::system::Cpu::other() { crate::interrupt::disable(core, interrupt); @@ -451,12 +338,264 @@ impl PeripheralClockConfig { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FrequencyError; +type RegisterBlock = pac::mcpwm0::RegisterBlock; + +/// Peripheral info for an MCPWM instance. +#[doc(hidden)] +#[derive(Debug)] +#[non_exhaustive] +#[allow(private_interfaces, reason = "Unstable details")] +pub struct Info { + /// Register block + register_block: *const RegisterBlock, + /// System peripheral marker. + _peripheral: crate::system::Peripheral, + /// Interrupt marker + _interrupt: crate::peripherals::Interrupt, + /// Sync inputs + sync_input: [InputSignal; 3], + /// Capture inputs + capture_input: [InputSignal; 3], + /// Operator A outputs + operator_a_output: [OutputSignal; 3], + /// Operator B outputs + operator_b_output: [OutputSignal; 3], +} + +/// Peripheral state for an MCPWM instance. +#[doc(hidden)] +#[derive(Debug)] +#[non_exhaustive] +pub struct State { + int_ena: Mutex>, +} + +unsafe impl Sync for State {} +impl State { + /// Return if the interrupt for an event is set + pub fn interrupt_set(&self, info: &Info, event: Event) -> bool { + let regs = info.regs(); + let int_st = regs.int_st().read(); + match event { + Event::TimerStop => int_st.timer_stop(UNIT).bit(), + Event::TimerEqualPeriod => int_st.timer_tep(UNIT).bit(), + Event::TimerEqualZero => int_st.timer_tez(UNIT).bit(), + Event::Capture => int_st.cap(UNIT).bit(), + Event::CompareA => int_st.cmpr_tea(UNIT).bit(), + Event::CompareB => int_st.cmpr_teb(UNIT).bit(), + Event::Fault => int_st.fault(UNIT).bit(), + Event::FaultClear => int_st.fault_clr(UNIT).bit(), + Event::FaultCycleByCycle => int_st.tz_cbc(UNIT).bit(), + Event::FaultOneShotMode => int_st.tz_ost(UNIT).bit(), + } + } + + /// Clear the interrupt for an event on a specific UNIT # + pub fn clear_interrupt(&self, info: &Info, event: Event) { + let regs = info.regs(); + regs.int_clr().write(|w| match event { + Event::TimerStop => w.timer_stop(UNIT).bit(true), + Event::TimerEqualPeriod => w.timer_tep(UNIT).bit(true), + Event::TimerEqualZero => w.timer_tez(UNIT).bit(true), + Event::Capture => w.cap(UNIT).bit(true), + Event::CompareA => w.cmpr_tea(UNIT).bit(true), + Event::CompareB => w.cmpr_teb(UNIT).bit(true), + Event::Fault => w.fault(UNIT).bit(true), + Event::FaultClear => w.fault_clr(UNIT).bit(true), + Event::FaultCycleByCycle => w.tz_cbc(UNIT).bit(true), + Event::FaultOneShotMode => w.tz_ost(UNIT).bit(true), + }); + } + + /// Enables listening for an event on a specific UNIT # + pub fn enable_listen(&self, info: &Info, events: EnumSet, value: bool) { + critical_section::with(|cs| { + let int_ena = self.int_ena.borrow(cs); + let regs = info.regs(); + + int_ena.set(regs.int_ena().write(|w| { + unsafe { w.bits(int_ena.take()) }; + + for event in events { + match event { + Event::TimerStop => w.timer_stop(UNIT).bit(value), + Event::TimerEqualPeriod => w.timer_tep(UNIT).bit(value), + Event::TimerEqualZero => w.timer_tez(UNIT).bit(value), + Event::Capture => w.cap(UNIT).bit(value), + Event::CompareA => w.cmpr_tea(UNIT).bit(value), + Event::CompareB => w.cmpr_teb(UNIT).bit(value), + Event::Fault => w.fault(UNIT).bit(value), + Event::FaultClear => w.fault_clr(UNIT).bit(value), + Event::FaultCycleByCycle => w.tz_cbc(UNIT).bit(value), + Event::FaultOneShotMode => w.tz_ost(UNIT).bit(value), + }; + } + + w + })); + }); + } +} + +/// Event types for MCPWM +#[derive(Debug, EnumSetType)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[doc(hidden)] +pub enum Event { + /// Event for when a timer stops + TimerStop, + /// Event for when a timer equals zero + TimerEqualZero, + /// Event for when a timer equals period + TimerEqualPeriod, + /// Event for a fault + Fault, + /// Event for a fault clear + FaultClear, + /// Event for a compare A + CompareA, + /// Event for a compare B + CompareB, + /// Event for a fault cycle by cycle + FaultCycleByCycle, + /// Event for a fault one shot mode + FaultOneShotMode, + /// Event for a capture + Capture, +} + +impl Info { + /// Returns the register block for this PWM instance. + pub fn regs(&self) -> &RegisterBlock { + unsafe { &*self.register_block } + } + + /// Returns the periperal + pub fn peripheral(&self) -> crate::system::Peripheral { + self._peripheral + } + + /// Returns the interrupt marker + pub fn interrupt(&self) -> crate::peripherals::Interrupt { + self._interrupt + } + + /// Returns the output signal for operators + pub fn operator_output_signal(&self) -> OutputSignal { + match IS_A { + true => self.operator_a_output[OP as usize], + false => self.operator_b_output[OP as usize], + } + } + + /// Returns the sync input signal + pub fn sync_input_signal(&self) -> InputSignal { + self.sync_input[SYNC as usize] + } + + /// Returns the capture input signal + pub fn capture_input_signal(&self) -> InputSignal { + self.capture_input[CHAN as usize] + } +} + +impl PartialEq for Info { + fn eq(&self, other: &Self) -> bool { + core::ptr::eq(self.register_block, other.register_block) + } +} + +unsafe impl Sync for Info {} + +/// Represents a MCPWM peripheral +pub trait Instance: crate::private::Sealed { + #[doc(hidden)] + /// Returns the peripheral data and state. + fn split() -> (&'static Info, &'static State); +} + +#[cfg(soc_has_mcpwm0)] +impl Instance for crate::peripherals::MCPWM0<'_> { + /// Returns peripheral data for MCPWM 0 + fn split() -> (&'static Info, &'static State) { + static INFO: Info = Info { + register_block: crate::peripherals::MCPWM0::regs(), + _peripheral: crate::system::Peripheral::Mcpwm0, + _interrupt: crate::peripherals::Interrupt::MCPWM0, + sync_input: [ + InputSignal::PWM0_SYNC0, + InputSignal::PWM0_SYNC1, + InputSignal::PWM0_SYNC2, + ], + capture_input: [ + InputSignal::PWM0_CAP0, + InputSignal::PWM0_CAP1, + InputSignal::PWM0_CAP2, + ], + operator_a_output: [ + OutputSignal::PWM0_0A, + OutputSignal::PWM0_1A, + OutputSignal::PWM0_2A, + ], + operator_b_output: [ + OutputSignal::PWM0_0B, + OutputSignal::PWM0_1B, + OutputSignal::PWM0_2B, + ], + }; + + static STATE: State = State { + int_ena: Mutex::new(Cell::new(0)), + }; + + (&INFO, &STATE) + } +} + +#[cfg(soc_has_mcpwm1)] +impl Instance for crate::peripherals::MCPWM1<'_> { + fn split() -> (&'static Info, &'static State) { + static INFO: Info = Info { + register_block: crate::peripherals::MCPWM1::regs(), + _peripheral: crate::system::Peripheral::Mcpwm1, + _interrupt: crate::peripherals::Interrupt::MCPWM1, + sync_input: [ + InputSignal::PWM1_SYNC0, + InputSignal::PWM1_SYNC1, + InputSignal::PWM1_SYNC2, + ], + capture_input: [ + InputSignal::PWM1_CAP0, + InputSignal::PWM1_CAP1, + InputSignal::PWM1_CAP2, + ], + operator_a_output: [ + OutputSignal::PWM1_0A, + OutputSignal::PWM1_1A, + OutputSignal::PWM1_2A, + ], + operator_b_output: [ + OutputSignal::PWM1_0B, + OutputSignal::PWM1_1B, + OutputSignal::PWM1_2B, + ], + }; + + static STATE: State = State { + int_ena: Mutex::new(Cell::new(0)), + }; + + (&INFO, &STATE) + } +} + #[allow(dead_code)] // Field is seemingly unused but we rely on its Drop impl struct PwmClockGuard(OnDrop); impl PwmClockGuard { fn instance() -> clocks::McpwmInstance { - match PWM::info().peripheral() { + let (info, _) = PWM::split(); + match info.peripheral() { Peripheral::Mcpwm0 => clocks::McpwmInstance::Mcpwm0, #[cfg(soc_has_mcpwm1)] Peripheral::Mcpwm1 => clocks::McpwmInstance::Mcpwm1, diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 0bdc71ce8b2..089c095c9e9 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -199,8 +199,8 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { let _ = timer; // SAFETY: // We only write to our OPERATORx_TIMERSEL register - let block = PWM::info().regs(); - block.operator_timersel().modify(|_, w| match OP { + let (info, _) = PWM::split(); + info.regs().operator_timersel().modify(|_, w| match OP { 0 => unsafe { w.operator0_timersel().bits(TIM) }, 1 => unsafe { w.operator1_timersel().bits(TIM) }, 2 => unsafe { w.operator2_timersel().bits(TIM) }, @@ -296,7 +296,8 @@ pub struct PwmPin<'d, PWM: Instance, const OP: u8, const IS_A: bool> { impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A> { fn new(pin: impl PeripheralOutput<'d>, config: PwmPinConfig) -> Self { let pin = pin.into(); - let guard = PeripheralGuard::new(PWM::info().peripheral()); + let (info, _) = PWM::split(); + let guard = PeripheralGuard::new(info.peripheral()); let mut pin = PwmPin { pin, @@ -306,7 +307,7 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A pin.set_actions(config.actions); pin.set_update_method(config.update_method); - let signal = PWM::info().operator_output_signal::(); + let signal = info.operator_output_signal::(); signal.connect_to(&pin.pin); pin.pin.set_output_enable(true); @@ -396,9 +397,9 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A pub fn period(&self) -> u16 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self - let block = PWM::info().regs(); + let (info, _) = PWM::split(); - let tim_select = block.operator_timersel().read(); + let tim_select = info.regs().operator_timersel().read(); let tim = match OP { 0 => tim_select.operator0_timersel().bits(), 1 => tim_select.operator1_timersel().bits(), @@ -411,12 +412,17 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A // SAFETY: // The CFG0 registers are identical for all timers so we can pretend they're // TIMER0_CFG0 - block.timer(tim as usize).cfg0().read().period().bits() + info.regs() + .timer(tim as usize) + .cfg0() + .read() + .period() + .bits() } unsafe fn ch() -> &'static pac::mcpwm0::CH { - let block = PWM::info().regs(); - block.ch(OP as usize) + let (info, _) = PWM::split(); + info.regs().ch(OP as usize) } } @@ -543,7 +549,7 @@ impl<'d, PWM: Instance, const OP: u8> LinkedPins<'d, PWM, OP> { /// The written value will take effect according to the set /// [`PwmUpdateMethod`]. pub fn set_timestamp_b(&mut self, value: u16) { - self.pin_a.set_timestamp(value) + self.pin_b.set_timestamp(value) } /// Configure the deadtime generator @@ -573,8 +579,8 @@ impl<'d, PWM: Instance, const OP: u8> LinkedPins<'d, PWM, OP> { } unsafe fn ch() -> &'static pac::mcpwm0::CH { - let block = PWM::info().regs(); - block.ch(OP as usize) + let (info, _) = PWM::split(); + info.regs().ch(OP as usize) } } diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index 3fc2642f9dc..e75080f250f 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -13,7 +13,7 @@ //! # MCPWM Sync Module //! //! ## Overview -//! The `Sync` is resposible for managing the different ways +//! The `Sync` is responsible for managing the different ways //! MCPWM can listen to sync events. There are 2 different types of //! sync sources. One is a [`SyncOut`] that comes from [`super::Timer::get_sync_out`], //! or from a [`SyncLine`]. @@ -101,7 +101,8 @@ impl<'d, const SYNC: u8, PWM: Instance> SyncLine<'d, SYNC, PWM> { /// Set the input signal for the sync line pub fn set_signal(&mut self, source: impl PeripheralInput<'d>) { // configure GPIO matrix → SYNC - let signal = PWM::info().sync_input_signal::(); + let (info, _) = PWM::split(); + let signal = info.sync_input_signal::(); if signal as usize <= property!("gpio.input_signal_max") { let source = source.into(); @@ -111,9 +112,19 @@ impl<'d, const SYNC: u8, PWM: Instance> SyncLine<'d, SYNC, PWM> { warn!("Signal {:?} out of range", signal); } } + + /// Inverts the input signal from the supplied input source + /// If invert is true sync events are triggered on falling edges. + /// If invert is false sync events are triggered on rising edges. + pub fn set_invert(&mut self, invert: bool) { + let (info, _) = PWM::split(); + info.regs() + .timer_synci_cfg() + .modify(|_, w| w.external_synci_invert(SYNC).variant(invert)); + } } -/// Repersents the different types of sync sources +/// Represents the different types of sync sources /// Either from sync lines or from timers sync out. /// /// Shall only be created from this file @@ -124,7 +135,7 @@ pub(crate) enum SyncKind { } /// Internal trait to repersent which pwm unit and -/// sync out it came from. Broadly repersents sync lines, +/// sync out it came from. Broadly represents sync lines, /// and timer sync out. pub(crate) trait InternalSyncSource: crate::private::Sealed { fn get_kind(&self) -> SyncKind; diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 531fee672bf..1e58ad32917 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -1,8 +1,25 @@ +#![cfg_attr(docsrs, procmacros::doc_replace)] + //! # MCPWM Timer Module //! //! ## Overview //! The `timer` module provides an interface to configure and use timers for //! generating `PWM` signals used in motor control and other applications. +//! +//! The `timer` module allows the configuration of setting the sync in source +//! for the timer, and the ability to get their sync out to given to other timers +//! as their sync in. +//! +//! ### Software Sync Events +//! The `timer` module supports the software triggering of syncs from Timers. +#![cfg_attr( + soc_has_mcpwm_swsync_can_propagate, + doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." +)] +#![cfg_attr( + not(soc_has_mcpwm_swsync_can_propagate), + doc = "**Note:** Software triggered sync events do not propagate to other timers on this chip." +)] use core::marker::PhantomData; @@ -11,6 +28,7 @@ use enumset::{EnumSet, EnumSetType}; use super::PeripheralGuard; use crate::{ mcpwm::{ + Event, FrequencyError, Instance, PeripheralClockConfig, @@ -34,6 +52,16 @@ pub enum TimerEvent { TimerEqualPeriod, } +impl Into for TimerEvent { + fn into(self) -> Event { + match self { + TimerEvent::TimerEqualPeriod => Event::TimerEqualPeriod, + TimerEvent::TimerEqualZero => Event::TimerEqualZero, + TimerEvent::TimerStop => Event::TimerStop, + } + } +} + /// A MCPWM timer /// /// Every timer of a particular [`MCPWM`](super::McPwm) peripheral can be used @@ -99,11 +127,6 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// ## Overview /// Internally we set the timers phase and direction /// Then trigger a software sync event. - /// - /// Note: This triggers a sync out event. If a timer is listening - /// to this timers sync out. Then a sync event will be propagated. - /// Refer to how sync events are handled for [`super::CaptureTimer`] - /// or [`Timer`] in the their respective documentation. pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { self.set_sync_phase(phase); self.set_sync_counter_direction(direction); @@ -130,8 +153,6 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } /// Trigger a software sync event - /// Note: This always triggers a sync out event from - /// its [`Timer::get_sync_out`] source. pub fn trigger_sync(&mut self) { // SAFETY: // We only write to our TIMERx_SYNC register @@ -148,7 +169,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } /// Selects the how the timer fires sync out events - pub fn set_sync_out_selection(&mut self, sync_out: SyncOutSelection) { + pub fn set_sync_out_selection(&mut self, sync_out: SyncOutSelect) { // SAFETY: // We only modify our TIMERx_SYNC register let timer = Self::tmr(); @@ -164,18 +185,15 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } /// Sets the timer sync in source - pub fn set_sync_in(&mut self, sync: impl SyncSource) { - // SAFETY: - // We only modify the PWM TIMER_SYNCI_CFG register - let block = PWM::info().regs(); - - // SAFETY: - // We only modify our TIMERx_SYNC register + pub fn set_sync(&mut self, sync: &impl SyncSource) { + let (info, _) = PWM::split(); let timer = Self::tmr(); // Update sync select first let sync_select: SyncSelection = sync.get_kind().into(); - block.timer_synci_cfg().modify(|_r, w| { + // SAFETY: + // We only modify the PWM TIMER_SYNCI_CFG register + info.regs().timer_synci_cfg().modify(|_r, w| { unsafe { w.timer_syncisel(TIM).bits(sync_select as u8) // Update timer input sync selection } @@ -186,7 +204,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } /// Clears the sync in for the timer and disables sync input - pub fn clear_sync_in(&mut self) { + pub fn clear_sync(&mut self) { // SAFETY: // We only modify our TIMERx_SYNC register let timer = Self::tmr(); @@ -196,20 +214,20 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { #[instability::unstable] pub fn listen(&mut self, events: EnumSet) { - self.enable_interrupts(events, true); + self.enable_listen(events, true); } #[instability::unstable] pub fn unlisten(&mut self, events: EnumSet) { - self.enable_interrupts(events, false); + self.enable_listen(events, false); } #[instability::unstable] pub fn interrupts(&self) -> EnumSet { let mut res = EnumSet::new(); - let reg_block = PWM::info().regs(); + let (info, _) = PWM::split(); - let ints = reg_block.int_st().read(); + let ints = info.regs().int_st().read(); if ints.timer_stop(TIM).bit() { res.insert(TimerEvent::TimerStop); } @@ -225,33 +243,27 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { #[instability::unstable] pub fn clear_interrupts(&mut self, events: EnumSet) { - let reg_block = PWM::info().regs(); - - reg_block.int_clr().write(|w| { + let (info, _) = PWM::split(); + info.regs().int_clr().write(|w| { for event in events { match event { - TimerEvent::TimerStop => w.timer_stop(TIM).variant(true), - TimerEvent::TimerEqualPeriod => w.timer_tep(TIM).variant(true), - TimerEvent::TimerEqualZero => w.timer_tez(TIM).variant(true), + TimerEvent::TimerStop => w.timer_stop(TIM).bit(true), + TimerEvent::TimerEqualPeriod => w.timer_tep(TIM).bit(true), + TimerEvent::TimerEqualZero => w.timer_tez(TIM).bit(true), }; } w }); } - fn enable_interrupts(&mut self, events: EnumSet, value: bool) { - let reg_block = PWM::info().regs(); + fn enable_listen(&mut self, events: EnumSet, value: bool) { + let (info, state) = PWM::split(); + let mut int_events = EnumSet::new(); + for timer_event in events { + int_events.insert(timer_event.into()); + } - reg_block.int_ena().modify(|_, w| { - for event in events { - match event { - TimerEvent::TimerStop => w.timer_stop(TIM).variant(value), - TimerEvent::TimerEqualPeriod => w.timer_tep(TIM).variant(value), - TimerEvent::TimerEqualZero => w.timer_tez(TIM).variant(value), - }; - } - w - }); + state.enable_listen::(info, int_events, value); } fn cfg0(&mut self) -> &pac::mcpwm0::timer::CFG0 { @@ -267,21 +279,22 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } fn tmr() -> &'static pac::mcpwm0::TIMER { - let block = PWM::info().regs(); - block.timer(TIM as usize) + let (info, _) = PWM::split(); + info.regs().timer(TIM as usize) } } /// Sync out selection for the timer /// -/// Note: +/// Note: For chips ESP32-S3, ESP32-C5, ESP32-C6, and ESP32-H2 +/// /// During a software sync event triggered by [`Timer::trigger_sync`] or -/// [`Timer::set_counter`] a sync out is always triggered regardless if -/// if the timer was configured with [`SyncOutSelection::SyncWhenEqualZero`] or -/// [`SyncOutSelection::SyncWhenEqualPeriod`]. +/// [`Timer::set_counter`]. A software triggered sync event will +/// propagate to the sync out regardless if the timer was configured +/// with [`SyncOutSelection::SyncWhenEqualZero`] or [`SyncOutSelection::SyncWhenEqualPeriod`]. #[derive(Clone, Copy)] #[repr(u8)] -pub enum SyncOutSelection { +pub enum SyncOutSelect { /// Sync out is triggered when a timer receives a sync in SyncIn = 0, /// Sync out is triggered when the timer equals zero diff --git a/esp-metadata/devices/esp32c5.toml b/esp-metadata/devices/esp32c5.toml index f2acb70a429..9dd8fac6b94 100644 --- a/esp-metadata/devices/esp32c5.toml +++ b/esp-metadata/devices/esp32c5.toml @@ -6,16 +6,19 @@ # update the table in the esp-hal README. [device] -name = "esp32c5" -arch = "riscv" +name = "esp32c5" +arch = "riscv" target = "riscv32imac-unknown-none-elf" -cores = 1 -trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c5_technical_reference_manual_en.pdf" +cores = 1 +trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c5_technical_reference_manual_en.pdf" symbols = [ # Additional peripherals defined by us (the developers): # "lp_core", + # MCPWM capabilites + "soc_has_mcpwm_capture_clk_from_group", + # ROM capabilities "rom_crc_le", "rom_crc_be", @@ -142,31 +145,31 @@ peripherals = [ ] clocks = { system_clocks = { clock_tree = [ # High-speed clock sources - { name = "XTAL_CLK", type = "source", values = "40, 48", output = "VALUE * 1_000_000", always_on = true }, # TODO: not user-configurable - { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, - { name = "RC_FAST_CLK", type = "source", output = "20_000_000" }, + { name = "XTAL_CLK", type = "source", values = "40, 48", output = "VALUE * 1_000_000", always_on = true }, # TODO: not user-configurable + { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, + { name = "RC_FAST_CLK", type = "source", output = "20_000_000" }, # Low-speed clocks - { name = "XTAL32K_CLK", type = "source", output = "32768" }, - { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, - { name = "RC_SLOW_CLK", type = "source", output = "130_000" }, + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "130_000" }, # { name = "EXT32K_CLK", type = "source", output = "32768" }, # currently unimplemented # PLL divider taps - { name = "PLL_F12M", type = "generic", output = "PLL_CLK / 40" }, - { name = "PLL_F20M", type = "generic", output = "PLL_CLK / 24" }, - { name = "PLL_F40M", type = "generic", output = "PLL_CLK / 12" }, - { name = "PLL_F48M", type = "generic", output = "PLL_CLK / 10" }, - { name = "PLL_F60M", type = "generic", output = "PLL_CLK / 8" }, - { name = "PLL_F80M", type = "generic", output = "PLL_CLK / 6" }, - { name = "PLL_F120M", type = "generic", output = "PLL_CLK / 4" }, - { name = "PLL_F160M", type = "generic", output = "PLL_CLK / 3" }, - { name = "PLL_F240M", type = "generic", output = "PLL_CLK / 2" }, + { name = "PLL_F12M", type = "generic", output = "PLL_CLK / 40" }, + { name = "PLL_F20M", type = "generic", output = "PLL_CLK / 24" }, + { name = "PLL_F40M", type = "generic", output = "PLL_CLK / 12" }, + { name = "PLL_F48M", type = "generic", output = "PLL_CLK / 10" }, + { name = "PLL_F60M", type = "generic", output = "PLL_CLK / 8" }, + { name = "PLL_F80M", type = "generic", output = "PLL_CLK / 6" }, + { name = "PLL_F120M", type = "generic", output = "PLL_CLK / 4" }, + { name = "PLL_F160M", type = "generic", output = "PLL_CLK / 3" }, + { name = "PLL_F240M", type = "generic", output = "PLL_CLK / 2" }, # HP SOC clock root (PCR_SOC_CLK_SEL: XTAL, RC_FAST, PLL_F160M, PLL_F240M) { name = "HP_ROOT_CLK", type = "mux", variants = [ - { name = "XTAL", outputs = "XTAL_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, { name = "PLL_F160M", outputs = "PLL_F160M" }, { name = "PLL_F240M", outputs = "PLL_F240M" }, ] }, @@ -184,67 +187,67 @@ clocks = { system_clocks = { clock_tree = [ { name = "LP_FAST_CLK", type = "mux", variants = [ { name = "RC_FAST", outputs = "RC_FAST_CLK" }, { name = "XTAL_D2", outputs = "XTAL_D2_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, ] }, { name = "LP_SLOW_CLK", type = "mux", variants = [ - { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, - { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, #{ name = "EXT32K", outputs = "EXT32K_CLK" }, { name = "OSC_SLOW", outputs = "OSC_SLOW_CLK" }, ] }, - + # Global peripheral-related clocks { name = "CRYPTO_CLK", type = "mux", variants = [ # PCR_SEC_CONF - { name = "XTAL", outputs = "XTAL_CLK" }, - { name = "FOSC", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "FOSC", outputs = "RC_FAST_CLK" }, { name = "PLL_F480M", outputs = "PLL_CLK" }, ] }, { name = "TIMG_CALIBRATION_CLOCK", type = "mux", variants = [ # PCR_32K_SEL / clk_tg_xtal32k - { name = "OSC_SLOW_CLK", outputs = "OSC_SLOW_CLK" }, - { name = "RC_SLOW_CLK", outputs = "RC_SLOW_CLK" }, + { name = "OSC_SLOW_CLK", outputs = "OSC_SLOW_CLK" }, + { name = "RC_SLOW_CLK", outputs = "RC_SLOW_CLK" }, # EXT32K not modeled { name = "RC_FAST_DIV_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, + { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, ] }, ], template_groups = [ { group = "UART", clocks = [ { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ - { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "XTAL", outputs = "XTAL_CLK", default = true }, { name = "PLL_F80M", outputs = "PLL_F80M" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, ], div_num = "0 .. 0x100" } }, { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, ] }, { group = "TIMG", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, ] }, { name = "WDT_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, ] }, ] }, { group = "RMT", clocks = [ { name = "SCLK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F80M", outputs = "PLL_F80M", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M", default = true }, ] }, ] }, { group = "PARL_IO", clocks = [ { name = "RX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, + { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, # TODO: external clock ] }, { name = "TX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, + { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, ] }, ] }, ] }, peripheral_clocks = { templates = [ @@ -258,14 +261,14 @@ clocks = { system_clocks = { clock_tree = [ { name = "clk_en_field", value = "{{peripheral}}_clk_en" }, { name = "rst_field", value = "{{peripheral}}_rst_en" }, ], peripheral_clocks = [ - { name = "Uart0", template_params = { conf_register = "uart(0).conf", clk_en_field = "clk_en", rst_field = "rst_en" }, keep_enabled = true}, + { name = "Uart0", template_params = { conf_register = "uart(0).conf", clk_en_field = "clk_en", rst_field = "rst_en" }, keep_enabled = true }, { name = "Uart1", template_params = { conf_register = "uart(1).conf", clk_en_field = "clk_en", rst_field = "rst_en" } }, { name = "Timg0", template_params = { conf_register = "timergroup(0).conf", clk_en_field = "clk_en", rst_field = "rst_en" }, keep_enabled = true }, { name = "Timg1", template_params = { conf_register = "timergroup(1).conf", clk_en_field = "clk_en", rst_field = "rst_en" } }, { name = "I2cExt0", template_params = { peripheral = "i2c0" } }, { name = "Pcnt" }, { name = "Rmt" }, - { name = "Systimer", keep_enabled = true }, # can be clocked from XTAL_CLK or RC_FAST_CLK, the latter has no divider? + { 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" } }, { name = "Dma", template_params = { peripheral = "gdma" } }, @@ -291,7 +294,7 @@ dma = true dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"] key_length = { options = [ { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, - { bits = 256, encrypt_mode = 2, decrypt_mode = 6 } + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, ] } [device.dma] @@ -317,12 +320,12 @@ working_modes = [ { id = 8, mode = "modular_addition" }, { id = 9, mode = "modular_subtraction" }, { id = 10, mode = "modular_multiplication" }, - { id = 11, mode = "modular_division" } + { id = 11, mode = "modular_division" }, ] curves = [ { id = 0, curve = 192 }, { id = 1, curve = 256 }, - { id = 2, curve = 384 } + { id = 2, curve = 384 }, ] separate_jacobian_point_memory = true has_memory_clock_gate = true @@ -334,105 +337,119 @@ gpio_function = 1 constant_0_input = 0x60 constant_1_input = 0x40 pins = [ - { pin = 0, analog = { 0 = "XTAL_32K_P" }, lp = { 0 = "LP_UART_DTRN", 1 = "LP_GPIO0" } }, - { pin = 1, analog = { 0 = "XTAL_32K_N", 1 = "ADC1_CH0" }, lp = { 0 = "LP_UART_DSRN", 1 = "LP_GPIO1" } }, - { pin = 2, functions = { 0 = "MTMS", 2 = "FSPIQ" }, limitations = ["strapping"], analog = { 1 = "ADC1_CH1" }, lp = { 0 = "LP_UART_RTSN", 1 = "LP_GPIO2", 3 = "LP_I2C_SDA" } }, - { pin = 3, functions = { 0 = "MTDI" }, limitations = ["strapping"], analog = { 1 = "ADC1_CH2" }, lp = { 0 = "LP_UART_CTSN", 1 = "LP_GPIO3", 3 = "LP_I2C_SCL" } }, - { pin = 4, functions = { 0 = "MTCK", 2 = "FSPIHD" }, analog = { 1 = "ADC1_CH3" }, lp = { 0 = "LP_UART_RXD_PAD", 1 = "LP_GPIO4" } }, - { pin = 5, functions = { 0 = "MTDO", 2 = "FSPIWP" }, analog = { 1 = "ADC1_CH4" }, lp = { 0 = "LP_UART_TXD_PAD", 1 = "LP_GPIO5" } }, - { pin = 6, functions = { 2 = "FSPICLK" }, analog = { 1 = "ADC1_CH5" }, lp = { 1 = "LP_GPIO6" } }, - { pin = 7, functions = { 0 = "SDIO_DATA1", 2 = "FSPID" }, limitations = ["strapping"] }, - { pin = 8, functions = { 0 = "SDIO_DATA0" }, analog = { 0 = "ZCD0" } }, - { pin = 9, functions = { 0 = "SDIO_CLK" }, analog = { 0 = "ZCD1" } }, - { pin = 10, functions = { 0 = "SDIO_CMD", 2 = "FSPICS0" } }, - { pin = 11, functions = { 0 = "U0TXD" } }, - { pin = 12, functions = { 0 = "U0RXD" } }, - { pin = 13, functions = { 0 = "SDIO_DATA3" }, analog = { 0 = "USB_DM" } }, - { pin = 14, functions = { 0 = "SDIO_DATA2" }, analog = { 0 = "USB_DP" } }, - { pin = 23 }, - { pin = 24 }, - { pin = 25, limitations = ["strapping"] }, - { pin = 26, limitations = ["strapping"] }, - { pin = 27, limitations = ["strapping"] }, - { pin = 28, limitations = ["strapping"] }, + { pin = 0, analog = { 0 = "XTAL_32K_P" }, lp = { 0 = "LP_UART_DTRN", 1 = "LP_GPIO0" } }, + { pin = 1, analog = { 0 = "XTAL_32K_N", 1 = "ADC1_CH0" }, lp = { 0 = "LP_UART_DSRN", 1 = "LP_GPIO1" } }, + { pin = 2, functions = { 0 = "MTMS", 2 = "FSPIQ" }, limitations = [ + "strapping", + ], analog = { 1 = "ADC1_CH1" }, lp = { 0 = "LP_UART_RTSN", 1 = "LP_GPIO2", 3 = "LP_I2C_SDA" } }, + { pin = 3, functions = { 0 = "MTDI" }, limitations = [ + "strapping", + ], analog = { 1 = "ADC1_CH2" }, lp = { 0 = "LP_UART_CTSN", 1 = "LP_GPIO3", 3 = "LP_I2C_SCL" } }, + { pin = 4, functions = { 0 = "MTCK", 2 = "FSPIHD" }, analog = { 1 = "ADC1_CH3" }, lp = { 0 = "LP_UART_RXD_PAD", 1 = "LP_GPIO4" } }, + { pin = 5, functions = { 0 = "MTDO", 2 = "FSPIWP" }, analog = { 1 = "ADC1_CH4" }, lp = { 0 = "LP_UART_TXD_PAD", 1 = "LP_GPIO5" } }, + { pin = 6, functions = { 2 = "FSPICLK" }, analog = { 1 = "ADC1_CH5" }, lp = { 1 = "LP_GPIO6" } }, + { pin = 7, functions = { 0 = "SDIO_DATA1", 2 = "FSPID" }, limitations = [ + "strapping", + ] }, + { pin = 8, functions = { 0 = "SDIO_DATA0" }, analog = { 0 = "ZCD0" } }, + { pin = 9, functions = { 0 = "SDIO_CLK" }, analog = { 0 = "ZCD1" } }, + { pin = 10, functions = { 0 = "SDIO_CMD", 2 = "FSPICS0" } }, + { pin = 11, functions = { 0 = "U0TXD" } }, + { pin = 12, functions = { 0 = "U0RXD" } }, + { pin = 13, functions = { 0 = "SDIO_DATA3" }, analog = { 0 = "USB_DM" } }, + { pin = 14, functions = { 0 = "SDIO_DATA2" }, analog = { 0 = "USB_DP" } }, + { pin = 23 }, + { pin = 24 }, + { pin = 25, limitations = [ + "strapping", + ] }, + { pin = 26, limitations = [ + "strapping", + ] }, + { pin = 27, limitations = [ + "strapping", + ] }, + { pin = 28, limitations = [ + "strapping", + ] }, ] input_signals = [ - { name = "U0RXD", id = 6 }, - { name = "U0CTS", id = 7 }, - { name = "U0DSR", id = 8 }, - { name = "U1RXD", id = 9 }, - { name = "U1CTS", id = 10 }, - { name = "U1DSR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SI_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, - { name = "CPU_GPIO_0", id = 27 }, - { name = "CPU_GPIO_1", id = 28 }, - { name = "CPU_GPIO_2", id = 29 }, - { name = "CPU_GPIO_3", id = 30 }, - { name = "CPU_GPIO_4", id = 31 }, - { name = "CPU_GPIO_5", id = 32 }, - { name = "CPU_GPIO_6", id = 33 }, - { name = "CPU_GPIO_7", id = 34 }, + { name = "U0RXD", id = 6 }, + { name = "U0CTS", id = 7 }, + { name = "U0DSR", id = 8 }, + { name = "U1RXD", id = 9 }, + { name = "U1CTS", id = 10 }, + { name = "U1DSR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SI_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, + { name = "CPU_GPIO_0", id = 27 }, + { name = "CPU_GPIO_1", id = 28 }, + { name = "CPU_GPIO_2", id = 29 }, + { name = "CPU_GPIO_3", id = 30 }, + { name = "CPU_GPIO_4", id = 31 }, + { name = "CPU_GPIO_5", id = 32 }, + { name = "CPU_GPIO_6", id = 33 }, + { name = "CPU_GPIO_7", id = 34 }, { name = "USB_JTAG_TDO_BRIDGE", id = 35 }, - { name = "I2CEXT0_SCL", id = 46 }, - { name = "I2CEXT0_SDA", id = 47 }, - { name = "PARL_RX_DATA0", id = 48 }, - { name = "PARL_RX_DATA1", id = 49 }, - { name = "PARL_RX_DATA2", id = 50 }, - { name = "PARL_RX_DATA3", id = 51 }, - { name = "PARL_RX_DATA4", id = 52 }, - { name = "PARL_RX_DATA5", id = 53 }, - { name = "PARL_RX_DATA6", id = 54 }, - { name = "PARL_RX_DATA7", id = 55 }, - { name = "FSPICLK", id = 56 }, - { name = "FSPIQ", id = 57 }, - { name = "FSPID", id = 58 }, - { name = "FSPIHD", id = 59 }, - { name = "FSPIWP", id = 60 }, - { name = "FSPICS0", id = 61 }, - { name = "PARL_RX_CLK", id = 62 }, - { name = "PARL_TX_CLK", id = 63 }, - { name = "RMT_SIG_0", id = 64 }, - { name = "RMT_SIG_1", id = 65 }, - { name = "TWAI0_RX", id = 66 }, - { name = "TWAI1_RX", id = 70 }, - { name = "PCNT0_RST", id = 76 }, - { name = "PCNT1_RST", id = 77 }, - { name = "PCNT2_RST", id = 78 }, - { name = "PCNT3_RST", id = 79 }, - { name = "PWM0_SYNC0", id = 80 }, - { name = "PWM0_SYNC1", id = 81 }, - { name = "PWM0_SYNC2", id = 82 }, - { name = "PWM0_F0", id = 83 }, - { name = "PWM0_F1", id = 84 }, - { name = "PWM0_F2", id = 85 }, - { name = "PWM0_CAP0", id = 86 }, - { name = "PWM0_CAP1", id = 87 }, - { name = "PWM0_CAP2", id = 88 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "PCNT0_SIG_CH0", id = 101 }, - { name = "PCNT0_SIG_CH1", id = 102 }, - { name = "PCNT0_CTRL_CH0", id = 103 }, - { name = "PCNT0_CTRL_CH1", id = 104 }, - { name = "PCNT1_SIG_CH0", id = 105 }, - { name = "PCNT1_SIG_CH1", id = 106 }, - { name = "PCNT1_CTRL_CH0", id = 107 }, - { name = "PCNT1_CTRL_CH1", id = 108 }, - { name = "PCNT2_SIG_CH0", id = 109 }, - { name = "PCNT2_SIG_CH1", id = 110 }, - { name = "PCNT2_CTRL_CH0", id = 111 }, - { name = "PCNT2_CTRL_CH1", id = 112 }, - { name = "PCNT3_SIG_CH0", id = 113 }, - { name = "PCNT3_SIG_CH1", id = 114 }, - { name = "PCNT3_CTRL_CH0", id = 115 }, - { name = "PCNT3_CTRL_CH1", id = 116 }, + { name = "I2CEXT0_SCL", id = 46 }, + { name = "I2CEXT0_SDA", id = 47 }, + { name = "PARL_RX_DATA0", id = 48 }, + { name = "PARL_RX_DATA1", id = 49 }, + { name = "PARL_RX_DATA2", id = 50 }, + { name = "PARL_RX_DATA3", id = 51 }, + { name = "PARL_RX_DATA4", id = 52 }, + { name = "PARL_RX_DATA5", id = 53 }, + { name = "PARL_RX_DATA6", id = 54 }, + { name = "PARL_RX_DATA7", id = 55 }, + { name = "FSPICLK", id = 56 }, + { name = "FSPIQ", id = 57 }, + { name = "FSPID", id = 58 }, + { name = "FSPIHD", id = 59 }, + { name = "FSPIWP", id = 60 }, + { name = "FSPICS0", id = 61 }, + { name = "PARL_RX_CLK", id = 62 }, + { name = "PARL_TX_CLK", id = 63 }, + { name = "RMT_SIG_0", id = 64 }, + { name = "RMT_SIG_1", id = 65 }, + { name = "TWAI0_RX", id = 66 }, + { name = "TWAI1_RX", id = 70 }, + { name = "PCNT0_RST", id = 76 }, + { name = "PCNT1_RST", id = 77 }, + { name = "PCNT2_RST", id = 78 }, + { name = "PCNT3_RST", id = 79 }, + { name = "PWM0_SYNC0", id = 80 }, + { name = "PWM0_SYNC1", id = 81 }, + { name = "PWM0_SYNC2", id = 82 }, + { name = "PWM0_F0", id = 83 }, + { name = "PWM0_F1", id = 84 }, + { name = "PWM0_F2", id = 85 }, + { name = "PWM0_CAP0", id = 86 }, + { name = "PWM0_CAP1", id = 87 }, + { name = "PWM0_CAP2", id = 88 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "PCNT0_SIG_CH0", id = 101 }, + { name = "PCNT0_SIG_CH1", id = 102 }, + { name = "PCNT0_CTRL_CH0", id = 103 }, + { name = "PCNT0_CTRL_CH1", id = 104 }, + { name = "PCNT1_SIG_CH0", id = 105 }, + { name = "PCNT1_SIG_CH1", id = 106 }, + { name = "PCNT1_CTRL_CH0", id = 107 }, + { name = "PCNT1_CTRL_CH1", id = 108 }, + { name = "PCNT2_SIG_CH0", id = 109 }, + { name = "PCNT2_SIG_CH1", id = 110 }, + { name = "PCNT2_CTRL_CH0", id = 111 }, + { name = "PCNT2_CTRL_CH1", id = 112 }, + { name = "PCNT3_SIG_CH0", id = 113 }, + { name = "PCNT3_SIG_CH1", id = 114 }, + { name = "PCNT3_CTRL_CH0", id = 115 }, + { name = "PCNT3_CTRL_CH1", id = 116 }, { name = "SDIO_CLK" }, { name = "SDIO_CMD" }, @@ -447,87 +464,98 @@ input_signals = [ { name = "MTMS" }, ] output_signals = [ - { name = "LEDC_LS_SIG0", id = 0 }, - { name = "LEDC_LS_SIG1", id = 1 }, - { name = "LEDC_LS_SIG2", id = 2 }, - { name = "LEDC_LS_SIG3", id = 3 }, - { name = "LEDC_LS_SIG4", id = 4 }, - { name = "LEDC_LS_SIG5", id = 5 }, - { name = "U0TXD", id = 6 }, - { name = "U0RTS", id = 7 }, - { name = "U0DTR", id = 8 }, - { name = "U1TXD", id = 9 }, - { name = "U1RTS", id = 10 }, - { name = "U1DTR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SO_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, - { name = "I2SO_SD1", id = 18 }, - { name = "CPU_GPIO_0", id = 27 }, - { name = "CPU_GPIO_1", id = 28 }, - { name = "CPU_GPIO_2", id = 29 }, - { name = "CPU_GPIO_3", id = 30 }, - { name = "CPU_GPIO_4", id = 31 }, - { name = "CPU_GPIO_5", id = 32 }, - { name = "CPU_GPIO_6", id = 33 }, - { name = "CPU_GPIO_7", id = 34 }, - { name = "I2CEXT0_SCL", id = 46 }, - { name = "I2CEXT0_SDA", id = 47 }, - { name = "PARL_TX_DATA0", id = 48 }, - { name = "PARL_TX_DATA1", id = 49 }, - { name = "PARL_TX_DATA2", id = 50 }, - { name = "PARL_TX_DATA3", id = 51 }, - { name = "PARL_TX_DATA4", id = 52 }, - { name = "PARL_TX_DATA5", id = 53 }, - { name = "PARL_TX_DATA6", id = 54 }, - { name = "PARL_TX_DATA7", id = 55 }, - { name = "FSPICLK", id = 56 }, - { name = "FSPIQ", id = 57 }, - { name = "FSPID", id = 58 }, - { name = "FSPIHD", id = 59 }, - { name = "FSPIWP", id = 60 }, - { name = "FSPICS0", id = 61 }, - { name = "PARL_RX_CLK", id = 62 }, - { name = "PARL_TX_CLK", id = 63 }, - { name = "RMT_SIG_0", id = 64 }, - { name = "RMT_SIG_1", id = 65 }, - { name = "TWAI0_TX", id = 66 }, + { name = "LEDC_LS_SIG0", id = 0 }, + { name = "LEDC_LS_SIG1", id = 1 }, + { name = "LEDC_LS_SIG2", id = 2 }, + { name = "LEDC_LS_SIG3", id = 3 }, + { name = "LEDC_LS_SIG4", id = 4 }, + { name = "LEDC_LS_SIG5", id = 5 }, + { name = "U0TXD", id = 6 }, + { name = "U0RTS", id = 7 }, + { name = "U0DTR", id = 8 }, + { name = "U1TXD", id = 9 }, + { name = "U1RTS", id = 10 }, + { name = "U1DTR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SO_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, + { name = "I2SO_SD1", id = 18 }, + { name = "CPU_GPIO_0", id = 27 }, + { name = "CPU_GPIO_1", id = 28 }, + { name = "CPU_GPIO_2", id = 29 }, + { name = "CPU_GPIO_3", id = 30 }, + { name = "CPU_GPIO_4", id = 31 }, + { name = "CPU_GPIO_5", id = 32 }, + { name = "CPU_GPIO_6", id = 33 }, + { name = "CPU_GPIO_7", id = 34 }, + { name = "I2CEXT0_SCL", id = 46 }, + { name = "I2CEXT0_SDA", id = 47 }, + { name = "PARL_TX_DATA0", id = 48 }, + { name = "PARL_TX_DATA1", id = 49 }, + { name = "PARL_TX_DATA2", id = 50 }, + { name = "PARL_TX_DATA3", id = 51 }, + { name = "PARL_TX_DATA4", id = 52 }, + { name = "PARL_TX_DATA5", id = 53 }, + { name = "PARL_TX_DATA6", id = 54 }, + { name = "PARL_TX_DATA7", id = 55 }, + { name = "FSPICLK", id = 56 }, + { name = "FSPIQ", id = 57 }, + { name = "FSPID", id = 58 }, + { name = "FSPIHD", id = 59 }, + { name = "FSPIWP", id = 60 }, + { name = "FSPICS0", id = 61 }, + { name = "PARL_RX_CLK", id = 62 }, + { name = "PARL_TX_CLK", id = 63 }, + { name = "RMT_SIG_0", id = 64 }, + { name = "RMT_SIG_1", id = 65 }, + { name = "TWAI0_TX", id = 66 }, { name = "TWAI0_BUS_OFF_ON", id = 67 }, - { name = "TWAI0_CLKOUT", id = 68 }, - { name = "TWAI0_STANDBY", id = 69 }, - { name = "TWAI1_TX", id = 70 }, + { name = "TWAI0_CLKOUT", id = 68 }, + { name = "TWAI0_STANDBY", id = 69 }, + { name = "TWAI1_TX", id = 70 }, { name = "TWAI1_BUS_OFF_ON", id = 71 }, - { name = "TWAI1_CLKOUT", id = 72 }, - { name = "TWAI1_STANDBY", id = 73 }, - { name = "GPIO_SD0", id = 76 }, - { name = "GPIO_SD1", id = 77 }, - { name = "GPIO_SD2", id = 78 }, - { name = "GPIO_SD3", id = 79 }, - { name = "PWM0_0A", id = 80 }, - { name = "PWM0_0B", id = 81 }, - { name = "PWM0_1A", id = 82 }, - { name = "PWM0_1B", id = 83 }, - { name = "PWM0_2A", id = 84 }, - { name = "PWM0_2B", id = 85 }, - { name = "PARL_TX_CS", id = 86 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "FSPICS1", id = 101 }, - { name = "FSPICS2", id = 102 }, - { name = "FSPICS3", id = 103 }, - { name = "FSPICS4", id = 104 }, - { name = "FSPICS5", id = 105 }, - { name = "GPIO", id = 256 } + { name = "TWAI1_CLKOUT", id = 72 }, + { name = "TWAI1_STANDBY", id = 73 }, + { name = "GPIO_SD0", id = 76 }, + { name = "GPIO_SD1", id = 77 }, + { name = "GPIO_SD2", id = 78 }, + { name = "GPIO_SD3", id = 79 }, + { name = "PWM0_0A", id = 80 }, + { name = "PWM0_0B", id = 81 }, + { name = "PWM0_1A", id = 82 }, + { name = "PWM0_1B", id = 83 }, + { name = "PWM0_2A", id = 84 }, + { name = "PWM0_2B", id = 85 }, + { name = "PARL_TX_CS", id = 86 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "FSPICS1", id = 101 }, + { name = "FSPICS2", id = 102 }, + { name = "FSPICS3", id = 103 }, + { name = "FSPICS4", id = 104 }, + { name = "FSPICS5", id = 105 }, + { name = "GPIO", id = 256 }, ] [device.dedicated_gpio] support_status = "partial" -channels = [["CPU_GPIO_0", "CPU_GPIO_1", "CPU_GPIO_2", "CPU_GPIO_3", "CPU_GPIO_4", "CPU_GPIO_5", "CPU_GPIO_6", "CPU_GPIO_7"]] +channels = [ + [ + "CPU_GPIO_0", + "CPU_GPIO_1", + "CPU_GPIO_2", + "CPU_GPIO_3", + "CPU_GPIO_4", + "CPU_GPIO_5", + "CPU_GPIO_6", + "CPU_GPIO_7", + ], +] [device.i2c_master] support_status = "supported" @@ -540,11 +568,11 @@ ll_intr_mask = 0x3ffff fifo_size = 32 has_bus_timeout_enable = true max_bus_timeout = 0x1F -can_estimate_nack_reason = true # not documented +can_estimate_nack_reason = true # not documented has_conf_update = true has_reliable_fsm_reset = true has_arbitration_en = true -has_tx_fifo_watermark = true # why not s2 +has_tx_fifo_watermark = true # why not s2 bus_timeout_is_exponential = true [device.i2c_slave] @@ -564,7 +592,7 @@ algo = { sha1 = 0, sha224 = 1, sha256 = 2 } support_status = "partial" status_registers = 3 software_interrupt_count = 4 -software_interrupt_delay = 24 # CPU speed dependent +software_interrupt_delay = 24 # CPU speed dependent controller = { Riscv = { flavour = "clic", interrupts = 48, priority_levels = 8 } } [device.rmt] @@ -589,7 +617,19 @@ has_app_interrupts = true has_dma_segmented_transfer = true has_clk_pre_div = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = ["FSPID", "FSPIQ", "FSPIWP", "FSPIHD"], cs = ["FSPICS0", "FSPICS1", "FSPICS2", "FSPICS3", "FSPICS4", "FSPICS5"] }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = [ + "FSPID", + "FSPIQ", + "FSPIWP", + "FSPIHD", + ], cs = [ + "FSPICS0", + "FSPICS1", + "FSPICS2", + "FSPICS3", + "FSPICS4", + "FSPICS5", + ] }, ] [device.spi_slave] @@ -648,8 +688,8 @@ fifo_size = 16 [device.rng] support_status = "partial" -trng_supported = false # TODO -apb_cycle_wait_num = 16 # TODO +trng_supported = false # TODO +apb_cycle_wait_num = 16 # TODO ## Radio [device.wifi] diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 9c6a0852dc2..8d67c0cc9c6 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -6,11 +6,11 @@ # update the table in the esp-hal README. [device] -name = "esp32c6" -arch = "riscv" +name = "esp32c6" +arch = "riscv" target = "riscv32imac-unknown-none-elf" -cores = 1 -trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf" +cores = 1 +trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf" symbols = [ # Additional peripherals defined by us (the developers): @@ -23,6 +23,9 @@ symbols = [ "rom_crc_be", "rom_md5_bsd", + # MCPWM capabilites + "soc_has_mcpwm_capture_clk_from_group", + # Wakeup SOC based on ESP-IDF: "pm_support_wifi_wakeup", "pm_support_beacon_wakeup", @@ -138,33 +141,48 @@ peripherals = [ clocks = { system_clocks = { clock_tree = [ # High-speed clock sources - { name = "XTAL_CLK", type = "source", values = "40", output = "VALUE * 1_000_000", always_on = true }, - { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, - { name = "RC_FAST_CLK", type = "source", output = "17_500_000" }, + { name = "XTAL_CLK", type = "source", values = "40", output = "VALUE * 1_000_000", always_on = true }, + { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, + { name = "RC_FAST_CLK", type = "source", output = "17_500_000" }, # Low-speed clocks - { name = "XTAL32K_CLK", type = "source", output = "32768" }, - { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, - { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, { name = "SOC_ROOT_CLK", type = "mux", variants = [ - { name = "XTAL", outputs = "XTAL_CLK", configures = ["HP_ROOT_CLK = 1", "CPU_CLK = LS", "AHB_CLK = LS", "MSPI_FAST_CLK = LS"] }, - { name = "RC_FAST", outputs = "RC_FAST_CLK", configures = ["HP_ROOT_CLK = 1", "CPU_CLK = LS", "AHB_CLK = LS", "MSPI_FAST_CLK = LS"] }, - { name = "PLL", outputs = "PLL_CLK", configures = ["HP_ROOT_CLK = 3", "CPU_CLK = HS", "AHB_CLK = HS", "MSPI_FAST_CLK = HS"] }, + { name = "XTAL", outputs = "XTAL_CLK", configures = [ + "HP_ROOT_CLK = 1", + "CPU_CLK = LS", + "AHB_CLK = LS", + "MSPI_FAST_CLK = LS", + ] }, + { name = "RC_FAST", outputs = "RC_FAST_CLK", configures = [ + "HP_ROOT_CLK = 1", + "CPU_CLK = LS", + "AHB_CLK = LS", + "MSPI_FAST_CLK = LS", + ] }, + { name = "PLL", outputs = "PLL_CLK", configures = [ + "HP_ROOT_CLK = 3", + "CPU_CLK = HS", + "AHB_CLK = HS", + "MSPI_FAST_CLK = HS", + ] }, ] }, { name = "HP_ROOT_CLK", type = "generic", params = { divisor = "1, 3" }, output = "SOC_ROOT_CLK / divisor" }, # AUTO_DIV, only divides when using PLL_CLK # TODO: model by-4 divider for 120MHz CPU clock { name = "CPU_HS_DIV", type = "generic", params = { divisor = "0, 1, 3" }, output = "HP_ROOT_CLK / (divisor + 1)" }, { name = "CPU_LS_DIV", type = "generic", params = { divisor = "0, 1, 3, 7, 15, 31" }, output = "HP_ROOT_CLK / (divisor + 1)" }, - { name = "CPU_CLK", type = "mux", always_on = true, variants = [ + { name = "CPU_CLK", type = "mux", always_on = true, variants = [ { name = "HS", outputs = "CPU_HS_DIV" }, { name = "LS", outputs = "CPU_LS_DIV" }, ] }, { name = "AHB_HS_DIV", type = "generic", params = { divisor = "3, 7, 15" }, output = "HP_ROOT_CLK / (divisor + 1)" }, { name = "AHB_LS_DIV", type = "generic", params = { divisor = "0, 1, 3, 7, 15, 31" }, output = "HP_ROOT_CLK / (divisor + 1)" }, - { name = "AHB_CLK", type = "mux", always_on = true, variants = [ + { name = "AHB_CLK", type = "mux", always_on = true, variants = [ { name = "HS", outputs = "AHB_HS_DIV" }, { name = "LS", outputs = "AHB_LS_DIV" }, ] }, @@ -174,19 +192,19 @@ clocks = { system_clocks = { clock_tree = [ { name = "MSPI_FAST_HS_CLK", type = "generic", params = { divisor = "3, 4, 5" }, output = "HP_ROOT_CLK / (divisor + 1)" }, { name = "MSPI_FAST_LS_CLK", type = "generic", params = { divisor = "0, 1, 2" }, output = "HP_ROOT_CLK / (divisor + 1)" }, - { name = "MSPI_FAST_CLK", type = "mux", variants = [ + { name = "MSPI_FAST_CLK", type = "mux", variants = [ { name = "HS", outputs = "MSPI_FAST_HS_CLK" }, { name = "LS", outputs = "MSPI_FAST_LS_CLK" }, ] }, - { name = "PLL_F48M", type = "derived", from = "PLL_CLK", output = "48_000_000" }, - { name = "PLL_F80M", type = "derived", from = "PLL_CLK", output = "80_000_000" }, + { name = "PLL_F48M", type = "derived", from = "PLL_CLK", output = "48_000_000" }, + { name = "PLL_F80M", type = "derived", from = "PLL_CLK", output = "80_000_000" }, { name = "PLL_F160M", type = "derived", from = "PLL_CLK", output = "160_000_000" }, { name = "PLL_F240M", type = "derived", from = "PLL_CLK", output = "240_000_000" }, { name = "LEDC_SCLK", type = "mux", variants = [ - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, # LP clocks @@ -196,8 +214,8 @@ clocks = { system_clocks = { clock_tree = [ { name = "XTAL_D2_CLK", outputs = "XTAL_D2_CLK" }, ] }, { name = "LP_SLOW_CLK", type = "mux", variants = [ - { name = "XTAL32K", outputs = "XTAL32K_CLK" }, - { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, { name = "OSC_SLOW", outputs = "OSC_SLOW_CLK" }, ] }, # LP_DYN_SLOW_CLK is LP_SLOW_CLK @@ -206,63 +224,63 @@ clocks = { system_clocks = { clock_tree = [ # There are separate clock muxes for each TIMG instance, but esp-hal only uses one. Only modelling # one makes the HAL code simpler. { name = "TIMG_CALIBRATION_CLOCK", type = "mux", variants = [ - { name = "RC_SLOW_CLK", outputs = "LP_SLOW_CLK" }, + { name = "RC_SLOW_CLK", outputs = "LP_SLOW_CLK" }, { name = "RC_FAST_DIV_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, + { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, ] }, ], template_groups = [ { group = "UART", clocks = [ { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ { name = "PLL_F80M", outputs = "PLL_F80M" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK", default = true }, ], div_num = "0 .. 0x100" } }, { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, ] }, { group = "RMT", clocks = [ { name = "SCLK", type = "mux", variants = [ - { name = "PLL_F80M", outputs = "PLL_F80M", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, ] }, { group = "TIMG", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, ] }, { name = "WDT_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, ] }, ] }, { group = "MCPWM", clocks = [ # TODO: MCPWM divider? { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "PLL_F160M", outputs = "PLL_F160M", default = true }, + { name = "PLL_F160M", outputs = "PLL_F160M", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, ] }, { group = "PARL_IO", clocks = [ { name = "RX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, + { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, # TODO: external clock ] }, { name = "TX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, + { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, ] }, ] }, ] }, peripheral_clocks = { templates = [ # templates { name = "default_clk_en_template", value = "{{control}}::regs().{{conf_register}}().modify(|_, w| w.{{clk_en_field}}().bit(enable));" }, - { name = "clk_en_template", value = "{{default_clk_en_template}}" }, # Indirection allows appending to the template for TWAI + { name = "clk_en_template", value = "{{default_clk_en_template}}" }, # Indirection allows appending to the template for TWAI { name = "rst_template", value = "{{control}}::regs().{{conf_register}}().modify(|_, w| w.{{rst_field}}().bit(reset));" }, # substitutions { name = "control", value = "crate::peripherals::SYSTEM" }, @@ -284,7 +302,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "Twai0", template_params = { clk_en_template = "{{default_clk_en_template}} {{func_clk_template}}", func_clk_template = "{{control}}::regs().twai0_func_clk_conf().modify(|_, w| w.twai0_func_clk_en().bit(enable));" } }, { name = "Twai1", template_params = { clk_en_template = "{{default_clk_en_template}} {{func_clk_template}}", func_clk_template = "{{control}}::regs().twai1_func_clk_conf().modify(|_, w| w.twai1_func_clk_en().bit(enable));" } }, { name = "I2s0", template_params = { peripheral = "i2s" } }, - { name = "ApbSarAdc", template_params = { peripheral = "saradc", clk_en_field = "saradc_reg_clk_en", rst_field = "saradc_reg_rst_en" }, keep_enabled = true }, # used by some wifi calibration steps. + { name = "ApbSarAdc", template_params = { peripheral = "saradc", clk_en_field = "saradc_reg_clk_en", rst_field = "saradc_reg_rst_en" }, keep_enabled = true }, # used by some wifi calibration steps. { name = "Tsens", template_params = { conf_register = "tsens_clk_conf" } }, { name = "UsbDevice", keep_enabled = true }, # { name = "Intmtx" }, @@ -308,15 +326,13 @@ clocks = { system_clocks = { clock_tree = [ #{ name = "Cache" }, #{ name = "ModemApb" }, #{ name = "Timeout" }, - + # Radio clocks not modeled here. ] } } [device.adc] support_status = "partial" -instances = [ - { name = "adc1" }, -] +instances = [{ name = "adc1" }] [device.aes] support_status = "partial" @@ -326,7 +342,7 @@ dma = true dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"] key_length = { options = [ { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, - { bits = 256, encrypt_mode = 2, decrypt_mode = 6 } + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, ] } [device.assist_debug] @@ -350,12 +366,9 @@ working_modes = [ { id = 3, mode = "affine_point_verification_and_multiplication" }, { id = 4, mode = "jacobian_point_multiplication" }, { id = 6, mode = "jacobian_point_verification" }, - { id = 7, mode = "affine_point_verification_and_jacobian_point_multiplication" } -] -curves = [ - { id = 0, curve = 192 }, - { id = 1, curve = 256 } + { id = 7, mode = "affine_point_verification_and_jacobian_point_multiplication" }, ] +curves = [{ id = 0, curve = 192 }, { id = 1, curve = 256 }] zero_extend_writes = true has_memory_clock_gate = true @@ -365,136 +378,160 @@ gpio_function = 1 constant_0_input = 0x3c constant_1_input = 0x38 pins = [ - { pin = 0, analog = { 0 = "XTAL_32K_P", 1 = "ADC0_CH0" }, lp = { 0 = "LP_GPIO0", 1 = "LP_UART_DTRN" } }, - { pin = 1, analog = { 0 = "XTAL_32K_N", 1 = "ADC0_CH1" }, lp = { 0 = "LP_GPIO1", 1 = "LP_UART_DSRN" } }, - { pin = 2, functions = { 2 = "FSPIQ" }, analog = { 1 = "ADC0_CH2" }, lp = { 0 = "LP_GPIO2", 1 = "LP_UART_RTSN" } }, - { pin = 3, analog = { 1 = "ADC0_CH3" }, lp = { 0 = "LP_GPIO3", 1 = "LP_UART_CTSN" } }, - { pin = 4, functions = { 0 = "MTMS", 2 = "FSPIHD" }, limitations = ["strapping"], analog = { 1 = "ADC0_CH4" }, lp = { 0 = "LP_GPIO4", 1 = "LP_UART_RXD" } }, - { pin = 5, functions = { 0 = "MTDI", 2 = "FSPIWP" }, limitations = ["strapping"], analog = { 1 = "ADC0_CH5" }, lp = { 0 = "LP_GPIO5", 1 = "LP_UART_TXD" } }, - { pin = 6, functions = { 0 = "MTCK", 2 = "FSPICLK" }, analog = { 1 = "ADC0_CH6" }, lp = { 0 = "LP_GPIO6", 1 = "LP_I2C_SDA" } }, - { pin = 7, functions = { 0 = "MTDO", 2 = "FSPID" }, lp = { 0 = "LP_GPIO7", 1 = "LP_I2C_SCL" } }, - { pin = 8, limitations = ["strapping"] }, - { pin = 9, limitations = ["strapping"] }, + { pin = 0, analog = { 0 = "XTAL_32K_P", 1 = "ADC0_CH0" }, lp = { 0 = "LP_GPIO0", 1 = "LP_UART_DTRN" } }, + { pin = 1, analog = { 0 = "XTAL_32K_N", 1 = "ADC0_CH1" }, lp = { 0 = "LP_GPIO1", 1 = "LP_UART_DSRN" } }, + { pin = 2, functions = { 2 = "FSPIQ" }, analog = { 1 = "ADC0_CH2" }, lp = { 0 = "LP_GPIO2", 1 = "LP_UART_RTSN" } }, + { pin = 3, analog = { 1 = "ADC0_CH3" }, lp = { 0 = "LP_GPIO3", 1 = "LP_UART_CTSN" } }, + { pin = 4, functions = { 0 = "MTMS", 2 = "FSPIHD" }, limitations = [ + "strapping", + ], analog = { 1 = "ADC0_CH4" }, lp = { 0 = "LP_GPIO4", 1 = "LP_UART_RXD" } }, + { pin = 5, functions = { 0 = "MTDI", 2 = "FSPIWP" }, limitations = [ + "strapping", + ], analog = { 1 = "ADC0_CH5" }, lp = { 0 = "LP_GPIO5", 1 = "LP_UART_TXD" } }, + { pin = 6, functions = { 0 = "MTCK", 2 = "FSPICLK" }, analog = { 1 = "ADC0_CH6" }, lp = { 0 = "LP_GPIO6", 1 = "LP_I2C_SDA" } }, + { pin = 7, functions = { 0 = "MTDO", 2 = "FSPID" }, lp = { 0 = "LP_GPIO7", 1 = "LP_I2C_SCL" } }, + { pin = 8, limitations = [ + "strapping", + ] }, + { pin = 9, limitations = [ + "strapping", + ] }, { pin = 10 }, { pin = 11 }, { pin = 12, analog = { 0 = "USB_DM" } }, { pin = 13, analog = { 0 = "USB_DP" } }, { pin = 14 }, - { pin = 15, limitations = ["strapping"] }, - { pin = 16, functions = { 0 = "U0TXD", 2 = "FSPICS0" } }, - { pin = 17, functions = { 0 = "U0RXD", 2 = "FSPICS1" } }, - { pin = 18, functions = { 0 = "SDIO_CMD", 2 = "FSPICS2" } }, - { pin = 19, functions = { 0 = "SDIO_CLK", 2 = "FSPICS3" } }, + { pin = 15, limitations = [ + "strapping", + ] }, + { pin = 16, functions = { 0 = "U0TXD", 2 = "FSPICS0" } }, + { pin = 17, functions = { 0 = "U0RXD", 2 = "FSPICS1" } }, + { pin = 18, functions = { 0 = "SDIO_CMD", 2 = "FSPICS2" } }, + { pin = 19, functions = { 0 = "SDIO_CLK", 2 = "FSPICS3" } }, { pin = 20, functions = { 0 = "SDIO_DATA0", 2 = "FSPICS4" } }, { pin = 21, functions = { 0 = "SDIO_DATA1", 2 = "FSPICS5" } }, { pin = 22, functions = { 0 = "SDIO_DATA2" } }, { pin = 23, functions = { 0 = "SDIO_DATA3" } }, - { pin = 24, functions = { 0 = "SPICS0" }, limitations = ["spi_flash"] }, - { pin = 25, functions = { 0 = "SPIQ" }, limitations = ["spi_flash"] }, - { pin = 26, functions = { 0 = "SPIWP" }, limitations = ["spi_flash"] }, - { pin = 27, limitations = ["spi_flash"] }, - { pin = 28, functions = { 0 = "SPIHD" }, limitations = ["spi_flash"] }, - { pin = 29, functions = { 0 = "SPICLK" }, limitations = ["spi_flash"] }, - { pin = 30, functions = { 0 = "SPID" }, limitations = ["spi_flash"] }, + { pin = 24, functions = { 0 = "SPICS0" }, limitations = [ + "spi_flash", + ] }, + { pin = 25, functions = { 0 = "SPIQ" }, limitations = [ + "spi_flash", + ] }, + { pin = 26, functions = { 0 = "SPIWP" }, limitations = [ + "spi_flash", + ] }, + { pin = 27, limitations = [ + "spi_flash", + ] }, + { pin = 28, functions = { 0 = "SPIHD" }, limitations = [ + "spi_flash", + ] }, + { pin = 29, functions = { 0 = "SPICLK" }, limitations = [ + "spi_flash", + ] }, + { pin = 30, functions = { 0 = "SPID" }, limitations = [ + "spi_flash", + ] }, ] input_signals = [ - { name = "EXT_ADC_START", id = 0 }, - { name = "U0RXD", id = 6 }, - { name = "U0CTS", id = 7 }, - { name = "U0DSR", id = 8 }, - { name = "U1RXD", id = 9 }, - { name = "U1CTS", id = 10 }, - { name = "U1DSR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SI_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, + { name = "EXT_ADC_START", id = 0 }, + { name = "U0RXD", id = 6 }, + { name = "U0CTS", id = 7 }, + { name = "U0DSR", id = 8 }, + { name = "U1RXD", id = 9 }, + { name = "U1CTS", id = 10 }, + { name = "U1DSR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SI_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, { name = "USB_JTAG_TDO_BRIDGE", id = 19 }, - { name = "CPU_TESTBUS0", id = 20 }, - { name = "CPU_TESTBUS1", id = 21 }, - { name = "CPU_TESTBUS2", id = 22 }, - { name = "CPU_TESTBUS3", id = 23 }, - { name = "CPU_TESTBUS4", id = 24 }, - { name = "CPU_TESTBUS5", id = 25 }, - { name = "CPU_TESTBUS6", id = 26 }, - { name = "CPU_TESTBUS7", id = 27 }, - { name = "CPU_GPIO_0", id = 28 }, - { name = "CPU_GPIO_1", id = 29 }, - { name = "CPU_GPIO_2", id = 30 }, - { name = "CPU_GPIO_3", id = 31 }, - { name = "CPU_GPIO_4", id = 32 }, - { name = "CPU_GPIO_5", id = 33 }, - { name = "CPU_GPIO_6", id = 34 }, - { name = "CPU_GPIO_7", id = 35 }, - { name = "USB_JTAG_TMS", id = 37 }, - { name = "USB_EXTPHY_OEN", id = 40 }, - { name = "USB_EXTPHY_VM", id = 41 }, - { name = "USB_EXTPHY_VPO", id = 42 }, - { name = "I2CEXT0_SCL", id = 45 }, - { name = "I2CEXT0_SDA", id = 46 }, - { name = "PARL_RX_DATA0", id = 47 }, - { name = "PARL_RX_DATA1", id = 48 }, - { name = "PARL_RX_DATA2", id = 49 }, - { name = "PARL_RX_DATA3", id = 50 }, - { name = "PARL_RX_DATA4", id = 51 }, - { name = "PARL_RX_DATA5", id = 52 }, - { name = "PARL_RX_DATA6", id = 53 }, - { name = "PARL_RX_DATA7", id = 54 }, - { name = "PARL_RX_DATA8", id = 55 }, - { name = "PARL_RX_DATA9", id = 56 }, - { name = "PARL_RX_DATA10", id = 57 }, - { name = "PARL_RX_DATA11", id = 58 }, - { name = "PARL_RX_DATA12", id = 59 }, - { name = "PARL_RX_DATA13", id = 60 }, - { name = "PARL_RX_DATA14", id = 61 }, - { name = "PARL_RX_DATA15", id = 62 }, - { name = "FSPICLK", id = 63 }, - { name = "FSPIQ", id = 64 }, - { name = "FSPID", id = 65 }, - { name = "FSPIHD", id = 66 }, - { name = "FSPIWP", id = 67 }, - { name = "FSPICS0", id = 68 }, - { name = "PARL_RX_CLK", id = 69 }, - { name = "PARL_TX_CLK", id = 70 }, - { name = "RMT_SIG_0", id = 71 }, - { name = "RMT_SIG_1", id = 72 }, - { name = "TWAI0_RX", id = 73 }, - { name = "TWAI1_RX", id = 77 }, - { name = "PWM0_SYNC0", id = 87 }, - { name = "PWM0_SYNC1", id = 88 }, - { name = "PWM0_SYNC2", id = 89 }, - { name = "PWM0_F0", id = 90 }, - { name = "PWM0_F1", id = 91 }, - { name = "PWM0_F2", id = 92 }, - { name = "PWM0_CAP0", id = 93 }, - { name = "PWM0_CAP1", id = 94 }, - { name = "PWM0_CAP2", id = 95 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "PCNT0_SIG_CH0", id = 101 }, - { name = "PCNT0_SIG_CH1", id = 102 }, - { name = "PCNT0_CTRL_CH0", id = 103 }, - { name = "PCNT0_CTRL_CH1", id = 104 }, - { name = "PCNT1_SIG_CH0", id = 105 }, - { name = "PCNT1_SIG_CH1", id = 106 }, - { name = "PCNT1_CTRL_CH0", id = 107 }, - { name = "PCNT1_CTRL_CH1", id = 108 }, - { name = "PCNT2_SIG_CH0", id = 109 }, - { name = "PCNT2_SIG_CH1", id = 110 }, - { name = "PCNT2_CTRL_CH0", id = 111 }, - { name = "PCNT2_CTRL_CH1", id = 112 }, - { name = "PCNT3_SIG_CH0", id = 113 }, - { name = "PCNT3_SIG_CH1", id = 114 }, - { name = "PCNT3_CTRL_CH0", id = 115 }, - { name = "PCNT3_CTRL_CH1", id = 116 }, - { name = "SPIQ", id = 121 }, - { name = "SPID", id = 122 }, - { name = "SPIHD", id = 123 }, - { name = "SPIWP", id = 124 }, + { name = "CPU_TESTBUS0", id = 20 }, + { name = "CPU_TESTBUS1", id = 21 }, + { name = "CPU_TESTBUS2", id = 22 }, + { name = "CPU_TESTBUS3", id = 23 }, + { name = "CPU_TESTBUS4", id = 24 }, + { name = "CPU_TESTBUS5", id = 25 }, + { name = "CPU_TESTBUS6", id = 26 }, + { name = "CPU_TESTBUS7", id = 27 }, + { name = "CPU_GPIO_0", id = 28 }, + { name = "CPU_GPIO_1", id = 29 }, + { name = "CPU_GPIO_2", id = 30 }, + { name = "CPU_GPIO_3", id = 31 }, + { name = "CPU_GPIO_4", id = 32 }, + { name = "CPU_GPIO_5", id = 33 }, + { name = "CPU_GPIO_6", id = 34 }, + { name = "CPU_GPIO_7", id = 35 }, + { name = "USB_JTAG_TMS", id = 37 }, + { name = "USB_EXTPHY_OEN", id = 40 }, + { name = "USB_EXTPHY_VM", id = 41 }, + { name = "USB_EXTPHY_VPO", id = 42 }, + { name = "I2CEXT0_SCL", id = 45 }, + { name = "I2CEXT0_SDA", id = 46 }, + { name = "PARL_RX_DATA0", id = 47 }, + { name = "PARL_RX_DATA1", id = 48 }, + { name = "PARL_RX_DATA2", id = 49 }, + { name = "PARL_RX_DATA3", id = 50 }, + { name = "PARL_RX_DATA4", id = 51 }, + { name = "PARL_RX_DATA5", id = 52 }, + { name = "PARL_RX_DATA6", id = 53 }, + { name = "PARL_RX_DATA7", id = 54 }, + { name = "PARL_RX_DATA8", id = 55 }, + { name = "PARL_RX_DATA9", id = 56 }, + { name = "PARL_RX_DATA10", id = 57 }, + { name = "PARL_RX_DATA11", id = 58 }, + { name = "PARL_RX_DATA12", id = 59 }, + { name = "PARL_RX_DATA13", id = 60 }, + { name = "PARL_RX_DATA14", id = 61 }, + { name = "PARL_RX_DATA15", id = 62 }, + { name = "FSPICLK", id = 63 }, + { name = "FSPIQ", id = 64 }, + { name = "FSPID", id = 65 }, + { name = "FSPIHD", id = 66 }, + { name = "FSPIWP", id = 67 }, + { name = "FSPICS0", id = 68 }, + { name = "PARL_RX_CLK", id = 69 }, + { name = "PARL_TX_CLK", id = 70 }, + { name = "RMT_SIG_0", id = 71 }, + { name = "RMT_SIG_1", id = 72 }, + { name = "TWAI0_RX", id = 73 }, + { name = "TWAI1_RX", id = 77 }, + { name = "PWM0_SYNC0", id = 87 }, + { name = "PWM0_SYNC1", id = 88 }, + { name = "PWM0_SYNC2", id = 89 }, + { name = "PWM0_F0", id = 90 }, + { name = "PWM0_F1", id = 91 }, + { name = "PWM0_F2", id = 92 }, + { name = "PWM0_CAP0", id = 93 }, + { name = "PWM0_CAP1", id = 94 }, + { name = "PWM0_CAP2", id = 95 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "PCNT0_SIG_CH0", id = 101 }, + { name = "PCNT0_SIG_CH1", id = 102 }, + { name = "PCNT0_CTRL_CH0", id = 103 }, + { name = "PCNT0_CTRL_CH1", id = 104 }, + { name = "PCNT1_SIG_CH0", id = 105 }, + { name = "PCNT1_SIG_CH1", id = 106 }, + { name = "PCNT1_CTRL_CH0", id = 107 }, + { name = "PCNT1_CTRL_CH1", id = 108 }, + { name = "PCNT2_SIG_CH0", id = 109 }, + { name = "PCNT2_SIG_CH1", id = 110 }, + { name = "PCNT2_CTRL_CH0", id = 111 }, + { name = "PCNT2_CTRL_CH1", id = 112 }, + { name = "PCNT3_SIG_CH0", id = 113 }, + { name = "PCNT3_SIG_CH1", id = 114 }, + { name = "PCNT3_CTRL_CH0", id = 115 }, + { name = "PCNT3_CTRL_CH1", id = 116 }, + { name = "SPIQ", id = 121 }, + { name = "SPID", id = 122 }, + { name = "SPIHD", id = 123 }, + { name = "SPIWP", id = 124 }, { name = "SDIO_CMD" }, { name = "SDIO_DATA0" }, @@ -507,116 +544,116 @@ input_signals = [ { name = "MTMS" }, ] output_signals = [ - { name = "LEDC_LS_SIG0", id = 0 }, - { name = "LEDC_LS_SIG1", id = 1 }, - { name = "LEDC_LS_SIG2", id = 2 }, - { name = "LEDC_LS_SIG3", id = 3 }, - { name = "LEDC_LS_SIG4", id = 4 }, - { name = "LEDC_LS_SIG5", id = 5 }, - { name = "U0TXD", id = 6 }, - { name = "U0RTS", id = 7 }, - { name = "U0DTR", id = 8 }, - { name = "U1TXD", id = 9 }, - { name = "U1RTS", id = 10 }, - { name = "U1DTR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SO_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, - { name = "I2SO_SD1", id = 18 }, - { name = "USB_JTAG_TDO_BRIDGE", id = 19 }, - { name = "CPU_TESTBUS0", id = 20 }, - { name = "CPU_TESTBUS1", id = 21 }, - { name = "CPU_TESTBUS2", id = 22 }, - { name = "CPU_TESTBUS3", id = 23 }, - { name = "CPU_TESTBUS4", id = 24 }, - { name = "CPU_TESTBUS5", id = 25 }, - { name = "CPU_TESTBUS6", id = 26 }, - { name = "CPU_TESTBUS7", id = 27 }, - { name = "CPU_GPIO_0", id = 28 }, - { name = "CPU_GPIO_1", id = 29 }, - { name = "CPU_GPIO_2", id = 30 }, - { name = "CPU_GPIO_3", id = 31 }, - { name = "CPU_GPIO_4", id = 32 }, - { name = "CPU_GPIO_5", id = 33 }, - { name = "CPU_GPIO_6", id = 34 }, - { name = "CPU_GPIO_7", id = 35 }, - { name = "USB_JTAG_TCK", id = 36 }, - { name = "USB_JTAG_TMS", id = 37 }, - { name = "USB_JTAG_TDI", id = 38 }, - { name = "USB_JTAG_TDO", id = 39 }, - { name = "I2CEXT0_SCL", id = 45 }, - { name = "I2CEXT0_SDA", id = 46 }, - { name = "PARL_TX_DATA0", id = 47 }, - { name = "PARL_TX_DATA1", id = 48 }, - { name = "PARL_TX_DATA2", id = 49 }, - { name = "PARL_TX_DATA3", id = 50 }, - { name = "PARL_TX_DATA4", id = 51 }, - { name = "PARL_TX_DATA5", id = 52 }, - { name = "PARL_TX_DATA6", id = 53 }, - { name = "PARL_TX_DATA7", id = 54 }, - { name = "PARL_TX_DATA8", id = 55 }, - { name = "PARL_TX_DATA9", id = 56 }, - { name = "PARL_TX_DATA10", id = 57 }, - { name = "PARL_TX_DATA11", id = 58 }, - { name = "PARL_TX_DATA12", id = 59 }, - { name = "PARL_TX_DATA13", id = 60 }, - { name = "PARL_TX_DATA14", id = 61 }, - { name = "PARL_TX_DATA15", id = 62 }, - { name = "FSPICLK", id = 63 }, - { name = "FSPIQ", id = 64 }, - { name = "FSPID", id = 65 }, - { name = "FSPIHD", id = 66 }, - { name = "FSPIWP", id = 67 }, - { name = "FSPICS0", id = 68 }, - { name = "SDIO_TOHOST_INT", id = 69 }, - { name = "PARL_TX_CLK", id = 70 }, - { name = "RMT_SIG_0", id = 71 }, - { name = "RMT_SIG_1", id = 72 }, - { name = "TWAI0_TX", id = 73 }, - { name = "TWAI0_BUS_OFF_ON", id = 74 }, - { name = "TWAI0_CLKOUT", id = 75 }, - { name = "TWAI0_STANDBY", id = 76 }, - { name = "TWAI1_TX", id = 77 }, - { name = "TWAI1_BUS_OFF_ON", id = 78 }, - { name = "TWAI1_CLKOUT", id = 79 }, - { name = "TWAI1_STANDBY", id = 80 }, - { name = "GPIO_SD0", id = 83 }, - { name = "GPIO_SD1", id = 84 }, - { name = "GPIO_SD2", id = 85 }, - { name = "GPIO_SD3", id = 86 }, - { name = "PWM0_0A", id = 87 }, - { name = "PWM0_0B", id = 88 }, - { name = "PWM0_1A", id = 89 }, - { name = "PWM0_1B", id = 90 }, - { name = "PWM0_2A", id = 91 }, - { name = "PWM0_2B", id = 92 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "FSPICS1", id = 101 }, - { name = "FSPICS2", id = 102 }, - { name = "FSPICS3", id = 103 }, - { name = "FSPICS4", id = 104 }, - { name = "FSPICS5", id = 105 }, - { name = "SPICLK", id = 114 }, - { name = "SPICS0", id = 115 }, - { name = "SPICS1", id = 116 }, + { name = "LEDC_LS_SIG0", id = 0 }, + { name = "LEDC_LS_SIG1", id = 1 }, + { name = "LEDC_LS_SIG2", id = 2 }, + { name = "LEDC_LS_SIG3", id = 3 }, + { name = "LEDC_LS_SIG4", id = 4 }, + { name = "LEDC_LS_SIG5", id = 5 }, + { name = "U0TXD", id = 6 }, + { name = "U0RTS", id = 7 }, + { name = "U0DTR", id = 8 }, + { name = "U1TXD", id = 9 }, + { name = "U1RTS", id = 10 }, + { name = "U1DTR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SO_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, + { name = "I2SO_SD1", id = 18 }, + { name = "USB_JTAG_TDO_BRIDGE", id = 19 }, + { name = "CPU_TESTBUS0", id = 20 }, + { name = "CPU_TESTBUS1", id = 21 }, + { name = "CPU_TESTBUS2", id = 22 }, + { name = "CPU_TESTBUS3", id = 23 }, + { name = "CPU_TESTBUS4", id = 24 }, + { name = "CPU_TESTBUS5", id = 25 }, + { name = "CPU_TESTBUS6", id = 26 }, + { name = "CPU_TESTBUS7", id = 27 }, + { name = "CPU_GPIO_0", id = 28 }, + { name = "CPU_GPIO_1", id = 29 }, + { name = "CPU_GPIO_2", id = 30 }, + { name = "CPU_GPIO_3", id = 31 }, + { name = "CPU_GPIO_4", id = 32 }, + { name = "CPU_GPIO_5", id = 33 }, + { name = "CPU_GPIO_6", id = 34 }, + { name = "CPU_GPIO_7", id = 35 }, + { name = "USB_JTAG_TCK", id = 36 }, + { name = "USB_JTAG_TMS", id = 37 }, + { name = "USB_JTAG_TDI", id = 38 }, + { name = "USB_JTAG_TDO", id = 39 }, + { name = "I2CEXT0_SCL", id = 45 }, + { name = "I2CEXT0_SDA", id = 46 }, + { name = "PARL_TX_DATA0", id = 47 }, + { name = "PARL_TX_DATA1", id = 48 }, + { name = "PARL_TX_DATA2", id = 49 }, + { name = "PARL_TX_DATA3", id = 50 }, + { name = "PARL_TX_DATA4", id = 51 }, + { name = "PARL_TX_DATA5", id = 52 }, + { name = "PARL_TX_DATA6", id = 53 }, + { name = "PARL_TX_DATA7", id = 54 }, + { name = "PARL_TX_DATA8", id = 55 }, + { name = "PARL_TX_DATA9", id = 56 }, + { name = "PARL_TX_DATA10", id = 57 }, + { name = "PARL_TX_DATA11", id = 58 }, + { name = "PARL_TX_DATA12", id = 59 }, + { name = "PARL_TX_DATA13", id = 60 }, + { name = "PARL_TX_DATA14", id = 61 }, + { name = "PARL_TX_DATA15", id = 62 }, + { name = "FSPICLK", id = 63 }, + { name = "FSPIQ", id = 64 }, + { name = "FSPID", id = 65 }, + { name = "FSPIHD", id = 66 }, + { name = "FSPIWP", id = 67 }, + { name = "FSPICS0", id = 68 }, + { name = "SDIO_TOHOST_INT", id = 69 }, + { name = "PARL_TX_CLK", id = 70 }, + { name = "RMT_SIG_0", id = 71 }, + { name = "RMT_SIG_1", id = 72 }, + { name = "TWAI0_TX", id = 73 }, + { name = "TWAI0_BUS_OFF_ON", id = 74 }, + { name = "TWAI0_CLKOUT", id = 75 }, + { name = "TWAI0_STANDBY", id = 76 }, + { name = "TWAI1_TX", id = 77 }, + { name = "TWAI1_BUS_OFF_ON", id = 78 }, + { name = "TWAI1_CLKOUT", id = 79 }, + { name = "TWAI1_STANDBY", id = 80 }, + { name = "GPIO_SD0", id = 83 }, + { name = "GPIO_SD1", id = 84 }, + { name = "GPIO_SD2", id = 85 }, + { name = "GPIO_SD3", id = 86 }, + { name = "PWM0_0A", id = 87 }, + { name = "PWM0_0B", id = 88 }, + { name = "PWM0_1A", id = 89 }, + { name = "PWM0_1B", id = 90 }, + { name = "PWM0_2A", id = 91 }, + { name = "PWM0_2B", id = 92 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "FSPICS1", id = 101 }, + { name = "FSPICS2", id = 102 }, + { name = "FSPICS3", id = 103 }, + { name = "FSPICS4", id = 104 }, + { name = "FSPICS5", id = 105 }, + { name = "SPICLK", id = 114 }, + { name = "SPICS0", id = 115 }, + { name = "SPICS1", id = 116 }, { name = "GPIO_TASK_MATRIX_OUT0", id = 117 }, { name = "GPIO_TASK_MATRIX_OUT1", id = 118 }, { name = "GPIO_TASK_MATRIX_OUT2", id = 119 }, { name = "GPIO_TASK_MATRIX_OUT3", id = 120 }, - { name = "SPIQ", id = 121 }, - { name = "SPID", id = 122 }, - { name = "SPIHD", id = 123 }, - { name = "SPIWP", id = 124 }, - { name = "CLK_OUT_OUT1", id = 125 }, - { name = "CLK_OUT_OUT2", id = 126 }, - { name = "CLK_OUT_OUT3", id = 127 }, - { name = "GPIO", id = 128 }, + { name = "SPIQ", id = 121 }, + { name = "SPID", id = 122 }, + { name = "SPIHD", id = 123 }, + { name = "SPIWP", id = 124 }, + { name = "CLK_OUT_OUT1", id = 125 }, + { name = "CLK_OUT_OUT2", id = 126 }, + { name = "CLK_OUT_OUT3", id = 127 }, + { name = "GPIO", id = 128 }, { name = "SDIO_CLK" }, { name = "SDIO_CMD" }, @@ -630,7 +667,18 @@ output_signals = [ [device.dedicated_gpio] support_status = "partial" -channels = [["CPU_GPIO_0", "CPU_GPIO_1", "CPU_GPIO_2", "CPU_GPIO_3", "CPU_GPIO_4", "CPU_GPIO_5", "CPU_GPIO_6", "CPU_GPIO_7"]] +channels = [ + [ + "CPU_GPIO_0", + "CPU_GPIO_1", + "CPU_GPIO_2", + "CPU_GPIO_3", + "CPU_GPIO_4", + "CPU_GPIO_5", + "CPU_GPIO_6", + "CPU_GPIO_7", + ], +] [device.i2c_master] support_status = "supported" @@ -661,7 +709,7 @@ support_status = "not_supported" support_status = "partial" status_registers = 3 software_interrupt_count = 4 -software_interrupt_delay = 14 # CPU-speed sensitive - what's clocked from where? +software_interrupt_delay = 14 # CPU-speed sensitive - what's clocked from where? controller = { Riscv = { flavour = "plic", interrupts = 32, priority_levels = 15 } } [device.rmt] @@ -676,7 +724,7 @@ has_tx_carrier_data_only = true has_tx_sync = true has_rx_wrap = true has_rx_demodulation = true -clock_sources.supported = [ "None", "Pll80MHz", "RcFast", "Xtal" ] +clock_sources.supported = ["None", "Pll80MHz", "RcFast", "Xtal"] clock_sources.default = "Pll80MHz" [device.rsa] @@ -695,14 +743,26 @@ supports_dma = true has_app_interrupts = true has_dma_segmented_transfer = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = ["FSPID", "FSPIQ", "FSPIWP", "FSPIHD"], cs = ["FSPICS0", "FSPICS1", "FSPICS2", "FSPICS3", "FSPICS4", "FSPICS5"] }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = [ + "FSPID", + "FSPIQ", + "FSPIWP", + "FSPIHD", + ], cs = [ + "FSPICS0", + "FSPICS1", + "FSPICS2", + "FSPICS3", + "FSPICS4", + "FSPICS5", + ] }, ] [device.spi_slave] support_status = "partial" supports_dma = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, ] [device.timergroup] @@ -733,7 +793,7 @@ support_status = "not_supported" [device.rng] support_status = "partial" trng_supported = true -apb_cycle_wait_num = 16 # TODO +apb_cycle_wait_num = 16 # TODO [device.sleep] support_status = "partial" diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index 6d8b3c22e69..9180c3cbb61 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -6,17 +6,20 @@ # update the table in the esp-hal README. [device] -name = "esp32h2" -arch = "riscv" +name = "esp32h2" +arch = "riscv" target = "riscv32imac-unknown-none-elf" -cores = 1 -trm = "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf" +cores = 1 +trm = "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf" symbols = [ # Additional peripherals defined by us (the developers): "phy", "swd", + # MCPWM capabilites + "soc_has_mcpwm_capture_clk_from_group", + # ROM capabilities "rom_crc_le", "rom_crc_be", @@ -76,7 +79,7 @@ peripherals = [ { name = "PLIC_MX" }, { name = "PMU" }, { name = "RMT", clock_group = "RMT" }, - { name = "RNG", virtual = true }, # a) RNG is LP_PERI in truth. b) we need to offset the rng_data register at runtime for newer revisions. + { name = "RNG", virtual = true }, # a) RNG is LP_PERI in truth. b) we need to offset the rng_data register at runtime for newer revisions. { name = "RSA", interrupts = { peri = "RSA" } }, { name = "SHA", interrupts = { peri = "SHA" }, dma_peripheral = 7 }, { name = "ETM", pac = "SOC_ETM" }, @@ -117,23 +120,23 @@ peripherals = [ clocks = { system_clocks = { clock_tree = [ # High-speed clock sources - { name = "XTAL_CLK", type = "source", values = "32", output = "VALUE * 1_000_000", always_on = true }, + { name = "XTAL_CLK", type = "source", values = "32", output = "VALUE * 1_000_000", always_on = true }, { name = "PLL_F96M_CLK", type = "derived", from = "XTAL_CLK", output = "96_000_000" }, - { name = "PLL_F64M_CLK", type = "generic", output = "PLL_F96M_CLK * 2 / 3" }, - { name = "PLL_F48M_CLK", type = "generic", output = "PLL_F96M_CLK / 2" }, - { name = "RC_FAST_CLK", type = "source", output = "8_000_000" }, - + { name = "PLL_F64M_CLK", type = "generic", output = "PLL_F96M_CLK * 2 / 3" }, + { name = "PLL_F48M_CLK", type = "generic", output = "PLL_F96M_CLK / 2" }, + { name = "RC_FAST_CLK", type = "source", output = "8_000_000" }, + # Low-speed clocks - { name = "XTAL32K_CLK", type = "source", output = "32768" }, - { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, - { name = "RC_SLOW_CLK", type = "source", output = "130_000" }, - { name = "PLL_LP_CLK", type = "derived", from = "XTAL32K_CLK", output = "8_000_000" }, + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "130_000" }, + { name = "PLL_LP_CLK", type = "derived", from = "XTAL32K_CLK", output = "8_000_000" }, { name = "HP_ROOT_CLK", type = "mux", variants = [ - { name = "PLL96", outputs = "PLL_F96M_CLK" }, - { name = "PLL64", outputs = "PLL_F64M_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "PLL96", outputs = "PLL_F96M_CLK" }, + { name = "PLL64", outputs = "PLL_F64M_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, ] }, { name = "CPU_CLK", type = "generic", params = { divisor = "0..=255" }, output = "HP_ROOT_CLK / (divisor + 1)", always_on = true }, # AHB_CLK * integer @@ -146,12 +149,12 @@ clocks = { system_clocks = { clock_tree = [ { name = "XTAL_D2_CLK", type = "generic", output = "XTAL_CLK / 2" }, { name = "LP_FAST_CLK", type = "mux", variants = [ { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_LP_CLK", outputs = "PLL_LP_CLK" }, + { name = "PLL_LP_CLK", outputs = "PLL_LP_CLK" }, { name = "XTAL_D2_CLK", outputs = "XTAL_D2_CLK" }, ] }, { name = "LP_SLOW_CLK", type = "mux", variants = [ - { name = "XTAL32K", outputs = "XTAL32K_CLK" }, - { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, { name = "OSC_SLOW", outputs = "OSC_SLOW_CLK" }, ] }, # LP_DYN_SLOW_CLK is LP_SLOW_CLK @@ -160,62 +163,62 @@ clocks = { system_clocks = { clock_tree = [ # There are separate clock muxes for each TIMG instance, but esp-hal only uses one. Only modelling # one makes the HAL code simpler. { name = "TIMG_CALIBRATION_CLOCK", type = "mux", variants = [ - { name = "RC_SLOW_CLK", outputs = "LP_SLOW_CLK" }, + { name = "RC_SLOW_CLK", outputs = "LP_SLOW_CLK" }, { name = "RC_FAST_DIV_CLK", outputs = "RC_FAST_CLK" }, #? - { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, + { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, ] }, ], template_groups = [ { group = "UART", clocks = [ { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK", default = true }, ], div_num = "0 .. 0x100" } }, { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, ] }, { group = "RMT", clocks = [ { name = "SCLK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, ] }, ] }, { group = "TIMG", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, + { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, ] }, { name = "WDT_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, + { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, ] }, ] }, { group = "MCPWM", clocks = [ # TODO: MCPWM divider? { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, + { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, ] }, { group = "PARL_IO", clocks = [ { name = "RX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, + { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, # TODO: external clock ] }, { name = "TX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, + { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, ] }, ] }, ] }, peripheral_clocks = { templates = [ # templates { name = "default_clk_en_template", value = "{{control}}::regs().{{conf_register}}().modify(|_, w| w.{{clk_en_field}}().bit(enable));" }, - { name = "clk_en_template", value = "{{default_clk_en_template}}" }, # Indirection allows appending to the template for TWAI + { name = "clk_en_template", value = "{{default_clk_en_template}}" }, # Indirection allows appending to the template for TWAI { name = "rst_template", value = "{{control}}::regs().{{conf_register}}().modify(|_, w| w.{{rst_field}}().bit(reset));" }, # substitutions { name = "control", value = "crate::peripherals::SYSTEM" }, @@ -267,9 +270,7 @@ clocks = { system_clocks = { clock_tree = [ [device.adc] support_status = "partial" -instances = [ - { name = "adc1" }, -] +instances = [{ name = "adc1" }] [device.aes] support_status = "partial" @@ -279,7 +280,7 @@ dma = true dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"] key_length = { options = [ { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, - { bits = 256, encrypt_mode = 2, decrypt_mode = 6 } + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, ] } [device.assist_debug] @@ -308,12 +309,9 @@ working_modes = [ { id = 8, mode = "modular_addition" }, { id = 9, mode = "modular_subtraction" }, { id = 10, mode = "modular_multiplication" }, - { id = 11, mode = "modular_division" } -] -curves = [ - { id = 0, curve = 192 }, - { id = 1, curve = 256 } + { id = 11, mode = "modular_division" }, ] +curves = [{ id = 0, curve = 192 }, { id = 1, curve = 256 }] zero_extend_writes = true separate_jacobian_point_memory = true has_memory_clock_gate = true @@ -325,213 +323,234 @@ gpio_function = 1 constant_0_input = 0x3c constant_1_input = 0x38 pins = [ - { pin = 0, functions = { 2 = "FSPIQ" } }, - { pin = 1, functions = { 2 = "FSPICS0" }, analog = { 1 = "ADC1_CH0" } }, - { pin = 2, functions = { 0 = "MTMS", 2 = "FSPIWP" }, analog = { 1 = "ADC1_CH1" } }, - { pin = 3, functions = { 0 = "MTDI", 2 = "FSPIHD" }, analog = { 1 = "ADC1_CH2" } }, - { pin = 4, functions = { 0 = "MTCK", 2 = "FSPICLK" }, analog = { 1 = "ADC1_CH3" } }, - { pin = 5, functions = { 0 = "MTDO", 2 = "FSPID" }, analog = { 1 = "ADC1_CH4" } }, - { pin = 6, limitations = ["spi_flash"] }, - { pin = 7, lp = { 0 = "LP_GPIO0" }, limitations = ["spi_flash"] }, - { pin = 8, lp = { 0 = "LP_GPIO1" }, limitations = ["strapping"] }, - { pin = 9, lp = { 0 = "LP_GPIO2" }, limitations = ["strapping"] }, - { pin = 10, lp = { 0 = "LP_GPIO3" }, analog = { 0 = "ZCD0" } }, - { pin = 11, lp = { 0 = "LP_GPIO4" }, analog = { 0 = "ZCD1" } }, + { pin = 0, functions = { 2 = "FSPIQ" } }, + { pin = 1, functions = { 2 = "FSPICS0" }, analog = { 1 = "ADC1_CH0" } }, + { pin = 2, functions = { 0 = "MTMS", 2 = "FSPIWP" }, analog = { 1 = "ADC1_CH1" } }, + { pin = 3, functions = { 0 = "MTDI", 2 = "FSPIHD" }, analog = { 1 = "ADC1_CH2" } }, + { pin = 4, functions = { 0 = "MTCK", 2 = "FSPICLK" }, analog = { 1 = "ADC1_CH3" } }, + { pin = 5, functions = { 0 = "MTDO", 2 = "FSPID" }, analog = { 1 = "ADC1_CH4" } }, + { pin = 6, limitations = [ + "spi_flash", + ] }, + { pin = 7, lp = { 0 = "LP_GPIO0" }, limitations = [ + "spi_flash", + ] }, + { pin = 8, lp = { 0 = "LP_GPIO1" }, limitations = [ + "strapping", + ] }, + { pin = 9, lp = { 0 = "LP_GPIO2" }, limitations = [ + "strapping", + ] }, + { pin = 10, lp = { 0 = "LP_GPIO3" }, analog = { 0 = "ZCD0" } }, + { pin = 11, lp = { 0 = "LP_GPIO4" }, analog = { 0 = "ZCD1" } }, { pin = 12, lp = { 0 = "LP_GPIO5" } }, - { pin = 13, lp = { 0 = "LP_GPIO6" }, analog = { 0 = "XTAL_32K_P" } }, - { pin = 14, lp = { 0 = "LP_GPIO7" }, analog = { 0 = "XTAL_32K_N" } }, + { pin = 13, lp = { 0 = "LP_GPIO6" }, analog = { 0 = "XTAL_32K_P" } }, + { pin = 14, lp = { 0 = "LP_GPIO7" }, analog = { 0 = "XTAL_32K_N" } }, { pin = 22 }, { pin = 23, functions = { 0 = "U0RXD", 2 = "FSPICS1" } }, { pin = 24, functions = { 0 = "U0TXD", 2 = "FSPICS2" } }, - { pin = 25, functions = { 2 = "FSPICS3" }, limitations = ["strapping"] }, - { pin = 26, functions = { 2 = "FSPICS4" }, analog = { 0 = "USB_DM" } }, - { pin = 27, functions = { 2 = "FSPICS5" }, analog = { 0 = "USB_DP" } }, + { pin = 25, functions = { 2 = "FSPICS3" }, limitations = [ + "strapping", + ] }, + { pin = 26, functions = { 2 = "FSPICS4" }, analog = { 0 = "USB_DM" } }, + { pin = 27, functions = { 2 = "FSPICS5" }, analog = { 0 = "USB_DP" } }, ] input_signals = [ - { name = "EXT_ADC_START", id = 0 }, - { name = "U0RXD", id = 6 }, - { name = "U0CTS", id = 7 }, - { name = "U0DSR", id = 8 }, - { name = "U1RXD", id = 9 }, - { name = "U1CTS", id = 10 }, - { name = "U1DSR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SI_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, + { name = "EXT_ADC_START", id = 0 }, + { name = "U0RXD", id = 6 }, + { name = "U0CTS", id = 7 }, + { name = "U0DSR", id = 8 }, + { name = "U1RXD", id = 9 }, + { name = "U1CTS", id = 10 }, + { name = "U1DSR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SI_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, { name = "USB_JTAG_TDO_BRIDGE", id = 19 }, - { name = "CPU_GPIO_0", id = 28 }, - { name = "CPU_GPIO_1", id = 29 }, - { name = "CPU_GPIO_2", id = 30 }, - { name = "CPU_GPIO_3", id = 31 }, - { name = "CPU_GPIO_4", id = 32 }, - { name = "CPU_GPIO_5", id = 33 }, - { name = "CPU_GPIO_6", id = 34 }, - { name = "CPU_GPIO_7", id = 35 }, - { name = "I2CEXT0_SCL", id = 45 }, - { name = "I2CEXT0_SDA", id = 46 }, - { name = "PARL_RX_DATA0", id = 47 }, - { name = "PARL_RX_DATA1", id = 48 }, - { name = "PARL_RX_DATA2", id = 49 }, - { name = "PARL_RX_DATA3", id = 50 }, - { name = "PARL_RX_DATA4", id = 51 }, - { name = "PARL_RX_DATA5", id = 52 }, - { name = "PARL_RX_DATA6", id = 53 }, - { name = "PARL_RX_DATA7", id = 54 }, - { name = "I2CEXT1_SCL", id = 55 }, - { name = "I2CEXT1_SDA", id = 56 }, - { name = "FSPICLK", id = 63 }, - { name = "FSPIQ", id = 64 }, - { name = "FSPID", id = 65 }, - { name = "FSPIHD", id = 66 }, - { name = "FSPIWP", id = 67 }, - { name = "FSPICS0", id = 68 }, - { name = "PARL_RX_CLK", id = 69 }, - { name = "PARL_TX_CLK", id = 70 }, - { name = "RMT_SIG_0", id = 71 }, - { name = "RMT_SIG_1", id = 72 }, - { name = "TWAI0_RX", id = 73 }, - { name = "PWM0_SYNC0", id = 87 }, - { name = "PWM0_SYNC1", id = 88 }, - { name = "PWM0_SYNC2", id = 89 }, - { name = "PWM0_F0", id = 90 }, - { name = "PWM0_F1", id = 91 }, - { name = "PWM0_F2", id = 92 }, - { name = "PWM0_CAP0", id = 93 }, - { name = "PWM0_CAP1", id = 94 }, - { name = "PWM0_CAP2", id = 95 }, - { name = "SIG_FUNC_97", id = 97 }, - { name = "SIG_FUNC_98", id = 98 }, - { name = "SIG_FUNC_99", id = 99 }, - { name = "SIG_FUNC_100", id = 100 }, - { name = "PCNT0_SIG_CH0", id = 101 }, - { name = "PCNT0_SIG_CH1", id = 102 }, - { name = "PCNT0_CTRL_CH0", id = 103 }, - { name = "PCNT0_CTRL_CH1", id = 104 }, - { name = "PCNT1_SIG_CH0", id = 105 }, - { name = "PCNT1_SIG_CH1", id = 106 }, - { name = "PCNT1_CTRL_CH0", id = 107 }, - { name = "PCNT1_CTRL_CH1", id = 108 }, - { name = "PCNT2_SIG_CH0", id = 109 }, - { name = "PCNT2_SIG_CH1", id = 110 }, - { name = "PCNT2_CTRL_CH0", id = 111 }, - { name = "PCNT2_CTRL_CH1", id = 112 }, - { name = "PCNT3_SIG_CH0", id = 113 }, - { name = "PCNT3_SIG_CH1", id = 114 }, - { name = "PCNT3_CTRL_CH0", id = 115 }, - { name = "PCNT3_CTRL_CH1", id = 116 }, - { name = "SPIQ", id = 121 }, - { name = "SPID", id = 122 }, - { name = "SPIHD", id = 123 }, - { name = "SPIWP", id = 124 }, + { name = "CPU_GPIO_0", id = 28 }, + { name = "CPU_GPIO_1", id = 29 }, + { name = "CPU_GPIO_2", id = 30 }, + { name = "CPU_GPIO_3", id = 31 }, + { name = "CPU_GPIO_4", id = 32 }, + { name = "CPU_GPIO_5", id = 33 }, + { name = "CPU_GPIO_6", id = 34 }, + { name = "CPU_GPIO_7", id = 35 }, + { name = "I2CEXT0_SCL", id = 45 }, + { name = "I2CEXT0_SDA", id = 46 }, + { name = "PARL_RX_DATA0", id = 47 }, + { name = "PARL_RX_DATA1", id = 48 }, + { name = "PARL_RX_DATA2", id = 49 }, + { name = "PARL_RX_DATA3", id = 50 }, + { name = "PARL_RX_DATA4", id = 51 }, + { name = "PARL_RX_DATA5", id = 52 }, + { name = "PARL_RX_DATA6", id = 53 }, + { name = "PARL_RX_DATA7", id = 54 }, + { name = "I2CEXT1_SCL", id = 55 }, + { name = "I2CEXT1_SDA", id = 56 }, + { name = "FSPICLK", id = 63 }, + { name = "FSPIQ", id = 64 }, + { name = "FSPID", id = 65 }, + { name = "FSPIHD", id = 66 }, + { name = "FSPIWP", id = 67 }, + { name = "FSPICS0", id = 68 }, + { name = "PARL_RX_CLK", id = 69 }, + { name = "PARL_TX_CLK", id = 70 }, + { name = "RMT_SIG_0", id = 71 }, + { name = "RMT_SIG_1", id = 72 }, + { name = "TWAI0_RX", id = 73 }, + { name = "PWM0_SYNC0", id = 87 }, + { name = "PWM0_SYNC1", id = 88 }, + { name = "PWM0_SYNC2", id = 89 }, + { name = "PWM0_F0", id = 90 }, + { name = "PWM0_F1", id = 91 }, + { name = "PWM0_F2", id = 92 }, + { name = "PWM0_CAP0", id = 93 }, + { name = "PWM0_CAP1", id = 94 }, + { name = "PWM0_CAP2", id = 95 }, + { name = "SIG_FUNC_97", id = 97 }, + { name = "SIG_FUNC_98", id = 98 }, + { name = "SIG_FUNC_99", id = 99 }, + { name = "SIG_FUNC_100", id = 100 }, + { name = "PCNT0_SIG_CH0", id = 101 }, + { name = "PCNT0_SIG_CH1", id = 102 }, + { name = "PCNT0_CTRL_CH0", id = 103 }, + { name = "PCNT0_CTRL_CH1", id = 104 }, + { name = "PCNT1_SIG_CH0", id = 105 }, + { name = "PCNT1_SIG_CH1", id = 106 }, + { name = "PCNT1_CTRL_CH0", id = 107 }, + { name = "PCNT1_CTRL_CH1", id = 108 }, + { name = "PCNT2_SIG_CH0", id = 109 }, + { name = "PCNT2_SIG_CH1", id = 110 }, + { name = "PCNT2_CTRL_CH0", id = 111 }, + { name = "PCNT2_CTRL_CH1", id = 112 }, + { name = "PCNT3_SIG_CH0", id = 113 }, + { name = "PCNT3_SIG_CH1", id = 114 }, + { name = "PCNT3_CTRL_CH0", id = 115 }, + { name = "PCNT3_CTRL_CH1", id = 116 }, + { name = "SPIQ", id = 121 }, + { name = "SPID", id = 122 }, + { name = "SPIHD", id = 123 }, + { name = "SPIWP", id = 124 }, { name = "MTDI" }, { name = "MTCK" }, { name = "MTMS" }, ] output_signals = [ - { name = "LEDC_LS_SIG0", id = 0 }, - { name = "LEDC_LS_SIG1", id = 1 }, - { name = "LEDC_LS_SIG2", id = 2 }, - { name = "LEDC_LS_SIG3", id = 3 }, - { name = "LEDC_LS_SIG4", id = 4 }, - { name = "LEDC_LS_SIG5", id = 5 }, - { name = "U0TXD", id = 6 }, - { name = "U0RTS", id = 7 }, - { name = "U0DTR", id = 8 }, - { name = "U1TXD", id = 9 }, - { name = "U1RTS", id = 10 }, - { name = "U1DTR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SO_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, - { name = "I2SO_SD1", id = 18 }, - { name = "USB_JTAG_TRST", id = 19 }, - { name = "CPU_GPIO_0", id = 28 }, - { name = "CPU_GPIO_1", id = 29 }, - { name = "CPU_GPIO_2", id = 30 }, - { name = "CPU_GPIO_3", id = 31 }, - { name = "CPU_GPIO_4", id = 32 }, - { name = "CPU_GPIO_5", id = 33 }, - { name = "CPU_GPIO_6", id = 34 }, - { name = "CPU_GPIO_7", id = 35 }, - { name = "I2CEXT0_SCL", id = 45 }, - { name = "I2CEXT0_SDA", id = 46 }, - { name = "PARL_TX_DATA0", id = 47 }, - { name = "PARL_TX_DATA1", id = 48 }, - { name = "PARL_TX_DATA2", id = 49 }, - { name = "PARL_TX_DATA3", id = 50 }, - { name = "PARL_TX_DATA4", id = 51 }, - { name = "PARL_TX_DATA5", id = 52 }, - { name = "PARL_TX_DATA6", id = 53 }, - { name = "PARL_TX_DATA7", id = 54 }, - { name = "I2CEXT1_SCL", id = 55 }, - { name = "I2CEXT1_SDA", id = 56 }, - { name = "FSPICLK", id = 63 }, - { name = "FSPIQ", id = 64 }, - { name = "FSPID", id = 65 }, - { name = "FSPIHD", id = 66 }, - { name = "FSPIWP", id = 67 }, - { name = "FSPICS0", id = 68 }, - { name = "PARL_RX_CLK", id = 69 }, - { name = "PARL_TX_CLK", id = 70 }, - { name = "RMT_SIG_0", id = 71 }, - { name = "RMT_SIG_1", id = 72 }, - { name = "TWAI0_TX", id = 73 }, + { name = "LEDC_LS_SIG0", id = 0 }, + { name = "LEDC_LS_SIG1", id = 1 }, + { name = "LEDC_LS_SIG2", id = 2 }, + { name = "LEDC_LS_SIG3", id = 3 }, + { name = "LEDC_LS_SIG4", id = 4 }, + { name = "LEDC_LS_SIG5", id = 5 }, + { name = "U0TXD", id = 6 }, + { name = "U0RTS", id = 7 }, + { name = "U0DTR", id = 8 }, + { name = "U1TXD", id = 9 }, + { name = "U1RTS", id = 10 }, + { name = "U1DTR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SO_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, + { name = "I2SO_SD1", id = 18 }, + { name = "USB_JTAG_TRST", id = 19 }, + { name = "CPU_GPIO_0", id = 28 }, + { name = "CPU_GPIO_1", id = 29 }, + { name = "CPU_GPIO_2", id = 30 }, + { name = "CPU_GPIO_3", id = 31 }, + { name = "CPU_GPIO_4", id = 32 }, + { name = "CPU_GPIO_5", id = 33 }, + { name = "CPU_GPIO_6", id = 34 }, + { name = "CPU_GPIO_7", id = 35 }, + { name = "I2CEXT0_SCL", id = 45 }, + { name = "I2CEXT0_SDA", id = 46 }, + { name = "PARL_TX_DATA0", id = 47 }, + { name = "PARL_TX_DATA1", id = 48 }, + { name = "PARL_TX_DATA2", id = 49 }, + { name = "PARL_TX_DATA3", id = 50 }, + { name = "PARL_TX_DATA4", id = 51 }, + { name = "PARL_TX_DATA5", id = 52 }, + { name = "PARL_TX_DATA6", id = 53 }, + { name = "PARL_TX_DATA7", id = 54 }, + { name = "I2CEXT1_SCL", id = 55 }, + { name = "I2CEXT1_SDA", id = 56 }, + { name = "FSPICLK", id = 63 }, + { name = "FSPIQ", id = 64 }, + { name = "FSPID", id = 65 }, + { name = "FSPIHD", id = 66 }, + { name = "FSPIWP", id = 67 }, + { name = "FSPICS0", id = 68 }, + { name = "PARL_RX_CLK", id = 69 }, + { name = "PARL_TX_CLK", id = 70 }, + { name = "RMT_SIG_0", id = 71 }, + { name = "RMT_SIG_1", id = 72 }, + { name = "TWAI0_TX", id = 73 }, { name = "TWAI0_BUS_OFF_ON", id = 74 }, - { name = "TWAI0_CLKOUT", id = 75 }, - { name = "TWAI0_STANDBY", id = 76 }, - { name = "CTE_ANT7", id = 78 }, - { name = "CTE_ANT8", id = 79 }, - { name = "CTE_ANT9", id = 80 }, - { name = "GPIO_SD0", id = 83 }, - { name = "GPIO_SD1", id = 84 }, - { name = "GPIO_SD2", id = 85 }, - { name = "GPIO_SD3", id = 86 }, - { name = "PWM0_0A", id = 87 }, - { name = "PWM0_0B", id = 88 }, - { name = "PWM0_1A", id = 89 }, - { name = "PWM0_1B", id = 90 }, - { name = "PWM0_2A", id = 91 }, - { name = "PWM0_2B", id = 92 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "FSPICS1", id = 101 }, - { name = "FSPICS2", id = 102 }, - { name = "FSPICS3", id = 103 }, - { name = "FSPICS4", id = 104 }, - { name = "FSPICS5", id = 105 }, - { name = "CTE_ANT10", id = 106 }, - { name = "CTE_ANT11", id = 107 }, - { name = "CTE_ANT12", id = 108 }, - { name = "CTE_ANT13", id = 109 }, - { name = "CTE_ANT14", id = 110 }, - { name = "CTE_ANT15", id = 111 }, - { name = "SPICLK", id = 114 }, - { name = "SPICS0", id = 115 }, - { name = "SPICS1", id = 116 }, - { name = "SPIQ", id = 121 }, - { name = "SPID", id = 122 }, - { name = "SPIHD", id = 123 }, - { name = "SPIWP", id = 124 }, - { name = "CLK_OUT_OUT1", id = 125 }, - { name = "CLK_OUT_OUT2", id = 126 }, - { name = "CLK_OUT_OUT3", id = 127 }, - { name = "GPIO", id = 128 }, - - { name = "MTDO" } + { name = "TWAI0_CLKOUT", id = 75 }, + { name = "TWAI0_STANDBY", id = 76 }, + { name = "CTE_ANT7", id = 78 }, + { name = "CTE_ANT8", id = 79 }, + { name = "CTE_ANT9", id = 80 }, + { name = "GPIO_SD0", id = 83 }, + { name = "GPIO_SD1", id = 84 }, + { name = "GPIO_SD2", id = 85 }, + { name = "GPIO_SD3", id = 86 }, + { name = "PWM0_0A", id = 87 }, + { name = "PWM0_0B", id = 88 }, + { name = "PWM0_1A", id = 89 }, + { name = "PWM0_1B", id = 90 }, + { name = "PWM0_2A", id = 91 }, + { name = "PWM0_2B", id = 92 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "FSPICS1", id = 101 }, + { name = "FSPICS2", id = 102 }, + { name = "FSPICS3", id = 103 }, + { name = "FSPICS4", id = 104 }, + { name = "FSPICS5", id = 105 }, + { name = "CTE_ANT10", id = 106 }, + { name = "CTE_ANT11", id = 107 }, + { name = "CTE_ANT12", id = 108 }, + { name = "CTE_ANT13", id = 109 }, + { name = "CTE_ANT14", id = 110 }, + { name = "CTE_ANT15", id = 111 }, + { name = "SPICLK", id = 114 }, + { name = "SPICS0", id = 115 }, + { name = "SPICS1", id = 116 }, + { name = "SPIQ", id = 121 }, + { name = "SPID", id = 122 }, + { name = "SPIHD", id = 123 }, + { name = "SPIWP", id = 124 }, + { name = "CLK_OUT_OUT1", id = 125 }, + { name = "CLK_OUT_OUT2", id = 126 }, + { name = "CLK_OUT_OUT3", id = 127 }, + { name = "GPIO", id = 128 }, + + { name = "MTDO" }, ] [device.dedicated_gpio] support_status = "partial" -channels = [["CPU_GPIO_0", "CPU_GPIO_1", "CPU_GPIO_2", "CPU_GPIO_3", "CPU_GPIO_4", "CPU_GPIO_5", "CPU_GPIO_6", "CPU_GPIO_7"]] +channels = [ + [ + "CPU_GPIO_0", + "CPU_GPIO_1", + "CPU_GPIO_2", + "CPU_GPIO_3", + "CPU_GPIO_4", + "CPU_GPIO_5", + "CPU_GPIO_6", + "CPU_GPIO_7", + ], +] [device.i2c_master] support_status = "supported" @@ -574,7 +593,7 @@ has_tx_carrier_data_only = true has_tx_sync = true has_rx_wrap = true has_rx_demodulation = true -clock_sources.supported = ["Xtal", "RcFast" ] +clock_sources.supported = ["Xtal", "RcFast"] # Power-on value is RcFast! clock_sources.default = "Xtal" @@ -594,14 +613,26 @@ supports_dma = true has_app_interrupts = true has_dma_segmented_transfer = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = ["FSPID", "FSPIQ", "FSPIWP", "FSPIHD"], cs = ["FSPICS0", "FSPICS1", "FSPICS2", "FSPICS3", "FSPICS4", "FSPICS5"] }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = [ + "FSPID", + "FSPIQ", + "FSPIWP", + "FSPIHD", + ], cs = [ + "FSPICS0", + "FSPICS1", + "FSPICS2", + "FSPICS3", + "FSPICS4", + "FSPICS5", + ] }, ] [device.spi_slave] support_status = "partial" supports_dma = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, ] [device.timergroup] @@ -628,7 +659,7 @@ support_status = "not_supported" [device.rng] support_status = "partial" trng_supported = true -apb_cycle_wait_num = 16 # TODO +apb_cycle_wait_num = 16 # TODO [device.parl_io] support_status = "partial" From dd42b2be4d588c8e5c01e17b34cedfe0594a78df Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Wed, 1 Apr 2026 23:09:25 -0600 Subject: [PATCH 12/37] Updateded esp-metadata for mcpwm capabilities. --- esp-hal/src/mcpwm/capture.rs | 4 +- esp-hal/src/mcpwm/mod.rs | 6 +- esp-hal/src/mcpwm/timer.rs | 4 +- .../src/_build_script_utils.rs | 16 + esp-metadata/devices/esp32c5.toml | 3 +- esp-metadata/devices/esp32c6.toml | 3 +- esp-metadata/devices/esp32h2.toml | 3 +- esp-metadata/devices/esp32s3.toml | 962 ++++++++++-------- 8 files changed, 557 insertions(+), 444 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index a82340d4b69..b700b08156b 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -257,9 +257,7 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { Self::cfg().modify(|_, w| { w.mode().variant(config.capture_mode); w.in_invert().variant(config.invert); - unsafe { - w.prescale().bits(config.prescaler); - } + unsafe { w.prescale().bits(config.prescaler) } }); } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index 8cbecc73550..b9dfdf0f651 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -61,16 +61,16 @@ //! * A hardware sync or software sync can trigger a reload on the capture timer with the set //! phase. #![cfg_attr( - soc_has_mcpwm_capture_clk_from_group, + soc_mcpwm_capture_clk_from_group, doc = " * Capture timer's clock source is the same as the PWM timers clock source" )] #![cfg_attr( - not(soc_has_mcpwm_capture_clk_from_group), + not(soc_mcpwm_capture_clk_from_group), doc = " * Capture timer's has it's own independent clock source from the MCPWM peripheral." )] //! * Fault Detection Module (Not yet implemented) #![cfg_attr( - not(soc_has_mcpwm_capture_clk_from_group), + not(soc_mcpwm_capture_clk_from_group), doc = "\nCapture clock source is `ADB-CLK (80 MHz)` by default.\n" )] //! Clock source is `__clock_src__`` by default. diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 1e58ad32917..c8a976e015d 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -13,11 +13,11 @@ //! ### Software Sync Events //! The `timer` module supports the software triggering of syncs from Timers. #![cfg_attr( - soc_has_mcpwm_swsync_can_propagate, + soc_mcpwm_swsync_can_propagate, doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." )] #![cfg_attr( - not(soc_has_mcpwm_swsync_can_propagate), + not(soc_mcpwm_swsync_can_propagate), doc = "**Note:** Software triggered sync events do not propagate to other timers on this chip." )] diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 41206d11269..1a253eb296d 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -1772,6 +1772,8 @@ impl Chip { "soc_has_mem2mem6", "soc_has_mem2mem7", "soc_has_mem2mem8", + "soc_mcpwm_swsync_can_propagate", + "soc_mcpwm_capture_clk_from_group", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", @@ -2011,6 +2013,8 @@ impl Chip { "cargo:rustc-cfg=soc_has_mem2mem6", "cargo:rustc-cfg=soc_has_mem2mem7", "cargo:rustc-cfg=soc_has_mem2mem8", + "cargo:rustc-cfg=soc_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=soc_mcpwm_capture_clk_from_group", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", @@ -2371,6 +2375,8 @@ impl Chip { "rom_crc_le", "rom_crc_be", "rom_md5_bsd", + "soc_mcpwm_swsync_can_propagate", + "soc_mcpwm_capture_clk_from_group", "pm_support_wifi_wakeup", "pm_support_beacon_wakeup", "pm_support_bt_wakeup", @@ -2645,6 +2651,8 @@ impl Chip { "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", + "cargo:rustc-cfg=soc_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=soc_mcpwm_capture_clk_from_group", "cargo:rustc-cfg=pm_support_wifi_wakeup", "cargo:rustc-cfg=pm_support_beacon_wakeup", "cargo:rustc-cfg=pm_support_bt_wakeup", @@ -3421,6 +3429,8 @@ impl Chip { "soc_has_mem2mem8", "phy", "swd", + "soc_mcpwm_swsync_can_propagate", + "soc_mcpwm_capture_clk_from_group", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", @@ -3659,6 +3669,8 @@ impl Chip { "cargo:rustc-cfg=soc_has_mem2mem8", "cargo:rustc-cfg=phy", "cargo:rustc-cfg=swd", + "cargo:rustc-cfg=soc_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=soc_mcpwm_capture_clk_from_group", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", @@ -4615,6 +4627,7 @@ impl Chip { "octal_psram", "swd", "ulp_riscv_core", + "soc_mcpwm_swsync_can_propagate", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", @@ -4863,6 +4876,7 @@ impl Chip { "cargo:rustc-cfg=octal_psram", "cargo:rustc-cfg=swd", "cargo:rustc-cfg=ulp_riscv_core", + "cargo:rustc-cfg=soc_mcpwm_swsync_can_propagate", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", @@ -5598,6 +5612,8 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem6)"); println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem7)"); println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem8)"); + println!("cargo:rustc-check-cfg=cfg(soc_mcpwm_swsync_can_propagate)"); + println!("cargo:rustc-check-cfg=cfg(soc_mcpwm_capture_clk_from_group)"); println!("cargo:rustc-check-cfg=cfg(ieee802154_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(lp_i2c_master_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(parl_io_driver_supported)"); diff --git a/esp-metadata/devices/esp32c5.toml b/esp-metadata/devices/esp32c5.toml index 9dd8fac6b94..9c7f964e559 100644 --- a/esp-metadata/devices/esp32c5.toml +++ b/esp-metadata/devices/esp32c5.toml @@ -17,7 +17,8 @@ symbols = [ # "lp_core", # MCPWM capabilites - "soc_has_mcpwm_capture_clk_from_group", + "soc_mcpwm_swsync_can_propagate", + "soc_mcpwm_capture_clk_from_group", # ROM capabilities "rom_crc_le", diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 8d67c0cc9c6..1e256430122 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -24,7 +24,8 @@ symbols = [ "rom_md5_bsd", # MCPWM capabilites - "soc_has_mcpwm_capture_clk_from_group", + "soc_mcpwm_swsync_can_propagate", + "soc_mcpwm_capture_clk_from_group", # Wakeup SOC based on ESP-IDF: "pm_support_wifi_wakeup", diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index 9180c3cbb61..a6cf908e0d9 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -18,7 +18,8 @@ symbols = [ "swd", # MCPWM capabilites - "soc_has_mcpwm_capture_clk_from_group", + "soc_mcpwm_swsync_can_propagate", + "soc_mcpwm_capture_clk_from_group", # ROM capabilities "rom_crc_le", diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index a1532c72b57..e8523ef91a1 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -6,11 +6,11 @@ # update the table in the esp-hal README. [device] -name = "esp32s3" -arch = "xtensa" +name = "esp32s3" +arch = "xtensa" target = "xtensa-esp32s3-none-elf" -cores = 2 -trm = "https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf" +cores = 2 +trm = "https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf" symbols = [ # Additional peripherals defined by us (the developers): @@ -21,6 +21,9 @@ symbols = [ "swd", "ulp_riscv_core", + # MCPWM capabilities + "soc_mcpwm_swsync_can_propagate", + # ROM capabilities "rom_crc_le", "rom_crc_be", @@ -122,34 +125,45 @@ peripherals = [ clocks = { system_clocks = { clock_tree = [ # High-speed clock sources - { name = "XTAL_CLK", type = "source", values = "40", output = "VALUE * 1_000_000", always_on = true }, - { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", values = "320, 480", output = "VALUE * 1_000_000", reject = "VALUE == 320_000_000 && CPU_PLL_DIV_OUT == 240_000_000" }, - { name = "RC_FAST_CLK", type = "source", output = "17_500_000" }, + { name = "XTAL_CLK", type = "source", values = "40", output = "VALUE * 1_000_000", always_on = true }, + { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", values = "320, 480", output = "VALUE * 1_000_000", reject = "VALUE == 320_000_000 && CPU_PLL_DIV_OUT == 240_000_000" }, + { name = "RC_FAST_CLK", type = "source", output = "17_500_000" }, # Low-speed clocks - { name = "XTAL32K_CLK", type = "source", output = "32768" }, - { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, { name = "RC_FAST_DIV_CLK", type = "generic", output = "RC_FAST_CLK / 256" }, # CPU clock source dividers { name = "SYSTEM_PRE_DIV_IN", type = "mux", variants = [ - { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, { name = "RC_FAST", outputs = "RC_FAST_CLK" }, ] }, - { name = "SYSTEM_PRE_DIV", type = "generic", params = { divisor = "0 .. 1024" }, output = "SYSTEM_PRE_DIV_IN / (divisor + 1)" }, + { name = "SYSTEM_PRE_DIV", type = "generic", params = { divisor = "0 .. 1024" }, output = "SYSTEM_PRE_DIV_IN / (divisor + 1)" }, # PLL CLK divider, modeled as a generic derived source because valid divider values depend on the PLL frequency { name = "CPU_PLL_DIV_OUT", type = "derived", from = "PLL_CLK", values = "80, 160, 240", output = "VALUE * 1_000_000", reject = "VALUE == 240_000_000 && PLL_CLK == 320_000_000" }, # The meta-switch { name = "CPU_CLK", type = "mux", always_on = true, variants = [ # source clock CPU clock additional config (mux = variant name, divider = divisor expression) - { name = "XTAL", outputs = "SYSTEM_PRE_DIV", configures = [ "APB_CLK = CPU", "CRYPTO_PWM_CLK = CPU", "SYSTEM_PRE_DIV_IN = XTAL" ] }, - { name = "RC_FAST", outputs = "SYSTEM_PRE_DIV", configures = [ "APB_CLK = CPU", "CRYPTO_PWM_CLK = CPU", "SYSTEM_PRE_DIV_IN = RC_FAST" ] }, - { name = "PLL", outputs = "CPU_PLL_DIV_OUT", configures = [ "APB_CLK = PLL", "CRYPTO_PWM_CLK = PLL" ] }, + { name = "XTAL", outputs = "SYSTEM_PRE_DIV", configures = [ + "APB_CLK = CPU", + "CRYPTO_PWM_CLK = CPU", + "SYSTEM_PRE_DIV_IN = XTAL", + ] }, + { name = "RC_FAST", outputs = "SYSTEM_PRE_DIV", configures = [ + "APB_CLK = CPU", + "CRYPTO_PWM_CLK = CPU", + "SYSTEM_PRE_DIV_IN = RC_FAST", + ] }, + { name = "PLL", outputs = "CPU_PLL_DIV_OUT", configures = [ + "APB_CLK = PLL", + "CRYPTO_PWM_CLK = PLL", + ] }, ] }, # CPU-dependent clock signals - { name = "PLL_D2", type = "generic", output = "PLL_CLK / 2" }, + { name = "PLL_D2", type = "generic", output = "PLL_CLK / 2" }, { name = "PLL_160M", type = "derived", from = "CPU_CLK", output = "160_000_000" }, { name = "APB_80M", type = "derived", from = "CPU_CLK", output = "80_000_000" }, @@ -159,12 +173,12 @@ clocks = { system_clocks = { clock_tree = [ ] }, { name = "CRYPTO_PWM_CLK", type = "mux", variants = [ { name = "PLL", outputs = "PLL_160M" }, - { name = "CPU", outputs = "CPU_CLK" }, + { name = "CPU", outputs = "CPU_CLK" }, ] }, # Low-power clocks { name = "RC_FAST_CLK_DIV_N", type = "generic", params = { divisor = "0 ..= 3" }, output = "RC_FAST_CLK / (divisor + 1)" }, - { name = "XTAL_DIV_CLK", type = "generic", output = "XTAL_CLK / 2" }, + { name = "XTAL_DIV_CLK", type = "generic", output = "XTAL_CLK / 2" }, { name = "RTC_SLOW_CLK", type = "mux", variants = [ { name = "XTAL32K", outputs = "XTAL32K_CLK" }, { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, @@ -172,14 +186,14 @@ clocks = { system_clocks = { clock_tree = [ ] }, { name = "RTC_FAST_CLK", type = "mux", variants = [ { name = "XTAL", outputs = "XTAL_DIV_CLK" }, - { name = "RC", outputs = "RC_FAST_CLK_DIV_N" }, + { name = "RC", outputs = "RC_FAST_CLK_DIV_N" }, ] }, # Low-power wireless clock source { name = "LOW_POWER_CLK", type = "mux", variants = [ - { name = "XTAL", outputs = "XTAL_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, - { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, { name = "RTC_SLOW", outputs = "RTC_SLOW_CLK" }, ] }, @@ -192,34 +206,34 @@ clocks = { system_clocks = { clock_tree = [ # There are separate clock muxes for each TIMG instance, but esp-hal only uses one. Only modelling # one makes the HAL code simpler. { name = "TIMG_CALIBRATION_CLOCK", type = "mux", variants = [ - { name = "RC_SLOW_CLK", outputs = "RC_SLOW_CLK" }, + { name = "RC_SLOW_CLK", outputs = "RC_SLOW_CLK" }, { name = "RC_FAST_DIV_CLK", outputs = "RC_FAST_DIV_CLK" }, - { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, + { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, ] }, ], template_groups = [ { group = "MCPWM", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "CRYPTO_PWM_CLK", outputs = "CRYPTO_PWM_CLK", default = true } - ] } + { name = "CRYPTO_PWM_CLK", outputs = "CRYPTO_PWM_CLK", default = true }, + ] }, ] }, { group = "TIMG", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, - { name = "APB_CLK", outputs = "APB_CLK" }, + { name = "APB_CLK", outputs = "APB_CLK" }, ] }, ] }, { group = "RMT", clocks = [ { name = "SCLK", type = "mux", variants = [ - { name = "APB_CLK", outputs = "APB_CLK", default = true }, + { name = "APB_CLK", outputs = "APB_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, ] }, { group = "UART", clocks = [ { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ - { name = "APB", outputs = "APB_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "APB", outputs = "APB_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK", default = true }, ], div_num = "0 .. 0x100" } }, { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, { name = "MEM_CLOCK", type = "generic", output = "UART_MEM_CLK" }, @@ -252,7 +266,7 @@ clocks = { system_clocks = { clock_tree = [ #{ name = "Adc2Arb" }, { name = "Systimer", keep_enabled = true }, { name = "ApbSarAdc", template_params = { peripheral = "apb_saradc" } }, - { name = "UartMem", keep_enabled = true }, # TODO: keep_enabled can be removed once esp-println needs explicit initialization + { name = "UartMem", keep_enabled = true }, # TODO: keep_enabled can be removed once esp-println needs explicit initialization { name = "Usb" }, { name = "I2s1" }, { name = "Mcpwm1", template_params = { peripheral = "pwm1" } }, @@ -273,16 +287,13 @@ clocks = { system_clocks = { clock_tree = [ { name = "Uart0", template_params = { peripheral = "uart" }, keep_enabled = true }, #{ name = "Spi01" }, #{ name = "Timers" }, - + # Radio clocks not modeled here. ] } } [device.adc] support_status = "partial" -instances = [ - { name = "adc1" }, - { name = "adc2" }, -] +instances = [{ name = "adc1" }, { name = "adc2" }] [device.aes] support_status = "partial" @@ -292,7 +303,7 @@ dma = true dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"] key_length = { options = [ { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, - { bits = 256, encrypt_mode = 2, decrypt_mode = 6 } + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, ] } [device.assist_debug] @@ -314,228 +325,270 @@ gpio_function = 1 constant_0_input = 0x3c constant_1_input = 0x38 pins = [ - { pin = 0, rtc = { 0 = "RTC_GPIO0", 1 = "SAR_I2C_SCL_0" }, limitations = ["strapping"] }, - { pin = 1, analog = { 0 = "TOUCH1", 1 = "ADC1_CH0" }, rtc = { 0 = "RTC_GPIO1", 1 = "SAR_I2C_SDA_0" } }, - { pin = 2, analog = { 0 = "TOUCH2", 1 = "ADC1_CH1" }, rtc = { 0 = "RTC_GPIO2", 1 = "SAR_I2C_SCL_1" } }, - { pin = 3, analog = { 0 = "TOUCH3", 1 = "ADC1_CH2" }, rtc = { 0 = "RTC_GPIO3", 1 = "SAR_I2C_SDA_1" }, limitations = ["strapping"] }, - { pin = 4, analog = { 0 = "TOUCH4", 1 = "ADC1_CH3" }, rtc = { 0 = "RTC_GPIO4" } }, - { pin = 5, analog = { 0 = "TOUCH5", 1 = "ADC1_CH4" }, rtc = { 0 = "RTC_GPIO5" } }, - { pin = 6, analog = { 0 = "TOUCH6", 1 = "ADC1_CH5" }, rtc = { 0 = "RTC_GPIO6" } }, - { pin = 7, analog = { 0 = "TOUCH7", 1 = "ADC1_CH6" }, rtc = { 0 = "RTC_GPIO7" } }, - { pin = 8, functions = { 3 = "SUBSPICS1" }, analog = { 0 = "TOUCH8", 1 = "ADC1_CH7" }, rtc = { 0 = "RTC_GPIO8" } }, - { pin = 9, functions = { 3 = "SUBSPIHD", 4 = "FSPIHD" }, analog = { 0 = "TOUCH9", 1 = "ADC1_CH8" }, rtc = { 0 = "RTC_GPIO9" } }, - { pin = 10, functions = { 2 = "FSPIIO4", 3 = "SUBSPICS0", 4 = "FSPICS0" }, analog = { 0 = "TOUCH10", 1 = "ADC1_CH9" }, rtc = { 0 = "RTC_GPIO10" } }, - { pin = 11, functions = { 2 = "FSPIIO5", 3 = "SUBSPID", 4 = "FSPID" }, analog = { 0 = "TOUCH11", 1 = "ADC2_CH0" }, rtc = { 0 = "RTC_GPIO11" } }, - { pin = 12, functions = { 2 = "FSPIIO6", 3 = "SUBSPICLK", 4 = "FSPICLK" }, analog = { 0 = "TOUCH12", 1 = "ADC2_CH1" }, rtc = { 0 = "RTC_GPIO12" } }, - { pin = 13, functions = { 2 = "FSPIIO7", 3 = "SUBSPIQ", 4 = "FSPIQ" }, analog = { 0 = "TOUCH13", 1 = "ADC2_CH2" }, rtc = { 0 = "RTC_GPIO13" } }, - { pin = 14, functions = { 2 = "FSPIDQS", 3 = "SUBSPIWP", 4 = "FSPIWP" }, analog = { 0 = "TOUCH14", 1 = "ADC2_CH3" }, rtc = { 0 = "RTC_GPIO14" } }, - { pin = 15, functions = { 2 = "U0RTS" }, analog = { 0 = "XTAL_32K_P", 1 = "ADC2_CH4" }, rtc = { 0 = "RTC_GPIO15" } }, - { pin = 16, functions = { 2 = "U0CTS" }, analog = { 0 = "XTAL_32K_N", 1 = "ADC2_CH5" }, rtc = { 0 = "RTC_GPIO16" } }, - { pin = 17, functions = { 2 = "U1TXD" }, analog = { 1 = "ADC2_CH6" }, rtc = { 0 = "RTC_GPIO17" } }, - { pin = 18, functions = { 2 = "U1RXD", 3 = "CLK_OUT3" }, analog = { 1 = "ADC2_CH7" }, rtc = { 0 = "RTC_GPIO18" } }, - { pin = 19, functions = { 2 = "U1RTS", 3 = "CLK_OUT2" }, analog = { 0 = "USB_DM", 1 = "ADC2_CH8" }, rtc = { 0 = "RTC_GPIO19" } }, - { pin = 20, functions = { 2 = "U1CTS", 3 = "CLK_OUT1" }, analog = { 0 = "USB_DP", 1 = "ADC2_CH9" }, rtc = { 0 = "RTC_GPIO20" } }, - { pin = 21, rtc = { 0 = "RTC_GPIO21" } }, - - { pin = 26, functions = { 0 = "SPICS1" }, limitations = ["spi_psram"] }, - { pin = 27, functions = { 0 = "SPIHD" }, limitations = ["spi_flash", "spi_psram"] }, - { pin = 28, functions = { 0 = "SPIWP" }, limitations = ["spi_flash", "spi_psram"] }, - { pin = 29, functions = { 0 = "SPICS0" }, limitations = ["spi_flash", "spi_psram"] }, - { pin = 30, functions = { 0 = "SPICLK" }, limitations = ["spi_flash", "spi_psram"] }, - { pin = 31, functions = { 0 = "SPIQ" }, limitations = ["spi_flash", "spi_psram"] }, - { pin = 32, functions = { 0 = "SPID" }, limitations = ["spi_flash"] }, - { pin = 33, functions = { 2 = "FSPIHD", 3 = "SUBSPIHD", 4 = "SPIIO4" }, limitations = ["octal_flash", "octal_psram"] }, - { pin = 34, functions = { 2 = "FSPICS0", 3 = "SUBSPICS0", 4 = "SPIIO5" }, limitations = ["octal_flash", "octal_psram"] }, - { pin = 35, functions = { 2 = "FSPID", 3 = "SUBSPID", 4 = "SPIIO6" }, limitations = ["octal_flash", "octal_psram"] }, - { pin = 36, functions = { 2 = "FSPICLK", 3 = "SUBSPICLK", 4 = "SPIIO7" }, limitations = ["octal_flash", "octal_psram"] }, - { pin = 37, functions = { 2 = "FSPIQ", 3 = "SUBSPIQ", 4 = "SPIDQS" }, limitations = ["octal_flash", "octal_psram"] }, - { pin = 38, functions = { 2 = "FSPIWP", 3 = "SUBSPIWP" } }, - { pin = 39, functions = { 0 = "MTCK", 2 = "CLK_OUT3", 3 = "SUBSPICS1" } }, + { pin = 0, rtc = { 0 = "RTC_GPIO0", 1 = "SAR_I2C_SCL_0" }, limitations = [ + "strapping", + ] }, + { pin = 1, analog = { 0 = "TOUCH1", 1 = "ADC1_CH0" }, rtc = { 0 = "RTC_GPIO1", 1 = "SAR_I2C_SDA_0" } }, + { pin = 2, analog = { 0 = "TOUCH2", 1 = "ADC1_CH1" }, rtc = { 0 = "RTC_GPIO2", 1 = "SAR_I2C_SCL_1" } }, + { pin = 3, analog = { 0 = "TOUCH3", 1 = "ADC1_CH2" }, rtc = { 0 = "RTC_GPIO3", 1 = "SAR_I2C_SDA_1" }, limitations = [ + "strapping", + ] }, + { pin = 4, analog = { 0 = "TOUCH4", 1 = "ADC1_CH3" }, rtc = { 0 = "RTC_GPIO4" } }, + { pin = 5, analog = { 0 = "TOUCH5", 1 = "ADC1_CH4" }, rtc = { 0 = "RTC_GPIO5" } }, + { pin = 6, analog = { 0 = "TOUCH6", 1 = "ADC1_CH5" }, rtc = { 0 = "RTC_GPIO6" } }, + { pin = 7, analog = { 0 = "TOUCH7", 1 = "ADC1_CH6" }, rtc = { 0 = "RTC_GPIO7" } }, + { pin = 8, functions = { 3 = "SUBSPICS1" }, analog = { 0 = "TOUCH8", 1 = "ADC1_CH7" }, rtc = { 0 = "RTC_GPIO8" } }, + { pin = 9, functions = { 3 = "SUBSPIHD", 4 = "FSPIHD" }, analog = { 0 = "TOUCH9", 1 = "ADC1_CH8" }, rtc = { 0 = "RTC_GPIO9" } }, + { pin = 10, functions = { 2 = "FSPIIO4", 3 = "SUBSPICS0", 4 = "FSPICS0" }, analog = { 0 = "TOUCH10", 1 = "ADC1_CH9" }, rtc = { 0 = "RTC_GPIO10" } }, + { pin = 11, functions = { 2 = "FSPIIO5", 3 = "SUBSPID", 4 = "FSPID" }, analog = { 0 = "TOUCH11", 1 = "ADC2_CH0" }, rtc = { 0 = "RTC_GPIO11" } }, + { pin = 12, functions = { 2 = "FSPIIO6", 3 = "SUBSPICLK", 4 = "FSPICLK" }, analog = { 0 = "TOUCH12", 1 = "ADC2_CH1" }, rtc = { 0 = "RTC_GPIO12" } }, + { pin = 13, functions = { 2 = "FSPIIO7", 3 = "SUBSPIQ", 4 = "FSPIQ" }, analog = { 0 = "TOUCH13", 1 = "ADC2_CH2" }, rtc = { 0 = "RTC_GPIO13" } }, + { pin = 14, functions = { 2 = "FSPIDQS", 3 = "SUBSPIWP", 4 = "FSPIWP" }, analog = { 0 = "TOUCH14", 1 = "ADC2_CH3" }, rtc = { 0 = "RTC_GPIO14" } }, + { pin = 15, functions = { 2 = "U0RTS" }, analog = { 0 = "XTAL_32K_P", 1 = "ADC2_CH4" }, rtc = { 0 = "RTC_GPIO15" } }, + { pin = 16, functions = { 2 = "U0CTS" }, analog = { 0 = "XTAL_32K_N", 1 = "ADC2_CH5" }, rtc = { 0 = "RTC_GPIO16" } }, + { pin = 17, functions = { 2 = "U1TXD" }, analog = { 1 = "ADC2_CH6" }, rtc = { 0 = "RTC_GPIO17" } }, + { pin = 18, functions = { 2 = "U1RXD", 3 = "CLK_OUT3" }, analog = { 1 = "ADC2_CH7" }, rtc = { 0 = "RTC_GPIO18" } }, + { pin = 19, functions = { 2 = "U1RTS", 3 = "CLK_OUT2" }, analog = { 0 = "USB_DM", 1 = "ADC2_CH8" }, rtc = { 0 = "RTC_GPIO19" } }, + { pin = 20, functions = { 2 = "U1CTS", 3 = "CLK_OUT1" }, analog = { 0 = "USB_DP", 1 = "ADC2_CH9" }, rtc = { 0 = "RTC_GPIO20" } }, + { pin = 21, rtc = { 0 = "RTC_GPIO21" } }, + + { pin = 26, functions = { 0 = "SPICS1" }, limitations = [ + "spi_psram", + ] }, + { pin = 27, functions = { 0 = "SPIHD" }, limitations = [ + "spi_flash", + "spi_psram", + ] }, + { pin = 28, functions = { 0 = "SPIWP" }, limitations = [ + "spi_flash", + "spi_psram", + ] }, + { pin = 29, functions = { 0 = "SPICS0" }, limitations = [ + "spi_flash", + "spi_psram", + ] }, + { pin = 30, functions = { 0 = "SPICLK" }, limitations = [ + "spi_flash", + "spi_psram", + ] }, + { pin = 31, functions = { 0 = "SPIQ" }, limitations = [ + "spi_flash", + "spi_psram", + ] }, + { pin = 32, functions = { 0 = "SPID" }, limitations = [ + "spi_flash", + ] }, + { pin = 33, functions = { 2 = "FSPIHD", 3 = "SUBSPIHD", 4 = "SPIIO4" }, limitations = [ + "octal_flash", + "octal_psram", + ] }, + { pin = 34, functions = { 2 = "FSPICS0", 3 = "SUBSPICS0", 4 = "SPIIO5" }, limitations = [ + "octal_flash", + "octal_psram", + ] }, + { pin = 35, functions = { 2 = "FSPID", 3 = "SUBSPID", 4 = "SPIIO6" }, limitations = [ + "octal_flash", + "octal_psram", + ] }, + { pin = 36, functions = { 2 = "FSPICLK", 3 = "SUBSPICLK", 4 = "SPIIO7" }, limitations = [ + "octal_flash", + "octal_psram", + ] }, + { pin = 37, functions = { 2 = "FSPIQ", 3 = "SUBSPIQ", 4 = "SPIDQS" }, limitations = [ + "octal_flash", + "octal_psram", + ] }, + { pin = 38, functions = { 2 = "FSPIWP", 3 = "SUBSPIWP" } }, + { pin = 39, functions = { 0 = "MTCK", 2 = "CLK_OUT3", 3 = "SUBSPICS1" } }, { pin = 40, functions = { 0 = "MTDO", 2 = "CLK_OUT2" } }, { pin = 41, functions = { 0 = "MTDI", 2 = "CLK_OUT1" } }, { pin = 42, functions = { 0 = "MTMS" } }, { pin = 43, functions = { 0 = "U0TXD", 2 = "CLK_OUT1" } }, { pin = 44, functions = { 0 = "U0RXD", 2 = "CLK_OUT2" } }, - { pin = 45, limitations = ["strapping"] }, - { pin = 46, limitations = ["strapping"] }, + { pin = 45, limitations = [ + "strapping", + ] }, + { pin = 46, limitations = [ + "strapping", + ] }, { pin = 47, functions = { 0 = "SPICLK_P_DIFF", 2 = "SUBSPICLK_P_DIFF" } }, { pin = 48, functions = { 0 = "SPICLK_N_DIFF", 2 = "SUBSPICLK_N_DIFF" } }, ] input_signals = [ - { name = "SPIQ", id = 0 }, - { name = "SPID", id = 1 }, - { name = "SPIHD", id = 2 }, - { name = "SPIWP", id = 3 }, - { name = "SPID4", id = 7 }, - { name = "SPID5", id = 8 }, - { name = "SPID6", id = 9 }, - { name = "SPID7", id = 10 }, - { name = "SPIDQS", id = 11 }, - { name = "U0RXD", id = 12 }, - { name = "U0CTS", id = 13 }, - { name = "U0DSR", id = 14 }, - { name = "U1RXD", id = 15 }, - { name = "U1CTS", id = 16 }, - { name = "U1DSR", id = 17 }, - { name = "U2RXD", id = 18 }, - { name = "U2CTS", id = 19 }, - { name = "U2DSR", id = 20 }, - { name = "I2S1_MCLK", id = 21 }, - { name = "I2S0O_BCK", id = 22 }, - { name = "I2S0_MCLK", id = 23 }, - { name = "I2S0O_WS", id = 24 }, - { name = "I2S0I_SD", id = 25 }, - { name = "I2S0I_BCK", id = 26 }, - { name = "I2S0I_WS", id = 27 }, - { name = "I2S1O_BCK", id = 28 }, - { name = "I2S1O_WS", id = 29 }, - { name = "I2S1I_SD", id = 30 }, - { name = "I2S1I_BCK", id = 31 }, - { name = "I2S1I_WS", id = 32 }, - { name = "PCNT0_SIG_CH0", id = 33 }, - { name = "PCNT0_SIG_CH1", id = 34 }, - { name = "PCNT0_CTRL_CH0", id = 35 }, - { name = "PCNT0_CTRL_CH1", id = 36 }, - { name = "PCNT1_SIG_CH0", id = 37 }, - { name = "PCNT1_SIG_CH1", id = 38 }, - { name = "PCNT1_CTRL_CH0", id = 39 }, - { name = "PCNT1_CTRL_CH1", id = 40 }, - { name = "PCNT2_SIG_CH0", id = 41 }, - { name = "PCNT2_SIG_CH1", id = 42 }, - { name = "PCNT2_CTRL_CH0", id = 43 }, - { name = "PCNT2_CTRL_CH1", id = 44 }, - { name = "PCNT3_SIG_CH0", id = 45 }, - { name = "PCNT3_SIG_CH1", id = 46 }, - { name = "PCNT3_CTRL_CH0", id = 47 }, - { name = "PCNT3_CTRL_CH1", id = 48 }, - { name = "I2S0I_SD1", id = 51 }, - { name = "I2S0I_SD2", id = 52 }, - { name = "I2S0I_SD3", id = 53 }, - { name = "CORE1_GPIO7", id = 54 }, - { name = "USB_EXTPHY_VP", id = 55 }, - { name = "USB_EXTPHY_VM", id = 56 }, - { name = "USB_EXTPHY_RCV", id = 57 }, - { name = "USB_OTG_IDDIG", id = 58 }, - { name = "USB_OTG_AVALID", id = 59 }, - { name = "USB_SRP_BVALID", id = 60 }, - { name = "USB_OTG_VBUSVALID", id = 61 }, - { name = "USB_SRP_SESSEND", id = 62 }, - { name = "SPI3_CLK", id = 66 }, - { name = "SPI3_Q", id = 67 }, - { name = "SPI3_D", id = 68 }, - { name = "SPI3_HD", id = 69 }, - { name = "SPI3_WP", id = 70 }, - { name = "SPI3_CS0", id = 71 }, - { name = "RMT_SIG_0", id = 81 }, - { name = "RMT_SIG_1", id = 82 }, - { name = "RMT_SIG_2", id = 83 }, - { name = "RMT_SIG_3", id = 84 }, - { name = "I2CEXT0_SCL", id = 89 }, - { name = "I2CEXT0_SDA", id = 90 }, - { name = "I2CEXT1_SCL", id = 91 }, - { name = "I2CEXT1_SDA", id = 92 }, - { name = "FSPICLK", id = 101 }, - { name = "FSPIQ", id = 102 }, - { name = "FSPID", id = 103 }, - { name = "FSPIHD", id = 104 }, - { name = "FSPIWP", id = 105 }, - { name = "FSPIIO4", id = 106 }, - { name = "FSPIIO5", id = 107 }, - { name = "FSPIIO6", id = 108 }, - { name = "FSPIIO7", id = 109 }, - { name = "FSPICS0", id = 110 }, - { name = "TWAI_RX", id = 116 }, - { name = "SUBSPIQ", id = 120 }, - { name = "SUBSPID", id = 121 }, - { name = "SUBSPIHD", id = 122 }, - { name = "SUBSPIWP", id = 123 }, - { name = "CORE1_GPIO0", id = 129 }, - { name = "CORE1_GPIO1", id = 130 }, - { name = "CORE1_GPIO2", id = 131 }, - { name = "CAM_DATA_0", id = 133 }, - { name = "CAM_DATA_1", id = 134 }, - { name = "CAM_DATA_2", id = 135 }, - { name = "CAM_DATA_3", id = 136 }, - { name = "CAM_DATA_4", id = 137 }, - { name = "CAM_DATA_5", id = 138 }, - { name = "CAM_DATA_6", id = 139 }, - { name = "CAM_DATA_7", id = 140 }, - { name = "CAM_DATA_8", id = 141 }, - { name = "CAM_DATA_9", id = 142 }, - { name = "CAM_DATA_10", id = 143 }, - { name = "CAM_DATA_11", id = 144 }, - { name = "CAM_DATA_12", id = 145 }, - { name = "CAM_DATA_13", id = 146 }, - { name = "CAM_DATA_14", id = 147 }, - { name = "CAM_DATA_15", id = 148 }, - { name = "CAM_PCLK", id = 149 }, - { name = "CAM_H_ENABLE", id = 150 }, - { name = "CAM_H_SYNC", id = 151 }, - { name = "CAM_V_SYNC", id = 152 }, - { name = "SUBSPID4", id = 155 }, - { name = "SUBSPID5", id = 156 }, - { name = "SUBSPID6", id = 157 }, - { name = "SUBSPID7", id = 158 }, - { name = "SUBSPIDQS", id = 159 }, - { name = "PWM0_SYNC0", id = 160 }, - { name = "PWM0_SYNC1", id = 161 }, - { name = "PWM0_SYNC2", id = 162 }, - { name = "PWM0_F0", id = 163 }, - { name = "PWM0_F1", id = 164 }, - { name = "PWM0_F2", id = 165 }, - { name = "PWM0_CAP0", id = 166 }, - { name = "PWM0_CAP1", id = 167 }, - { name = "PWM0_CAP2", id = 168 }, - { name = "PWM1_SYNC0", id = 169 }, - { name = "PWM1_SYNC1", id = 170 }, - { name = "PWM1_SYNC2", id = 171 }, - { name = "PWM1_F0", id = 172 }, - { name = "PWM1_F1", id = 173 }, - { name = "PWM1_F2", id = 174 }, - { name = "PWM1_CAP0", id = 175 }, - { name = "PWM1_CAP1", id = 176 }, - { name = "PWM1_CAP2", id = 177 }, - { name = "SDHOST_CCMD_IN_1", id = 178 }, - { name = "SDHOST_CCMD_IN_2", id = 179 }, - { name = "SDHOST_CDATA_IN_10", id = 180 }, - { name = "SDHOST_CDATA_IN_11", id = 181 }, - { name = "SDHOST_CDATA_IN_12", id = 182 }, - { name = "SDHOST_CDATA_IN_13", id = 183 }, - { name = "SDHOST_CDATA_IN_14", id = 184 }, - { name = "SDHOST_CDATA_IN_15", id = 185 }, - { name = "SDHOST_CDATA_IN_16", id = 186 }, - { name = "SDHOST_CDATA_IN_17", id = 187 }, - { name = "SDHOST_DATA_STROBE_1", id = 192 }, - { name = "SDHOST_DATA_STROBE_2", id = 193 }, - { name = "SDHOST_CARD_DETECT_N_1", id = 194 }, - { name = "SDHOST_CARD_DETECT_N_2", id = 195 }, + { name = "SPIQ", id = 0 }, + { name = "SPID", id = 1 }, + { name = "SPIHD", id = 2 }, + { name = "SPIWP", id = 3 }, + { name = "SPID4", id = 7 }, + { name = "SPID5", id = 8 }, + { name = "SPID6", id = 9 }, + { name = "SPID7", id = 10 }, + { name = "SPIDQS", id = 11 }, + { name = "U0RXD", id = 12 }, + { name = "U0CTS", id = 13 }, + { name = "U0DSR", id = 14 }, + { name = "U1RXD", id = 15 }, + { name = "U1CTS", id = 16 }, + { name = "U1DSR", id = 17 }, + { name = "U2RXD", id = 18 }, + { name = "U2CTS", id = 19 }, + { name = "U2DSR", id = 20 }, + { name = "I2S1_MCLK", id = 21 }, + { name = "I2S0O_BCK", id = 22 }, + { name = "I2S0_MCLK", id = 23 }, + { name = "I2S0O_WS", id = 24 }, + { name = "I2S0I_SD", id = 25 }, + { name = "I2S0I_BCK", id = 26 }, + { name = "I2S0I_WS", id = 27 }, + { name = "I2S1O_BCK", id = 28 }, + { name = "I2S1O_WS", id = 29 }, + { name = "I2S1I_SD", id = 30 }, + { name = "I2S1I_BCK", id = 31 }, + { name = "I2S1I_WS", id = 32 }, + { name = "PCNT0_SIG_CH0", id = 33 }, + { name = "PCNT0_SIG_CH1", id = 34 }, + { name = "PCNT0_CTRL_CH0", id = 35 }, + { name = "PCNT0_CTRL_CH1", id = 36 }, + { name = "PCNT1_SIG_CH0", id = 37 }, + { name = "PCNT1_SIG_CH1", id = 38 }, + { name = "PCNT1_CTRL_CH0", id = 39 }, + { name = "PCNT1_CTRL_CH1", id = 40 }, + { name = "PCNT2_SIG_CH0", id = 41 }, + { name = "PCNT2_SIG_CH1", id = 42 }, + { name = "PCNT2_CTRL_CH0", id = 43 }, + { name = "PCNT2_CTRL_CH1", id = 44 }, + { name = "PCNT3_SIG_CH0", id = 45 }, + { name = "PCNT3_SIG_CH1", id = 46 }, + { name = "PCNT3_CTRL_CH0", id = 47 }, + { name = "PCNT3_CTRL_CH1", id = 48 }, + { name = "I2S0I_SD1", id = 51 }, + { name = "I2S0I_SD2", id = 52 }, + { name = "I2S0I_SD3", id = 53 }, + { name = "CORE1_GPIO7", id = 54 }, + { name = "USB_EXTPHY_VP", id = 55 }, + { name = "USB_EXTPHY_VM", id = 56 }, + { name = "USB_EXTPHY_RCV", id = 57 }, + { name = "USB_OTG_IDDIG", id = 58 }, + { name = "USB_OTG_AVALID", id = 59 }, + { name = "USB_SRP_BVALID", id = 60 }, + { name = "USB_OTG_VBUSVALID", id = 61 }, + { name = "USB_SRP_SESSEND", id = 62 }, + { name = "SPI3_CLK", id = 66 }, + { name = "SPI3_Q", id = 67 }, + { name = "SPI3_D", id = 68 }, + { name = "SPI3_HD", id = 69 }, + { name = "SPI3_WP", id = 70 }, + { name = "SPI3_CS0", id = 71 }, + { name = "RMT_SIG_0", id = 81 }, + { name = "RMT_SIG_1", id = 82 }, + { name = "RMT_SIG_2", id = 83 }, + { name = "RMT_SIG_3", id = 84 }, + { name = "I2CEXT0_SCL", id = 89 }, + { name = "I2CEXT0_SDA", id = 90 }, + { name = "I2CEXT1_SCL", id = 91 }, + { name = "I2CEXT1_SDA", id = 92 }, + { name = "FSPICLK", id = 101 }, + { name = "FSPIQ", id = 102 }, + { name = "FSPID", id = 103 }, + { name = "FSPIHD", id = 104 }, + { name = "FSPIWP", id = 105 }, + { name = "FSPIIO4", id = 106 }, + { name = "FSPIIO5", id = 107 }, + { name = "FSPIIO6", id = 108 }, + { name = "FSPIIO7", id = 109 }, + { name = "FSPICS0", id = 110 }, + { name = "TWAI_RX", id = 116 }, + { name = "SUBSPIQ", id = 120 }, + { name = "SUBSPID", id = 121 }, + { name = "SUBSPIHD", id = 122 }, + { name = "SUBSPIWP", id = 123 }, + { name = "CORE1_GPIO0", id = 129 }, + { name = "CORE1_GPIO1", id = 130 }, + { name = "CORE1_GPIO2", id = 131 }, + { name = "CAM_DATA_0", id = 133 }, + { name = "CAM_DATA_1", id = 134 }, + { name = "CAM_DATA_2", id = 135 }, + { name = "CAM_DATA_3", id = 136 }, + { name = "CAM_DATA_4", id = 137 }, + { name = "CAM_DATA_5", id = 138 }, + { name = "CAM_DATA_6", id = 139 }, + { name = "CAM_DATA_7", id = 140 }, + { name = "CAM_DATA_8", id = 141 }, + { name = "CAM_DATA_9", id = 142 }, + { name = "CAM_DATA_10", id = 143 }, + { name = "CAM_DATA_11", id = 144 }, + { name = "CAM_DATA_12", id = 145 }, + { name = "CAM_DATA_13", id = 146 }, + { name = "CAM_DATA_14", id = 147 }, + { name = "CAM_DATA_15", id = 148 }, + { name = "CAM_PCLK", id = 149 }, + { name = "CAM_H_ENABLE", id = 150 }, + { name = "CAM_H_SYNC", id = 151 }, + { name = "CAM_V_SYNC", id = 152 }, + { name = "SUBSPID4", id = 155 }, + { name = "SUBSPID5", id = 156 }, + { name = "SUBSPID6", id = 157 }, + { name = "SUBSPID7", id = 158 }, + { name = "SUBSPIDQS", id = 159 }, + { name = "PWM0_SYNC0", id = 160 }, + { name = "PWM0_SYNC1", id = 161 }, + { name = "PWM0_SYNC2", id = 162 }, + { name = "PWM0_F0", id = 163 }, + { name = "PWM0_F1", id = 164 }, + { name = "PWM0_F2", id = 165 }, + { name = "PWM0_CAP0", id = 166 }, + { name = "PWM0_CAP1", id = 167 }, + { name = "PWM0_CAP2", id = 168 }, + { name = "PWM1_SYNC0", id = 169 }, + { name = "PWM1_SYNC1", id = 170 }, + { name = "PWM1_SYNC2", id = 171 }, + { name = "PWM1_F0", id = 172 }, + { name = "PWM1_F1", id = 173 }, + { name = "PWM1_F2", id = 174 }, + { name = "PWM1_CAP0", id = 175 }, + { name = "PWM1_CAP1", id = 176 }, + { name = "PWM1_CAP2", id = 177 }, + { name = "SDHOST_CCMD_IN_1", id = 178 }, + { name = "SDHOST_CCMD_IN_2", id = 179 }, + { name = "SDHOST_CDATA_IN_10", id = 180 }, + { name = "SDHOST_CDATA_IN_11", id = 181 }, + { name = "SDHOST_CDATA_IN_12", id = 182 }, + { name = "SDHOST_CDATA_IN_13", id = 183 }, + { name = "SDHOST_CDATA_IN_14", id = 184 }, + { name = "SDHOST_CDATA_IN_15", id = 185 }, + { name = "SDHOST_CDATA_IN_16", id = 186 }, + { name = "SDHOST_CDATA_IN_17", id = 187 }, + { name = "SDHOST_DATA_STROBE_1", id = 192 }, + { name = "SDHOST_DATA_STROBE_2", id = 193 }, + { name = "SDHOST_CARD_DETECT_N_1", id = 194 }, + { name = "SDHOST_CARD_DETECT_N_2", id = 195 }, { name = "SDHOST_CARD_WRITE_PRT_1", id = 196 }, { name = "SDHOST_CARD_WRITE_PRT_2", id = 197 }, - { name = "SDHOST_CARD_INT_N_1", id = 198 }, - { name = "SDHOST_CARD_INT_N_2", id = 199 }, - { name = "SDHOST_CDATA_IN_20", id = 213 }, - { name = "SDHOST_CDATA_IN_21", id = 214 }, - { name = "SDHOST_CDATA_IN_22", id = 215 }, - { name = "SDHOST_CDATA_IN_23", id = 216 }, - { name = "SDHOST_CDATA_IN_24", id = 217 }, - { name = "SDHOST_CDATA_IN_25", id = 218 }, - { name = "SDHOST_CDATA_IN_26", id = 219 }, - { name = "SDHOST_CDATA_IN_27", id = 220 }, - - { name = "PRO_ALONEGPIO0", id = 221 }, - { name = "PRO_ALONEGPIO1", id = 222 }, - { name = "PRO_ALONEGPIO2", id = 223 }, - { name = "PRO_ALONEGPIO3", id = 224 }, - { name = "PRO_ALONEGPIO4", id = 225 }, - { name = "PRO_ALONEGPIO5", id = 226 }, - { name = "PRO_ALONEGPIO6", id = 227 }, - { name = "PRO_ALONEGPIO7", id = 228 }, - - { name = "USB_JTAG_TDO_BRIDGE", id = 251 }, - { name = "CORE1_GPIO3", id = 252 }, - { name = "CORE1_GPIO4", id = 253 }, - { name = "CORE1_GPIO5", id = 254 }, - { name = "CORE1_GPIO6", id = 255 }, + { name = "SDHOST_CARD_INT_N_1", id = 198 }, + { name = "SDHOST_CARD_INT_N_2", id = 199 }, + { name = "SDHOST_CDATA_IN_20", id = 213 }, + { name = "SDHOST_CDATA_IN_21", id = 214 }, + { name = "SDHOST_CDATA_IN_22", id = 215 }, + { name = "SDHOST_CDATA_IN_23", id = 216 }, + { name = "SDHOST_CDATA_IN_24", id = 217 }, + { name = "SDHOST_CDATA_IN_25", id = 218 }, + { name = "SDHOST_CDATA_IN_26", id = 219 }, + { name = "SDHOST_CDATA_IN_27", id = 220 }, + + { name = "PRO_ALONEGPIO0", id = 221 }, + { name = "PRO_ALONEGPIO1", id = 222 }, + { name = "PRO_ALONEGPIO2", id = 223 }, + { name = "PRO_ALONEGPIO3", id = 224 }, + { name = "PRO_ALONEGPIO4", id = 225 }, + { name = "PRO_ALONEGPIO5", id = 226 }, + { name = "PRO_ALONEGPIO6", id = 227 }, + { name = "PRO_ALONEGPIO7", id = 228 }, + + { name = "USB_JTAG_TDO_BRIDGE", id = 251 }, + { name = "CORE1_GPIO3", id = 252 }, + { name = "CORE1_GPIO4", id = 253 }, + { name = "CORE1_GPIO5", id = 254 }, + { name = "CORE1_GPIO6", id = 255 }, { name = "SPIIO4" }, { name = "SPIIO5" }, @@ -547,184 +600,184 @@ input_signals = [ { name = "MTMS" }, ] output_signals = [ - { name = "SPIQ", id = 0 }, - { name = "SPID", id = 1 }, - { name = "SPIHD", id = 2 }, - { name = "SPIWP", id = 3 }, - { name = "SPICLK", id = 4 }, - { name = "SPICS0", id = 5 }, - { name = "SPICS1", id = 6 }, - { name = "SPID4", id = 7 }, - { name = "SPID5", id = 8 }, - { name = "SPID6", id = 9 }, - { name = "SPID7", id = 10 }, - { name = "SPIDQS", id = 11 }, - { name = "U0TXD", id = 12 }, - { name = "U0RTS", id = 13 }, - { name = "U0DTR", id = 14 }, - { name = "U1TXD", id = 15 }, - { name = "U1RTS", id = 16 }, - { name = "U1DTR", id = 17 }, - { name = "U2TXD", id = 18 }, - { name = "U2RTS", id = 19 }, - { name = "U2DTR", id = 20 }, - { name = "I2S1_MCLK", id = 21 }, - { name = "I2S0O_BCK", id = 22 }, - { name = "I2S0_MCLK", id = 23 }, - { name = "I2S0O_WS", id = 24 }, - { name = "I2S0O_SD", id = 25 }, - { name = "I2S0I_BCK", id = 26 }, - { name = "I2S0I_WS", id = 27 }, - { name = "I2S1O_BCK", id = 28 }, - { name = "I2S1O_WS", id = 29 }, - { name = "I2S1O_SD", id = 30 }, - { name = "I2S1I_BCK", id = 31 }, - { name = "I2S1I_WS", id = 32 }, - { name = "CORE1_GPIO7", id = 54 }, - { name = "USB_EXTPHY_OEN", id = 55 }, - { name = "USB_EXTPHY_VPO", id = 57 }, - { name = "USB_EXTPHY_VMO", id = 58 }, - { name = "SPI3_CLK", id = 66 }, - { name = "SPI3_Q", id = 67 }, - { name = "SPI3_D", id = 68 }, - { name = "SPI3_HD", id = 69 }, - { name = "SPI3_WP", id = 70 }, - { name = "SPI3_CS0", id = 71 }, - { name = "SPI3_CS1", id = 72 }, - { name = "LEDC_LS_SIG0", id = 73 }, - { name = "LEDC_LS_SIG1", id = 74 }, - { name = "LEDC_LS_SIG2", id = 75 }, - { name = "LEDC_LS_SIG3", id = 76 }, - { name = "LEDC_LS_SIG4", id = 77 }, - { name = "LEDC_LS_SIG5", id = 78 }, - { name = "LEDC_LS_SIG6", id = 79 }, - { name = "LEDC_LS_SIG7", id = 80 }, - { name = "RMT_SIG_0", id = 81 }, - { name = "RMT_SIG_1", id = 82 }, - { name = "RMT_SIG_2", id = 83 }, - { name = "RMT_SIG_3", id = 84 }, - { name = "I2CEXT0_SCL", id = 89 }, - { name = "I2CEXT0_SDA", id = 90 }, - { name = "I2CEXT1_SCL", id = 91 }, - { name = "I2CEXT1_SDA", id = 92 }, - { name = "GPIO_SD0", id = 93 }, - { name = "GPIO_SD1", id = 94 }, - { name = "GPIO_SD2", id = 95 }, - { name = "GPIO_SD3", id = 96 }, - { name = "GPIO_SD4", id = 97 }, - { name = "GPIO_SD5", id = 98 }, - { name = "GPIO_SD6", id = 99 }, - { name = "GPIO_SD7", id = 100 }, - { name = "FSPICLK", id = 101 }, - { name = "FSPIQ", id = 102 }, - { name = "FSPID", id = 103 }, - { name = "FSPIHD", id = 104 }, - { name = "FSPIWP", id = 105 }, - { name = "FSPIIO4", id = 106 }, - { name = "FSPIIO5", id = 107 }, - { name = "FSPIIO6", id = 108 }, - { name = "FSPIIO7", id = 109 }, - { name = "FSPICS0", id = 110 }, - { name = "FSPICS1", id = 111 }, - { name = "FSPICS2", id = 112 }, - { name = "FSPICS3", id = 113 }, - { name = "FSPICS4", id = 114 }, - { name = "FSPICS5", id = 115 }, - { name = "TWAI_TX", id = 116 }, - { name = "SUBSPICLK", id = 119 }, - { name = "SUBSPIQ", id = 120 }, - { name = "SUBSPID", id = 121 }, - { name = "SUBSPIHD", id = 122 }, - { name = "SUBSPIWP", id = 123 }, - { name = "SUBSPICS0", id = 124 }, - { name = "SUBSPICS1", id = 125 }, - { name = "FSPIDQS", id = 126 }, - { name = "SPI3_CS2", id = 127 }, - { name = "I2S0O_SD1", id = 128 }, - { name = "CORE1_GPIO0", id = 129 }, - { name = "CORE1_GPIO1", id = 130 }, - { name = "CORE1_GPIO2", id = 131 }, - { name = "LCD_CS", id = 132 }, - { name = "LCD_DATA_0", id = 133 }, - { name = "LCD_DATA_1", id = 134 }, - { name = "LCD_DATA_2", id = 135 }, - { name = "LCD_DATA_3", id = 136 }, - { name = "LCD_DATA_4", id = 137 }, - { name = "LCD_DATA_5", id = 138 }, - { name = "LCD_DATA_6", id = 139 }, - { name = "LCD_DATA_7", id = 140 }, - { name = "LCD_DATA_8", id = 141 }, - { name = "LCD_DATA_9", id = 142 }, - { name = "LCD_DATA_10", id = 143 }, - { name = "LCD_DATA_11", id = 144 }, - { name = "LCD_DATA_12", id = 145 }, - { name = "LCD_DATA_13", id = 146 }, - { name = "LCD_DATA_14", id = 147 }, - { name = "LCD_DATA_15", id = 148 }, - { name = "CAM_CLK", id = 149 }, - { name = "LCD_H_ENABLE", id = 150 }, - { name = "LCD_H_SYNC", id = 151 }, - { name = "LCD_V_SYNC", id = 152 }, - { name = "LCD_DC", id = 153 }, - { name = "LCD_PCLK", id = 154 }, - { name = "SUBSPID4", id = 155 }, - { name = "SUBSPID5", id = 156 }, - { name = "SUBSPID6", id = 157 }, - { name = "SUBSPID7", id = 158 }, - { name = "SUBSPIDQS", id = 159 }, - { name = "PWM0_0A", id = 160 }, - { name = "PWM0_0B", id = 161 }, - { name = "PWM0_1A", id = 162 }, - { name = "PWM0_1B", id = 163 }, - { name = "PWM0_2A", id = 164 }, - { name = "PWM0_2B", id = 165 }, - { name = "PWM1_0A", id = 166 }, - { name = "PWM1_0B", id = 167 }, - { name = "PWM1_1A", id = 168 }, - { name = "PWM1_1B", id = 169 }, - { name = "PWM1_2A", id = 170 }, - { name = "PWM1_2B", id = 171 }, - { name = "SDHOST_CCLK_OUT_1", id = 172 }, - { name = "SDHOST_CCLK_OUT_2", id = 173 }, - { name = "SDHOST_RST_N_1", id = 174 }, - { name = "SDHOST_RST_N_2", id = 175 }, + { name = "SPIQ", id = 0 }, + { name = "SPID", id = 1 }, + { name = "SPIHD", id = 2 }, + { name = "SPIWP", id = 3 }, + { name = "SPICLK", id = 4 }, + { name = "SPICS0", id = 5 }, + { name = "SPICS1", id = 6 }, + { name = "SPID4", id = 7 }, + { name = "SPID5", id = 8 }, + { name = "SPID6", id = 9 }, + { name = "SPID7", id = 10 }, + { name = "SPIDQS", id = 11 }, + { name = "U0TXD", id = 12 }, + { name = "U0RTS", id = 13 }, + { name = "U0DTR", id = 14 }, + { name = "U1TXD", id = 15 }, + { name = "U1RTS", id = 16 }, + { name = "U1DTR", id = 17 }, + { name = "U2TXD", id = 18 }, + { name = "U2RTS", id = 19 }, + { name = "U2DTR", id = 20 }, + { name = "I2S1_MCLK", id = 21 }, + { name = "I2S0O_BCK", id = 22 }, + { name = "I2S0_MCLK", id = 23 }, + { name = "I2S0O_WS", id = 24 }, + { name = "I2S0O_SD", id = 25 }, + { name = "I2S0I_BCK", id = 26 }, + { name = "I2S0I_WS", id = 27 }, + { name = "I2S1O_BCK", id = 28 }, + { name = "I2S1O_WS", id = 29 }, + { name = "I2S1O_SD", id = 30 }, + { name = "I2S1I_BCK", id = 31 }, + { name = "I2S1I_WS", id = 32 }, + { name = "CORE1_GPIO7", id = 54 }, + { name = "USB_EXTPHY_OEN", id = 55 }, + { name = "USB_EXTPHY_VPO", id = 57 }, + { name = "USB_EXTPHY_VMO", id = 58 }, + { name = "SPI3_CLK", id = 66 }, + { name = "SPI3_Q", id = 67 }, + { name = "SPI3_D", id = 68 }, + { name = "SPI3_HD", id = 69 }, + { name = "SPI3_WP", id = 70 }, + { name = "SPI3_CS0", id = 71 }, + { name = "SPI3_CS1", id = 72 }, + { name = "LEDC_LS_SIG0", id = 73 }, + { name = "LEDC_LS_SIG1", id = 74 }, + { name = "LEDC_LS_SIG2", id = 75 }, + { name = "LEDC_LS_SIG3", id = 76 }, + { name = "LEDC_LS_SIG4", id = 77 }, + { name = "LEDC_LS_SIG5", id = 78 }, + { name = "LEDC_LS_SIG6", id = 79 }, + { name = "LEDC_LS_SIG7", id = 80 }, + { name = "RMT_SIG_0", id = 81 }, + { name = "RMT_SIG_1", id = 82 }, + { name = "RMT_SIG_2", id = 83 }, + { name = "RMT_SIG_3", id = 84 }, + { name = "I2CEXT0_SCL", id = 89 }, + { name = "I2CEXT0_SDA", id = 90 }, + { name = "I2CEXT1_SCL", id = 91 }, + { name = "I2CEXT1_SDA", id = 92 }, + { name = "GPIO_SD0", id = 93 }, + { name = "GPIO_SD1", id = 94 }, + { name = "GPIO_SD2", id = 95 }, + { name = "GPIO_SD3", id = 96 }, + { name = "GPIO_SD4", id = 97 }, + { name = "GPIO_SD5", id = 98 }, + { name = "GPIO_SD6", id = 99 }, + { name = "GPIO_SD7", id = 100 }, + { name = "FSPICLK", id = 101 }, + { name = "FSPIQ", id = 102 }, + { name = "FSPID", id = 103 }, + { name = "FSPIHD", id = 104 }, + { name = "FSPIWP", id = 105 }, + { name = "FSPIIO4", id = 106 }, + { name = "FSPIIO5", id = 107 }, + { name = "FSPIIO6", id = 108 }, + { name = "FSPIIO7", id = 109 }, + { name = "FSPICS0", id = 110 }, + { name = "FSPICS1", id = 111 }, + { name = "FSPICS2", id = 112 }, + { name = "FSPICS3", id = 113 }, + { name = "FSPICS4", id = 114 }, + { name = "FSPICS5", id = 115 }, + { name = "TWAI_TX", id = 116 }, + { name = "SUBSPICLK", id = 119 }, + { name = "SUBSPIQ", id = 120 }, + { name = "SUBSPID", id = 121 }, + { name = "SUBSPIHD", id = 122 }, + { name = "SUBSPIWP", id = 123 }, + { name = "SUBSPICS0", id = 124 }, + { name = "SUBSPICS1", id = 125 }, + { name = "FSPIDQS", id = 126 }, + { name = "SPI3_CS2", id = 127 }, + { name = "I2S0O_SD1", id = 128 }, + { name = "CORE1_GPIO0", id = 129 }, + { name = "CORE1_GPIO1", id = 130 }, + { name = "CORE1_GPIO2", id = 131 }, + { name = "LCD_CS", id = 132 }, + { name = "LCD_DATA_0", id = 133 }, + { name = "LCD_DATA_1", id = 134 }, + { name = "LCD_DATA_2", id = 135 }, + { name = "LCD_DATA_3", id = 136 }, + { name = "LCD_DATA_4", id = 137 }, + { name = "LCD_DATA_5", id = 138 }, + { name = "LCD_DATA_6", id = 139 }, + { name = "LCD_DATA_7", id = 140 }, + { name = "LCD_DATA_8", id = 141 }, + { name = "LCD_DATA_9", id = 142 }, + { name = "LCD_DATA_10", id = 143 }, + { name = "LCD_DATA_11", id = 144 }, + { name = "LCD_DATA_12", id = 145 }, + { name = "LCD_DATA_13", id = 146 }, + { name = "LCD_DATA_14", id = 147 }, + { name = "LCD_DATA_15", id = 148 }, + { name = "CAM_CLK", id = 149 }, + { name = "LCD_H_ENABLE", id = 150 }, + { name = "LCD_H_SYNC", id = 151 }, + { name = "LCD_V_SYNC", id = 152 }, + { name = "LCD_DC", id = 153 }, + { name = "LCD_PCLK", id = 154 }, + { name = "SUBSPID4", id = 155 }, + { name = "SUBSPID5", id = 156 }, + { name = "SUBSPID6", id = 157 }, + { name = "SUBSPID7", id = 158 }, + { name = "SUBSPIDQS", id = 159 }, + { name = "PWM0_0A", id = 160 }, + { name = "PWM0_0B", id = 161 }, + { name = "PWM0_1A", id = 162 }, + { name = "PWM0_1B", id = 163 }, + { name = "PWM0_2A", id = 164 }, + { name = "PWM0_2B", id = 165 }, + { name = "PWM1_0A", id = 166 }, + { name = "PWM1_0B", id = 167 }, + { name = "PWM1_1A", id = 168 }, + { name = "PWM1_1B", id = 169 }, + { name = "PWM1_2A", id = 170 }, + { name = "PWM1_2B", id = 171 }, + { name = "SDHOST_CCLK_OUT_1", id = 172 }, + { name = "SDHOST_CCLK_OUT_2", id = 173 }, + { name = "SDHOST_RST_N_1", id = 174 }, + { name = "SDHOST_RST_N_2", id = 175 }, { name = "SDHOST_CCMD_OD_PULLUP_EN_N", id = 176 }, - { name = "SDIO_TOHOST_INT", id = 177 }, - { name = "SDHOST_CCMD_OUT_1", id = 178 }, - { name = "SDHOST_CCMD_OUT_2", id = 179 }, - { name = "SDHOST_CDATA_OUT_10", id = 180 }, - { name = "SDHOST_CDATA_OUT_11", id = 181 }, - { name = "SDHOST_CDATA_OUT_12", id = 182 }, - { name = "SDHOST_CDATA_OUT_13", id = 183 }, - { name = "SDHOST_CDATA_OUT_14", id = 184 }, - { name = "SDHOST_CDATA_OUT_15", id = 185 }, - { name = "SDHOST_CDATA_OUT_16", id = 186 }, - { name = "SDHOST_CDATA_OUT_17", id = 187 }, - { name = "SDHOST_CDATA_OUT_20", id = 213 }, - { name = "SDHOST_CDATA_OUT_21", id = 214 }, - { name = "SDHOST_CDATA_OUT_22", id = 215 }, - { name = "SDHOST_CDATA_OUT_23", id = 216 }, - { name = "SDHOST_CDATA_OUT_24", id = 217 }, - { name = "SDHOST_CDATA_OUT_25", id = 218 }, - { name = "SDHOST_CDATA_OUT_26", id = 219 }, - { name = "SDHOST_CDATA_OUT_27", id = 220 }, - - { name = "PRO_ALONEGPIO0", id = 221 }, - { name = "PRO_ALONEGPIO1", id = 222 }, - { name = "PRO_ALONEGPIO2", id = 223 }, - { name = "PRO_ALONEGPIO3", id = 224 }, - { name = "PRO_ALONEGPIO4", id = 225 }, - { name = "PRO_ALONEGPIO5", id = 226 }, - { name = "PRO_ALONEGPIO6", id = 227 }, - { name = "PRO_ALONEGPIO7", id = 228 }, - - { name = "USB_JTAG_TRST", id = 251 }, - { name = "CORE1_GPIO3", id = 252 }, - { name = "CORE1_GPIO4", id = 253 }, - { name = "CORE1_GPIO5", id = 254 }, - { name = "CORE1_GPIO6", id = 255 }, - - { name = "GPIO", id = 256 }, + { name = "SDIO_TOHOST_INT", id = 177 }, + { name = "SDHOST_CCMD_OUT_1", id = 178 }, + { name = "SDHOST_CCMD_OUT_2", id = 179 }, + { name = "SDHOST_CDATA_OUT_10", id = 180 }, + { name = "SDHOST_CDATA_OUT_11", id = 181 }, + { name = "SDHOST_CDATA_OUT_12", id = 182 }, + { name = "SDHOST_CDATA_OUT_13", id = 183 }, + { name = "SDHOST_CDATA_OUT_14", id = 184 }, + { name = "SDHOST_CDATA_OUT_15", id = 185 }, + { name = "SDHOST_CDATA_OUT_16", id = 186 }, + { name = "SDHOST_CDATA_OUT_17", id = 187 }, + { name = "SDHOST_CDATA_OUT_20", id = 213 }, + { name = "SDHOST_CDATA_OUT_21", id = 214 }, + { name = "SDHOST_CDATA_OUT_22", id = 215 }, + { name = "SDHOST_CDATA_OUT_23", id = 216 }, + { name = "SDHOST_CDATA_OUT_24", id = 217 }, + { name = "SDHOST_CDATA_OUT_25", id = 218 }, + { name = "SDHOST_CDATA_OUT_26", id = 219 }, + { name = "SDHOST_CDATA_OUT_27", id = 220 }, + + { name = "PRO_ALONEGPIO0", id = 221 }, + { name = "PRO_ALONEGPIO1", id = 222 }, + { name = "PRO_ALONEGPIO2", id = 223 }, + { name = "PRO_ALONEGPIO3", id = 224 }, + { name = "PRO_ALONEGPIO4", id = 225 }, + { name = "PRO_ALONEGPIO5", id = 226 }, + { name = "PRO_ALONEGPIO6", id = 227 }, + { name = "PRO_ALONEGPIO7", id = 228 }, + + { name = "USB_JTAG_TRST", id = 251 }, + { name = "CORE1_GPIO3", id = 252 }, + { name = "CORE1_GPIO4", id = 253 }, + { name = "CORE1_GPIO5", id = 254 }, + { name = "CORE1_GPIO6", id = 255 }, + + { name = "GPIO", id = 256 }, { name = "SPIIO4" }, { name = "SPIIO5" }, @@ -746,8 +799,26 @@ output_signals = [ [device.dedicated_gpio] support_status = "partial" channels = [ - ["PRO_ALONEGPIO0", "PRO_ALONEGPIO1", "PRO_ALONEGPIO2", "PRO_ALONEGPIO3", "PRO_ALONEGPIO4", "PRO_ALONEGPIO5", "PRO_ALONEGPIO6", "PRO_ALONEGPIO7"], - ["CORE1_GPIO0", "CORE1_GPIO1", "CORE1_GPIO2", "CORE1_GPIO3", "CORE1_GPIO4", "CORE1_GPIO5", "CORE1_GPIO6", "CORE1_GPIO7" ] + [ + "PRO_ALONEGPIO0", + "PRO_ALONEGPIO1", + "PRO_ALONEGPIO2", + "PRO_ALONEGPIO3", + "PRO_ALONEGPIO4", + "PRO_ALONEGPIO5", + "PRO_ALONEGPIO6", + "PRO_ALONEGPIO7", + ], + [ + "CORE1_GPIO0", + "CORE1_GPIO1", + "CORE1_GPIO2", + "CORE1_GPIO3", + "CORE1_GPIO4", + "CORE1_GPIO5", + "CORE1_GPIO6", + "CORE1_GPIO7", + ], ] needs_initialization = true @@ -792,7 +863,7 @@ has_tx_sync = true has_rx_wrap = true has_rx_demodulation = true has_dma = true -clock_sources.supported = [ "None", "Apb", "RcFast", "Xtal" ] +clock_sources.supported = ["None", "Apb", "RcFast", "Xtal"] clock_sources.default = "Apb" [device.rsa] @@ -812,15 +883,40 @@ has_octal = true has_app_interrupts = true has_dma_segmented_transfer = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = ["FSPID", "FSPIQ", "FSPIWP", "FSPIHD", "FSPIIO4", "FSPIIO5", "FSPIIO6", "FSPIIO7"], cs = ["FSPICS0", "FSPICS1", "FSPICS2", "FSPICS3", "FSPICS4", "FSPICS5"] }, - { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CLK", sio = ["SPI3_D", "SPI3_Q", "SPI3_WP", "SPI3_HD"], cs = ["SPI3_CS0", "SPI3_CS1", "SPI3_CS2"] }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = [ + "FSPID", + "FSPIQ", + "FSPIWP", + "FSPIHD", + "FSPIIO4", + "FSPIIO5", + "FSPIIO6", + "FSPIIO7", + ], cs = [ + "FSPICS0", + "FSPICS1", + "FSPICS2", + "FSPICS3", + "FSPICS4", + "FSPICS5", + ] }, + { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CLK", sio = [ + "SPI3_D", + "SPI3_Q", + "SPI3_WP", + "SPI3_HD", + ], cs = [ + "SPI3_CS0", + "SPI3_CS1", + "SPI3_CS2", + ] }, ] [device.spi_slave] support_status = "partial" supports_dma = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CLK", mosi = "SPI3_D", miso = "SPI3_Q", cs = "SPI3_CS0" }, ] @@ -852,7 +948,7 @@ support_status = "not_supported" [device.rng] support_status = "partial" trng_supported = true -apb_cycle_wait_num = 16 # TODO +apb_cycle_wait_num = 16 # TODO [device.sleep] support_status = "partial" From e1954c24a1d4dfaef8b05ce0ccb5e3baf0965076 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Thu, 2 Apr 2026 10:49:45 -0600 Subject: [PATCH 13/37] Changes --- esp-hal/src/mcpwm/capture.rs | 37 ++++---- esp-hal/src/mcpwm/mod.rs | 93 +++++++++++-------- esp-hal/src/mcpwm/operator.rs | 10 +- esp-hal/src/mcpwm/sync.rs | 8 +- esp-hal/src/mcpwm/timer.rs | 67 ++++++------- .../src/_build_script_utils.rs | 49 ++++++---- esp-metadata/devices/esp32c5.toml | 7 +- esp-metadata/devices/esp32c6.toml | 6 +- esp-metadata/devices/esp32h2.toml | 6 +- esp-metadata/devices/esp32s3.toml | 2 +- 10 files changed, 153 insertions(+), 132 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index b700b08156b..2395cafca92 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -97,8 +97,7 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { /// Set the sync phase pub fn set_sync_phase(&mut self, phase: u32) { - // SAFETY: - // We write to our MCPWM_CAP_TIMER_PHASE register + // SAFETY: Only CAP_TIMER_PHASE accessed; unique per PWM instance Self::phase().write(|w| unsafe { w.cap_phase().bits(phase) }); } @@ -108,20 +107,18 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { } /// Clears the captures timer sync source - pub fn clear_sync(&mut self) { - self.set_sync_enable(SyncSelection::None, false); + pub fn clear_sync_in(&mut self) { + self.enable_sync_in(SyncSelection::None, false); } - /// ## Overview /// Sets the capture timers sync source. Refer to how sync events are /// handled in the [`CaptureTimer`] documentation. - pub fn set_sync(&mut self, sync_source: &impl SyncSource) { + pub fn set_sync_in(&mut self, sync_source: &impl SyncSource) { let sync_kind = sync_source.get_kind(); - self.set_sync_enable(sync_kind.into(), false); + self.enable_sync_in(sync_kind.into(), false); } - /// ## Overview - /// This triggers a software sync event on the capture timer + /// Triggers a software sync event on the capture timer. /// Refer to how sync events are handled in the [`CaptureTimer`] documentation. pub fn trigger_sync(&mut self) { Self::cfg().modify(|_r, w| w.cap_sync_sw().set_bit()); @@ -131,13 +128,12 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { Self::cfg().modify(|_r, w| w.cap_timer_en().bit(enable)); } - fn set_sync_enable(&mut self, selection: SyncSelection, enable: bool) { - unsafe { - Self::cfg().modify(|_r, w| { - w.cap_synci_en().bit(enable); // Disable sync inputs - w.cap_synci_sel().bits(selection as u8) // No sync input - }) - }; + fn enable_sync_in(&mut self, sync_sel: SyncSelection, enable: bool) { + // SAFETY: Only CAP_TIMER_CFG accessed; unique per PWM instance + Self::cfg().modify(|_r, w| { + w.cap_synci_en().bit(enable); + unsafe { w.cap_synci_sel().bits(sync_sel as u8) } + }); } fn cfg() -> &'static crate::Reg { @@ -153,6 +149,8 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { /// Represents the capture event /// Contains the capture time and the captured edge +#[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CaptureEvent { time: u32, edge: CaptureEdge, @@ -160,18 +158,19 @@ pub struct CaptureEvent { impl CaptureEvent { /// Gets the captured time - pub fn get_time(&self) -> u32 { + pub const fn time(&self) -> u32 { self.time } /// Gets the captured edge - pub fn get_edge(&self) -> CaptureEdge { + pub const fn edge(&self) -> CaptureEdge { self.edge } } /// Configuration for capture channel #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] // Hash cannot be implemented for CaptureMode pub struct CaptureChannelConfig { invert: bool, @@ -184,7 +183,6 @@ impl CaptureChannelConfig { pub fn with_invert(self, invert: bool) -> Self { Self { invert, ..self } } - /// Sets the capture mode for the config pub fn with_capture_mode(self, capture_mode: CaptureMode) -> Self { Self { @@ -192,7 +190,6 @@ impl CaptureChannelConfig { ..self } } - /// Sets the prescaler for the config pub fn with_prescaler(self, prescaler: u8) -> Self { Self { prescaler, ..self } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index b9dfdf0f651..98c81517357 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -61,16 +61,16 @@ //! * A hardware sync or software sync can trigger a reload on the capture timer with the set //! phase. #![cfg_attr( - soc_mcpwm_capture_clk_from_group, + soc_has_mcpwm_capture_clk_from_group, doc = " * Capture timer's clock source is the same as the PWM timers clock source" )] #![cfg_attr( - not(soc_mcpwm_capture_clk_from_group), + not(soc_has_mcpwm_capture_clk_from_group), doc = " * Capture timer's has it's own independent clock source from the MCPWM peripheral." )] //! * Fault Detection Module (Not yet implemented) #![cfg_attr( - not(soc_mcpwm_capture_clk_from_group), + not(soc_has_mcpwm_capture_clk_from_group), doc = "\nCapture clock source is `ADB-CLK (80 MHz)` by default.\n" )] //! Clock source is `__clock_src__`` by default. @@ -334,10 +334,18 @@ impl PeripheralClockConfig { /// Target frequency could not be set. /// Check how the frequency is calculated in the corresponding method docs. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FrequencyError; +impl core::fmt::Display for FrequencyError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Target frequency could not be set") + } +} + +impl core::error::Error for FrequencyError {} + type RegisterBlock = pac::mcpwm0::RegisterBlock; /// Peripheral info for an MCPWM instance. @@ -371,39 +379,57 @@ pub struct State { } unsafe impl Sync for State {} + +/// Dispatches event to register bit getter for interrupt status checks +macro_rules! dispatch_event_bit { + ($int_register:expr, $event:expr, $unit:expr) => { + match $event { + Event::TimerStop => $int_register.timer_stop($unit).bit(), + Event::TimerEqualZero => $int_register.timer_tez($unit).bit(), + Event::TimerEqualPeriod => $int_register.timer_tep($unit).bit(), + Event::Capture => $int_register.cap($unit).bit(), + Event::CompareA => $int_register.cmpr_tea($unit).bit(), + Event::CompareB => $int_register.cmpr_teb($unit).bit(), + Event::Fault => $int_register.fault($unit).bit(), + Event::FaultClear => $int_register.fault_clr($unit).bit(), + Event::FaultCycleByCycle => $int_register.tz_cbc($unit).bit(), + Event::FaultOneShotMode => $int_register.tz_ost($unit).bit(), + } + }; +} + +/// Dispatches event to register bit setter for interrupt control +macro_rules! dispatch_event_write { + ($int_register:expr, $event:expr, $unit:expr, $value:expr) => { + match $event { + Event::TimerStop => $int_register.timer_stop($unit).bit($value), + Event::TimerEqualZero => $int_register.timer_tez($unit).bit($value), + Event::TimerEqualPeriod => $int_register.timer_tep($unit).bit($value), + Event::Capture => $int_register.cap($unit).bit($value), + Event::CompareA => $int_register.cmpr_tea($unit).bit($value), + Event::CompareB => $int_register.cmpr_teb($unit).bit($value), + Event::Fault => $int_register.fault($unit).bit($value), + Event::FaultClear => $int_register.fault_clr($unit).bit($value), + Event::FaultCycleByCycle => $int_register.tz_cbc($unit).bit($value), + Event::FaultOneShotMode => $int_register.tz_ost($unit).bit($value), + } + }; +} + impl State { /// Return if the interrupt for an event is set pub fn interrupt_set(&self, info: &Info, event: Event) -> bool { let regs = info.regs(); let int_st = regs.int_st().read(); - match event { - Event::TimerStop => int_st.timer_stop(UNIT).bit(), - Event::TimerEqualPeriod => int_st.timer_tep(UNIT).bit(), - Event::TimerEqualZero => int_st.timer_tez(UNIT).bit(), - Event::Capture => int_st.cap(UNIT).bit(), - Event::CompareA => int_st.cmpr_tea(UNIT).bit(), - Event::CompareB => int_st.cmpr_teb(UNIT).bit(), - Event::Fault => int_st.fault(UNIT).bit(), - Event::FaultClear => int_st.fault_clr(UNIT).bit(), - Event::FaultCycleByCycle => int_st.tz_cbc(UNIT).bit(), - Event::FaultOneShotMode => int_st.tz_ost(UNIT).bit(), - } + dispatch_event_bit!(int_st, event, UNIT) } /// Clear the interrupt for an event on a specific UNIT # pub fn clear_interrupt(&self, info: &Info, event: Event) { let regs = info.regs(); - regs.int_clr().write(|w| match event { - Event::TimerStop => w.timer_stop(UNIT).bit(true), - Event::TimerEqualPeriod => w.timer_tep(UNIT).bit(true), - Event::TimerEqualZero => w.timer_tez(UNIT).bit(true), - Event::Capture => w.cap(UNIT).bit(true), - Event::CompareA => w.cmpr_tea(UNIT).bit(true), - Event::CompareB => w.cmpr_teb(UNIT).bit(true), - Event::Fault => w.fault(UNIT).bit(true), - Event::FaultClear => w.fault_clr(UNIT).bit(true), - Event::FaultCycleByCycle => w.tz_cbc(UNIT).bit(true), - Event::FaultOneShotMode => w.tz_ost(UNIT).bit(true), + regs.int_clr().write(|w| { + dispatch_event_write!(w, event, UNIT, true); + w }); } @@ -417,18 +443,7 @@ impl State { unsafe { w.bits(int_ena.take()) }; for event in events { - match event { - Event::TimerStop => w.timer_stop(UNIT).bit(value), - Event::TimerEqualPeriod => w.timer_tep(UNIT).bit(value), - Event::TimerEqualZero => w.timer_tez(UNIT).bit(value), - Event::Capture => w.cap(UNIT).bit(value), - Event::CompareA => w.cmpr_tea(UNIT).bit(value), - Event::CompareB => w.cmpr_teb(UNIT).bit(value), - Event::Fault => w.fault(UNIT).bit(value), - Event::FaultClear => w.fault_clr(UNIT).bit(value), - Event::FaultCycleByCycle => w.tz_cbc(UNIT).bit(value), - Event::FaultOneShotMode => w.tz_ost(UNIT).bit(value), - }; + dispatch_event_write!(w, event, UNIT, value); } w diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 089c095c9e9..1bf9b398822 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -30,7 +30,8 @@ pub enum PWMStream { /// Configuration for MCPWM Operator DeadTime /// It's recommended to reference the technical manual for configuration -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DeadTimeCfg { cfg_reg: u32, } @@ -178,12 +179,7 @@ where impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { pub(super) fn new(guard: PeripheralGuard) -> Self { - // Side note: - // It would have been nice to deselect any timer reference on peripheral - // initialization. - // However experimentation (ESP32-S3) showed that writing `3` to timersel - // will not disable the timer reference but instead act as though `2` was - // written. + // NOTE: Writing 3 to timersel does not disable timer reference (hardware limitation) Operator { _phantom: PhantomData, _guard: guard, diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index e75080f250f..ee4cecf6d23 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -70,7 +70,8 @@ use crate::{gpio::interconnect::PeripheralInput, mcpwm::Instance}; pub trait SyncSource: InternalSyncSource {} /// Sync out created by timers -#[derive(Clone, Copy)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SyncOut<'d, const TIM: u8, PWM: Instance> { _phantom: PhantomData<&'d PWM>, } @@ -85,7 +86,8 @@ impl<'d, const TIM: u8, PWM: Instance> SyncOut<'d, TIM, PWM> { } /// There are only a limited number sync lines for the MCPWM unit -#[derive(Clone, Copy)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SyncLine<'d, const SYNC: u8, PWM: Instance> { _phantom: PhantomData<&'d PWM>, } @@ -177,7 +179,7 @@ pub(crate) enum SyncSelection { impl From for SyncSelection { fn from(value: SyncKind) -> Self { match value { - // SAFTEY for panic: + // SAFETY: Const generics ensure TIM and SYNC are valid (0-2) // Runtime values for line, and timer are only created // from generic constants SyncKind::SyncLine(line) => match line { diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index c8a976e015d..b4e328c2ff9 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -13,11 +13,11 @@ //! ### Software Sync Events //! The `timer` module supports the software triggering of syncs from Timers. #![cfg_attr( - soc_mcpwm_swsync_can_propagate, + soc_has_mcpwm_swsync_can_propagate, doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." )] #![cfg_attr( - not(soc_mcpwm_swsync_can_propagate), + not(soc_has_mcpwm_swsync_can_propagate), doc = "**Note:** Software triggered sync events do not propagate to other timers on this chip." )] @@ -68,7 +68,7 @@ impl Into for TimerEvent { /// as a timing reference for every /// [`Operator`](super::operator::Operator) of that peripheral pub struct Timer<'d, const TIM: u8, PWM: Instance> { - pub(super) phantom: PhantomData<&'d PWM>, + _phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } @@ -135,8 +135,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// Set the timers sync phase pub fn set_sync_phase(&mut self, phase: u16) { - // SAFETY: - // We only write to our TIMERx_SYNC register + // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const let tmr = Self::tmr(); tmr.sync().modify(|_r, w| unsafe { w.phase().bits(phase) }); } @@ -145,8 +144,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// This specifies how the counter direction will be updated /// during a sync event. pub fn set_sync_counter_direction(&mut self, direction: CounterDirection) { - // SAFETY: - // We only write to our TIMERx_SYNC register + // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const let tmr = Self::tmr(); tmr.sync() .modify(|_r, w| w.phase_direction().bit(direction as u8 != 0)); @@ -154,26 +152,22 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// Trigger a software sync event pub fn trigger_sync(&mut self) { - // SAFETY: - // We only write to our TIMERx_SYNC register + // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const let tmr = Self::tmr(); tmr.sync().modify(|r, w| w.sw().bit(!r.sw().bit())); } /// Read the counter value and counter direction of the timer pub fn status(&self) -> (u16, CounterDirection) { - // SAFETY: - // We only read from our TIMERx_STATUS register + // SAFETY: Only read TIMERx_STATUS; unique per TIM const let reg = Self::tmr().status().read(); (reg.value().bits(), reg.direction().bit_is_set().into()) } /// Selects the how the timer fires sync out events pub fn set_sync_out_selection(&mut self, sync_out: SyncOutSelect) { - // SAFETY: - // We only modify our TIMERx_SYNC register + // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const let timer = Self::tmr(); - // Disable sync input on our timer timer .sync() .modify(|_r, w| unsafe { w.synco_sel().bits(sync_out as u8) }); @@ -185,31 +179,14 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } /// Sets the timer sync in source - pub fn set_sync(&mut self, sync: &impl SyncSource) { - let (info, _) = PWM::split(); - let timer = Self::tmr(); - - // Update sync select first + pub fn set_sync_in(&mut self, sync: &impl SyncSource) { let sync_select: SyncSelection = sync.get_kind().into(); - // SAFETY: - // We only modify the PWM TIMER_SYNCI_CFG register - info.regs().timer_synci_cfg().modify(|_r, w| { - unsafe { - w.timer_syncisel(TIM).bits(sync_select as u8) // Update timer input sync selection - } - }); - - // Enable sync input on our timer - timer.sync().modify(|_r, w| w.synci_en().set_bit()); + self.enable_sync_in(sync_select, true); } /// Clears the sync in for the timer and disables sync input - pub fn clear_sync(&mut self) { - // SAFETY: - // We only modify our TIMERx_SYNC register - let timer = Self::tmr(); - // Disable sync input on our timer - timer.sync().modify(|_r, w| w.synci_en().clear_bit()); + pub fn clear_sync_in(&mut self) { + self.enable_sync_in(SyncSelection::None, false); } #[instability::unstable] @@ -256,6 +233,17 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { }); } + fn enable_sync_in(&mut self, sync_sel: SyncSelection, enable: bool) { + let (info, _) = PWM::split(); + let timer = Self::tmr(); + + // SAFETY: Only TIMER_SYNCI_CFG and TIMERx_SYNC accessed + info.regs() + .timer_synci_cfg() + .modify(|_r, w| unsafe { w.timer_syncisel(TIM).bits(sync_sel as u8) }); + timer.sync().modify(|_r, w| w.synci_en().bit(enable)); + } + fn enable_listen(&mut self, events: EnumSet, value: bool) { let (info, state) = PWM::split(); let mut int_events = EnumSet::new(); @@ -267,14 +255,12 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } fn cfg0(&mut self) -> &pac::mcpwm0::timer::CFG0 { - // SAFETY: - // We only grant access to our CFG0 register with the lifetime of &mut self + // SAFETY: Unique register access per TIM Self::tmr().cfg0() } fn cfg1(&mut self) -> &pac::mcpwm0::timer::CFG1 { - // SAFETY: - // We only grant access to our CFG0 register with the lifetime of &mut self + // SAFETY: Unique register access per TIM Self::tmr().cfg1() } @@ -292,7 +278,8 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// [`Timer::set_counter`]. A software triggered sync event will /// propagate to the sync out regardless if the timer was configured /// with [`SyncOutSelection::SyncWhenEqualZero`] or [`SyncOutSelection::SyncWhenEqualPeriod`]. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(u8)] pub enum SyncOutSelect { /// Sync out is triggered when a timer receives a sync in diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 1a253eb296d..5c2919b1a24 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -1772,8 +1772,11 @@ impl Chip { "soc_has_mem2mem6", "soc_has_mem2mem7", "soc_has_mem2mem8", - "soc_mcpwm_swsync_can_propagate", - "soc_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_swsync_can_propagate", + "soc_has_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_support_etm", + "soc_has_mcpwm_support_event_comparator", + "soc_has_mcpwm_support_sleep_retention", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", @@ -2013,8 +2016,11 @@ impl Chip { "cargo:rustc-cfg=soc_has_mem2mem6", "cargo:rustc-cfg=soc_has_mem2mem7", "cargo:rustc-cfg=soc_has_mem2mem8", - "cargo:rustc-cfg=soc_mcpwm_swsync_can_propagate", - "cargo:rustc-cfg=soc_mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=soc_has_mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=soc_has_mcpwm_support_etm", + "cargo:rustc-cfg=soc_has_mcpwm_support_event_comparator", + "cargo:rustc-cfg=soc_has_mcpwm_support_sleep_retention", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", @@ -2375,8 +2381,10 @@ impl Chip { "rom_crc_le", "rom_crc_be", "rom_md5_bsd", - "soc_mcpwm_swsync_can_propagate", - "soc_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_swsync_can_propagate", + "soc_has_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_support_etm", + "soc_has_mcpwm_support_sleep_retention", "pm_support_wifi_wakeup", "pm_support_beacon_wakeup", "pm_support_bt_wakeup", @@ -2651,8 +2659,10 @@ impl Chip { "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", - "cargo:rustc-cfg=soc_mcpwm_swsync_can_propagate", - "cargo:rustc-cfg=soc_mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=soc_has_mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=soc_has_mcpwm_support_etm", + "cargo:rustc-cfg=soc_has_mcpwm_support_sleep_retention", "cargo:rustc-cfg=pm_support_wifi_wakeup", "cargo:rustc-cfg=pm_support_beacon_wakeup", "cargo:rustc-cfg=pm_support_bt_wakeup", @@ -3429,8 +3439,10 @@ impl Chip { "soc_has_mem2mem8", "phy", "swd", - "soc_mcpwm_swsync_can_propagate", - "soc_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_swsync_can_propagate", + "soc_has_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_support_etm", + "soc_has_mcpwm_support_sleep_retention", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", @@ -3669,8 +3681,10 @@ impl Chip { "cargo:rustc-cfg=soc_has_mem2mem8", "cargo:rustc-cfg=phy", "cargo:rustc-cfg=swd", - "cargo:rustc-cfg=soc_mcpwm_swsync_can_propagate", - "cargo:rustc-cfg=soc_mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=soc_has_mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=soc_has_mcpwm_support_etm", + "cargo:rustc-cfg=soc_has_mcpwm_support_sleep_retention", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", @@ -4627,7 +4641,7 @@ impl Chip { "octal_psram", "swd", "ulp_riscv_core", - "soc_mcpwm_swsync_can_propagate", + "soc_has_mcpwm_swsync_can_propagate", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", @@ -4876,7 +4890,7 @@ impl Chip { "cargo:rustc-cfg=octal_psram", "cargo:rustc-cfg=swd", "cargo:rustc-cfg=ulp_riscv_core", - "cargo:rustc-cfg=soc_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", @@ -5612,8 +5626,11 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem6)"); println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem7)"); println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem8)"); - println!("cargo:rustc-check-cfg=cfg(soc_mcpwm_swsync_can_propagate)"); - println!("cargo:rustc-check-cfg=cfg(soc_mcpwm_capture_clk_from_group)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_swsync_can_propagate)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_capture_clk_from_group)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_support_etm)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_support_event_comparator)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_support_sleep_retention)"); println!("cargo:rustc-check-cfg=cfg(ieee802154_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(lp_i2c_master_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(parl_io_driver_supported)"); diff --git a/esp-metadata/devices/esp32c5.toml b/esp-metadata/devices/esp32c5.toml index 9c7f964e559..1c7460889c0 100644 --- a/esp-metadata/devices/esp32c5.toml +++ b/esp-metadata/devices/esp32c5.toml @@ -17,8 +17,11 @@ symbols = [ # "lp_core", # MCPWM capabilites - "soc_mcpwm_swsync_can_propagate", - "soc_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_swsync_can_propagate", + "soc_has_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_support_etm", + "soc_has_mcpwm_support_event_comparator", + "soc_has_mcpwm_support_sleep_retention", # ROM capabilities "rom_crc_le", diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 1e256430122..cfe301a9c82 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -24,8 +24,10 @@ symbols = [ "rom_md5_bsd", # MCPWM capabilites - "soc_mcpwm_swsync_can_propagate", - "soc_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_swsync_can_propagate", + "soc_has_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_support_etm", + "soc_has_mcpwm_support_sleep_retention", # Wakeup SOC based on ESP-IDF: "pm_support_wifi_wakeup", diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index a6cf908e0d9..a98ca0626cf 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -18,8 +18,10 @@ symbols = [ "swd", # MCPWM capabilites - "soc_mcpwm_swsync_can_propagate", - "soc_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_swsync_can_propagate", + "soc_has_mcpwm_capture_clk_from_group", + "soc_has_mcpwm_support_etm", + "soc_has_mcpwm_support_sleep_retention", # ROM capabilities "rom_crc_le", diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index e8523ef91a1..b01dee69f4b 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -22,7 +22,7 @@ symbols = [ "ulp_riscv_core", # MCPWM capabilities - "soc_mcpwm_swsync_can_propagate", + "soc_has_mcpwm_swsync_can_propagate", # ROM capabilities "rom_crc_le", From 1c48e3a1770175c04c7b2925bd43723859520ef7 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Thu, 2 Apr 2026 21:54:58 -0600 Subject: [PATCH 14/37] Allowing timer to have a default config to allow starting without a specifly set config --- build_all.ps1 | 20 +++ esp-hal/Cargo.toml | 18 +-- esp-hal/src/mcpwm/capture.rs | 72 +++++++---- esp-hal/src/mcpwm/mod.rs | 6 +- esp-hal/src/mcpwm/sync.rs | 18 +-- esp-hal/src/mcpwm/timer.rs | 240 +++++++++++++++++++++-------------- 6 files changed, 233 insertions(+), 141 deletions(-) create mode 100644 build_all.ps1 diff --git a/build_all.ps1 b/build_all.ps1 new file mode 100644 index 00000000000..114bd9882d9 --- /dev/null +++ b/build_all.ps1 @@ -0,0 +1,20 @@ +$builds = @( + @{ Chip = "esp32"; Target = "xtensa-esp32-none-elf" }, + @{ Chip = "esp32s2"; Target = "xtensa-esp32s2-none-elf" }, + @{ Chip = "esp32s3"; Target = "xtensa-esp32s3-none-elf" }, + @{ Chip = "esp32c2"; Target = "riscv32imc-unknown-none-elf" }, + @{ Chip = "esp32c3"; Target = "riscv32imc-unknown-none-elf" }, + @{ Chip = "esp32c5"; Target = "riscv32imac-unknown-none-elf" }, + @{ Chip = "esp32c6"; Target = "riscv32imac-unknown-none-elf" }, + @{ Chip = "esp32h2"; Target = "riscv32imac-unknown-none-elf" } +) + +foreach ($b in $builds) { + cargo +esp build ` + --manifest-path esp-hal/Cargo.toml ` + --features "$($b.Chip),unstable" ` + --target $b.Target ` + -Zbuild-std + + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +} \ No newline at end of file diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 34aae1c7168..26709665008 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -147,39 +147,39 @@ ufmt-write = { version = "0.1", optional = true } esp32 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc79498" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32" } esp32c2 = { version = "0.28", features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32c2" } esp32c3 = { version = "0.31", features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32c3" } esp32c5 = { version = "0.1", features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32c5" } esp32c6 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc79498" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32c6" } esp32c61 = { version = "0.1", features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32c61" } esp32h2 = { version = "0.18", features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32h2" } esp32s2 = { version = "0.30", features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "663c742" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32s2" } esp32s3 = { features = [ "critical-section", "rt", -], optional = true, git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "cc79498" } +], optional = true, path = "../../esp-pacs-mcpwm/esp32s3" } [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { version = "0.15.0" } diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 2395cafca92..efc476772b3 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -46,22 +46,42 @@ use crate::{ mcpwm::{ Instance, PwmClockGuard, - sync::{SyncSelection, SyncSource}, + sync::{SyncInSelect, SyncSource}, }, pac, }; +/// Configuration for capture timer +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct CaptureTimerConfig { + sync_phase: u32, +} + +impl CaptureTimerConfig { + /// Sets the sync phase for the capture timer + pub fn with_sync_phase(self, sync_phase: u32) -> Self { + Self { sync_phase, ..self } + } +} + +impl Default for CaptureTimerConfig { + fn default() -> Self { + Self { sync_phase: 0 } + } +} + /// The MCPWM Capture Timer /// /// ## Overview /// This timer is used for all [`CaptureChannel`]'s for a given MCPWM instance. -/// * This timer can be configured with a sync source by calling [`CaptureTimer::set_sync`], and -/// cleared by calling [`CaptureTimer::clear_sync_in`]. +/// * This timer can be configured with a sync source with [`CaptureTimerConfig`]. /// /// ### Sync Events -/// When this timer receives a sync event the counter of the timer is reset. -/// The value that the timer is set to is dependent on [`CaptureTimer::set_sync_phase`] -/// This timer always counts up towards a the positive direction. +/// When this timer receives a sync event the counter of the timer is reset +/// to the phase value set in [`CaptureTimerConfig`]. +/// +/// **Note:** This timer always counts up towards a the positive direction. pub struct CaptureTimer<'d, PWM: Instance> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, @@ -77,7 +97,7 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { } } - /// Start the capture timer counting at APB_CLK + /// Start the capture timer to being counting and capturing events pub fn start(&mut self) { self.set_enable(true); } @@ -95,43 +115,41 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { self.trigger_sync(); } - /// Set the sync phase - pub fn set_sync_phase(&mut self, phase: u32) { - // SAFETY: Only CAP_TIMER_PHASE accessed; unique per PWM instance - Self::phase().write(|w| unsafe { w.cap_phase().bits(phase) }); - } - - /// Get the sync phase - pub fn get_sync_phase(&mut self) -> u32 { - Self::phase().read().cap_phase().bits() + /// Configure the capture timer with the provided config + pub fn set_config(&mut self, config: CaptureTimerConfig) { + self.set_sync_phase(config.sync_phase); } - /// Clears the captures timer sync source - pub fn clear_sync_in(&mut self) { - self.enable_sync_in(SyncSelection::None, false); + /// Triggers a software sync event on the capture timer. + /// Refer to how sync events are handled in the [`CaptureTimer`] documentation. + pub fn trigger_sync(&mut self) { + Self::cfg().modify(|_r, w| w.cap_sync_sw().set_bit()); } /// Sets the capture timers sync source. Refer to how sync events are /// handled in the [`CaptureTimer`] documentation. pub fn set_sync_in(&mut self, sync_source: &impl SyncSource) { - let sync_kind = sync_source.get_kind(); - self.enable_sync_in(sync_kind.into(), false); + let sync_in = sync_source.get_kind().into(); + self.set_sync_in_select(sync_in); } - /// Triggers a software sync event on the capture timer. - /// Refer to how sync events are handled in the [`CaptureTimer`] documentation. - pub fn trigger_sync(&mut self) { - Self::cfg().modify(|_r, w| w.cap_sync_sw().set_bit()); + /// Clears the sync in + pub fn clear_sync_in(&mut self) { + self.set_sync_in_select(SyncInSelect::None); } fn set_enable(&mut self, enable: bool) { Self::cfg().modify(|_r, w| w.cap_timer_en().bit(enable)); } - fn enable_sync_in(&mut self, sync_sel: SyncSelection, enable: bool) { + fn set_sync_phase(&mut self, sync_phase: u32) { + Self::phase().write(|w| unsafe { w.cap_phase().bits(sync_phase) }); + } + + fn set_sync_in_select(&mut self, sync_sel: SyncInSelect) { // SAFETY: Only CAP_TIMER_CFG accessed; unique per PWM instance Self::cfg().modify(|_r, w| { - w.cap_synci_en().bit(enable); + w.cap_synci_en().bit(sync_sel != SyncInSelect::None); unsafe { w.cap_synci_sel().bits(sync_sel as u8) } }); } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index 98c81517357..c7e3590a425 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -194,9 +194,9 @@ impl<'d, PWM: Instance> McPwm<'d, PWM> { Self { _phantom: PhantomData, - timer0: Timer::new(guard.clone()), - timer1: Timer::new(guard.clone()), - timer2: Timer::new(guard.clone()), + timer0: Timer::new(guard.clone(), &peripheral_clock), + timer1: Timer::new(guard.clone(), &peripheral_clock), + timer2: Timer::new(guard.clone(), &peripheral_clock), operator0: Operator::new(guard.clone()), operator1: Operator::new(guard.clone()), operator2: Operator::new(guard.clone()), diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index ee4cecf6d23..14b7a99c93d 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -160,8 +160,8 @@ impl<'d, const SYNC: u8, PWM: Instance> InternalSyncSource for SyncLine<'d, SYNC /// Values for any of the sync selection registers /// This is the internal value used by capture timer, and timers #[repr(u8)] -#[derive(Copy, Clone)] -pub(crate) enum SyncSelection { +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub(crate) enum SyncInSelect { /// Select no sync input for the capture timer None = 0, /// Select the timers sync source for a timer's sync out, @@ -176,22 +176,22 @@ pub(crate) enum SyncSelection { /// Provides a simple way of translating the internal SyncKind to /// the value for sync selection used in SYNCI_SEL register fields -impl From for SyncSelection { +impl From for SyncInSelect { fn from(value: SyncKind) -> Self { match value { // SAFETY: Const generics ensure TIM and SYNC are valid (0-2) // Runtime values for line, and timer are only created // from generic constants SyncKind::SyncLine(line) => match line { - 0 => SyncSelection::SyncLine0, - 1 => SyncSelection::SyncLine1, - 2 => SyncSelection::SyncLine2, + 0 => SyncInSelect::SyncLine0, + 1 => SyncInSelect::SyncLine1, + 2 => SyncInSelect::SyncLine2, _ => panic!("Invalid sync line"), }, SyncKind::TimerSyncOut(timer) => match timer { - 0 => SyncSelection::Timer0SyncOut, - 1 => SyncSelection::Timer1SyncOut, - 2 => SyncSelection::Timer2SyncOut, + 0 => SyncInSelect::Timer0SyncOut, + 1 => SyncInSelect::Timer1SyncOut, + 2 => SyncInSelect::Timer2SyncOut, _ => panic!("Invalid timer for sync out"), }, } diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index b4e328c2ff9..f604e1879ab 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -33,7 +33,7 @@ use crate::{ Instance, PeripheralClockConfig, PwmClockGuard, - sync::{SyncOut, SyncSelection, SyncSource}, + sync::{SyncInSelect, SyncOut, SyncSource}, }, pac, time::Rate, @@ -68,51 +68,44 @@ impl Into for TimerEvent { /// as a timing reference for every /// [`Operator`](super::operator::Operator) of that peripheral pub struct Timer<'d, const TIM: u8, PWM: Instance> { + /// Sync out for the timer that can be connected to other timers sync in or operators sync in + pub sync_out: SyncOut<'d, TIM, PWM>, _phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, + config: TimerClockConfig, } impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { - pub(super) fn new(guard: PeripheralGuard) -> Self { - Timer { - phantom: PhantomData, + pub(super) fn new(guard: PeripheralGuard, peripheral_clock: &PeripheralClockConfig) -> Self { + // Default configuration for the timer + let config = TimerClockConfig::with_prescaler( + peripheral_clock, + u16::MAX, + PwmWorkingMode::Increase, + 0, + ); + + let mut timer = Timer { + sync_out: SyncOut::new(), + _phantom: PhantomData, _guard: guard, _pwm_clock_guard: PwmClockGuard::new::(), - } - } + config, + }; + timer.configure(); - /// Apply the given timer configuration. - /// - /// ### Note: - /// The prescaler and period configuration will be applied immediately by - /// default and before setting the [`PwmWorkingMode`]. - /// If the timer is already running you might want to call [`Timer::stop`] - /// and/or [`Timer::set_counter`] first - /// (if the new period is larger than the current counter value this will - /// cause weird behavior). - /// - /// If configured via [`TimerClockConfig::with_period_updating_method`], - /// another behavior can be applied. Currently, only - /// [`PeriodUpdatingMethod::Immediately`] - /// and [`PeriodUpdatingMethod::TimerEqualsZero`] are useful as the sync - /// method is not yet implemented. - /// - /// The hardware supports writing these settings in sync with certain timer - /// events but this HAL does not expose these for now. - pub fn start(&mut self, timer_config: TimerClockConfig) { - // write prescaler and period with immediate update method - self.cfg0().write(|w| unsafe { - w.prescale().bits(timer_config.prescaler); - w.period().bits(timer_config.period); - w.period_upmethod() - .bits(timer_config.period_updating_method as u8) - }); + timer + } + /// Start the given timer with the provided configurationn + pub fn start(&mut self) { // set timer to run with a stop condition + let stop_condition = self.config.stop_condition as u8; + let mode = self.config.mode as u8; self.cfg1().write(|w| unsafe { - w.start().bits(timer_config.stop_condition as u8); - w.mod_().bits(timer_config.mode as u8) + w.start().bits(stop_condition); + w.mod_().bits(mode) }); } @@ -122,71 +115,60 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { self.cfg1().write(|w| unsafe { w.mod_().bits(0) }); } + /// ### Note: + /// * The prescaler configuration will be applied immediately. + /// * The period configuration will be applied based on the [`PeriodUpdatingMethod`] set in the + /// [`TimerClockConfig`]. + /// + /// If the timer is already running you might want to call [`Timer::stop`] first. + /// + /// If your [`PeriodUpdatingMethod`] is set to [`PeriodUpdatingMethod::Immediately`] + /// and if your new period is larger than the current counter value as this will cause weird + /// behavior. + pub fn set_config(&mut self, config: TimerClockConfig) { + self.config = config; + self.configure(); + } + /// Set the timer counter to the provided value /// /// ## Overview /// Internally we set the timers phase and direction /// Then trigger a software sync event. + #[cfg(soc_has_mcpwm_swsync_can_propagate)] + /// **Note** This will cause the timer to fire a sync out event to other timers pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { self.set_sync_phase(phase); self.set_sync_counter_direction(direction); self.trigger_sync(); } - /// Set the timers sync phase - pub fn set_sync_phase(&mut self, phase: u16) { - // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const - let tmr = Self::tmr(); - tmr.sync().modify(|_r, w| unsafe { w.phase().bits(phase) }); - } - - /// Set the timers sync counter direction - /// This specifies how the counter direction will be updated - /// during a sync event. - pub fn set_sync_counter_direction(&mut self, direction: CounterDirection) { - // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const - let tmr = Self::tmr(); - tmr.sync() - .modify(|_r, w| w.phase_direction().bit(direction as u8 != 0)); - } - /// Trigger a software sync event + #[cfg(soc_has_mcpwm_swsync_can_propagate)] + /// **Note** This will cause the timer to fire a sync out event to other timers pub fn trigger_sync(&mut self) { // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const - let tmr = Self::tmr(); + let tmr = unsafe { Self::tmr() }; tmr.sync().modify(|r, w| w.sw().bit(!r.sw().bit())); } /// Read the counter value and counter direction of the timer pub fn status(&self) -> (u16, CounterDirection) { // SAFETY: Only read TIMERx_STATUS; unique per TIM const - let reg = Self::tmr().status().read(); + let reg = unsafe { Self::tmr() }.status().read(); (reg.value().bits(), reg.direction().bit_is_set().into()) } - /// Selects the how the timer fires sync out events - pub fn set_sync_out_selection(&mut self, sync_out: SyncOutSelect) { - // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const - let timer = Self::tmr(); - timer - .sync() - .modify(|_r, w| unsafe { w.synco_sel().bits(sync_out as u8) }); - } - - /// Returns the timers sync_out source - pub fn get_sync_out(&self) -> SyncOut<'d, TIM, PWM> { - SyncOut::new() - } - - /// Sets the timer sync in source - pub fn set_sync_in(&mut self, sync: &impl SyncSource) { - let sync_select: SyncSelection = sync.get_kind().into(); - self.enable_sync_in(sync_select, true); + /// Sets the capture timers sync source. Refer to how sync events are + /// handled in the [`Timer`] documentation. + pub fn set_sync_in(&mut self, sync_source: &impl SyncSource) { + let sync_in_sel = sync_source.get_kind().into(); + self.set_sync_in_select(sync_in_sel); } /// Clears the sync in for the timer and disables sync input pub fn clear_sync_in(&mut self) { - self.enable_sync_in(SyncSelection::None, false); + self.set_sync_in_select(SyncInSelect::None); } #[instability::unstable] @@ -233,15 +215,56 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { }); } - fn enable_sync_in(&mut self, sync_sel: SyncSelection, enable: bool) { + fn configure(&mut self) { + // write prescaler and period + let (prescaler, period, period_updating_method) = ( + self.config.prescaler, + self.config.period, + self.config.period_updating_method as u8, + ); + self.cfg0().write(|w| unsafe { + w.prescale().bits(prescaler); + w.period().bits(period); + w.period_upmethod().bits(period_updating_method as u8) + }); + + // write sync configure + self.set_sync_counter_direction(self.config.sync_direction); + self.set_sync_out_selection(self.config.sync_out); + self.set_sync_phase(self.config.sync_phase); + } + + fn set_sync_phase(&mut self, sync_phase: u16) { + // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const + let tmr = unsafe { Self::tmr() }; + tmr.sync() + .modify(|_r, w| unsafe { w.phase().bits(sync_phase) }); + } + + fn set_sync_counter_direction(&mut self, direction: CounterDirection) { + // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const + let tmr = unsafe { Self::tmr() }; + tmr.sync() + .modify(|_r, w| w.phase_direction().bit(direction as u8 != 0)); + } + + fn set_sync_out_selection(&mut self, sync_out: SyncOutSelect) { + // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const + let timer = unsafe { Self::tmr() }; + timer + .sync() + .modify(|_r, w| unsafe { w.synco_sel().bits(sync_out as u8) }); + } + + fn set_sync_in_select(&mut self, sync_sel: SyncInSelect) { let (info, _) = PWM::split(); - let timer = Self::tmr(); // SAFETY: Only TIMER_SYNCI_CFG and TIMERx_SYNC accessed info.regs() .timer_synci_cfg() .modify(|_r, w| unsafe { w.timer_syncisel(TIM).bits(sync_sel as u8) }); - timer.sync().modify(|_r, w| w.synci_en().bit(enable)); + self.sync() + .modify(|_r, w| w.synci_en().bit(sync_sel != SyncInSelect::None)); } fn enable_listen(&mut self, events: EnumSet, value: bool) { @@ -256,29 +279,29 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { fn cfg0(&mut self) -> &pac::mcpwm0::timer::CFG0 { // SAFETY: Unique register access per TIM - Self::tmr().cfg0() + unsafe { Self::tmr() }.cfg0() } fn cfg1(&mut self) -> &pac::mcpwm0::timer::CFG1 { // SAFETY: Unique register access per TIM - Self::tmr().cfg1() + unsafe { Self::tmr() }.cfg1() } - fn tmr() -> &'static pac::mcpwm0::TIMER { + fn sync(&mut self) -> &pac::mcpwm0::timer::SYNC { + // SAFETY: Unique register access per TIM + unsafe { Self::tmr() }.sync() + } + + // Marked unsafe as the caller must ensure that only one timer + // is accessing the registers for a given TIM const + unsafe fn tmr() -> &'static pac::mcpwm0::TIMER { let (info, _) = PWM::split(); info.regs().timer(TIM as usize) } } /// Sync out selection for the timer -/// -/// Note: For chips ESP32-S3, ESP32-C5, ESP32-C6, and ESP32-H2 -/// -/// During a software sync event triggered by [`Timer::trigger_sync`] or -/// [`Timer::set_counter`]. A software triggered sync event will -/// propagate to the sync out regardless if the timer was configured -/// with [`SyncOutSelection::SyncWhenEqualZero`] or [`SyncOutSelection::SyncWhenEqualPeriod`]. -#[derive(Clone, Copy, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(u8)] pub enum SyncOutSelect { @@ -294,7 +317,8 @@ pub enum SyncOutSelect { /// /// Use [`PeripheralClockConfig::timer_clock_with_prescaler`](super::PeripheralClockConfig::timer_clock_with_prescaler) or /// [`PeripheralClockConfig::timer_clock_with_frequency`](super::PeripheralClockConfig::timer_clock_with_frequency) to it. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TimerClockConfig { frequency: Rate, period: u16, @@ -302,6 +326,9 @@ pub struct TimerClockConfig { stop_condition: StopCondition, prescaler: u8, mode: PwmWorkingMode, + sync_out: SyncOutSelect, + sync_phase: u16, + sync_direction: CounterDirection, } impl TimerClockConfig { @@ -318,13 +345,16 @@ impl TimerClockConfig { }; let frequency = clock.frequency / (prescaler as u32 + 1) / cycle_period; - TimerClockConfig { + Self { frequency, prescaler, period, period_updating_method: PeriodUpdatingMethod::Immediately, stop_condition: StopCondition::RunContinuously, mode, + sync_out: SyncOutSelect::SyncIn, + sync_phase: 0, + sync_direction: CounterDirection::Increasing, } } @@ -352,13 +382,16 @@ impl TimerClockConfig { } let frequency = clock.frequency / (prescaler + 1) / cycle_period; - Ok(TimerClockConfig { + Ok(Self { frequency, prescaler: prescaler as u8, period, period_updating_method: PeriodUpdatingMethod::Immediately, stop_condition: StopCondition::RunContinuously, mode, + sync_out: SyncOutSelect::SyncIn, + sync_phase: 0, + sync_direction: CounterDirection::Increasing, }) } @@ -378,6 +411,24 @@ impl TimerClockConfig { } } + /// Set sync out selection + pub fn with_sync_out_selection(self, sync_out: SyncOutSelect) -> Self { + Self { sync_out, ..self } + } + + /// Sets the counter direction when the timer receives a sync event in up-down mode + pub fn with_sync_direction(self, direction: CounterDirection) -> Self { + Self { + sync_direction: direction, + ..self + } + } + + /// Sets the sync phase for the timer + pub fn with_sync_phase(self, sync_phase: u16) -> Self { + Self { sync_phase, ..self } + } + /// Get the timer clock frequency. /// /// ### Note: @@ -388,7 +439,8 @@ impl TimerClockConfig { } /// Method for updating the PWM period -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(u8)] pub enum PeriodUpdatingMethod { /// The period is updated immediately. @@ -403,7 +455,8 @@ pub enum PeriodUpdatingMethod { } /// Method for stop conditions for timers -#[derive(Clone, Copy)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(u8)] pub enum StopCondition { /// Defines to start the timer now and run till [`Timer::stop`] is called. @@ -417,7 +470,8 @@ pub enum StopCondition { } /// PWM working mode -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(u8)] pub enum PwmWorkingMode { /// In this mode, the PWM timer increments from zero until reaching the @@ -438,7 +492,7 @@ pub enum PwmWorkingMode { } /// The direction the timer counter is changing -#[derive(Debug)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(u8)] pub enum CounterDirection { /// The timer counter is increasing From 7536da63d390708e38ada9b330c3331f0f5f6ffb Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Thu, 9 Apr 2026 00:56:49 -0600 Subject: [PATCH 15/37] Added some nice public api types --- esp-hal/src/mcpwm/mod.rs | 57 ++++++++++++++++++++++++++++++++++- esp-hal/src/mcpwm/operator.rs | 21 ++++++------- esp-hal/src/mcpwm/timer.rs | 8 +++++ 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index c7e3590a425..a7c05064733 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -142,6 +142,61 @@ pub mod sync; /// MCPWM timers pub mod timer; +/// Provides nice types for public API +#[cfg(soc_has_mcpwm0)] +pub mod mcpwm0 { + use crate::{mcpwm::*, peripherals::MCPWM0 as MCPWMPerfipheral}; + + /// MCPWM Driver for MCPWM0 + pub type McPwm<'d> = super::McPwm<'d, MCPWMPerfipheral<'d>>; + /// Capture channel creator for MCPWM0 + pub type CaptureChannelCreator<'d, const NUM: u8> = + capture::CaptureChannelCreator<'d, NUM, MCPWMPerfipheral<'d>>; + /// Capture Channel for MCPWM0 + pub type CaptureChannel<'d, const NUM: u8> = + capture::CaptureChannel<'d, NUM, MCPWMPerfipheral<'d>>; + /// Capture timer for MCPWM0 + pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPerfipheral<'d>>; + /// Timer for MCPWM0 + pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPerfipheral<'d>>; + /// Operator for MCPWM0 + pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPerfipheral<'d>>; + /// Pwm Pin for MCPWM0 + pub type PwmPin<'d, const NUM: u8, const IS_A: bool> = + operator::PwmPin<'d, MCPWMPerfipheral<'d>, NUM, IS_A>; + /// Linked Pins for MCPWM0 + pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPerfipheral<'d>, NUM>; + /// Sync source for MCPWM0 + pub type SyncSource<'d> = dyn sync::SyncSource>; +} + +/// Provides nice types for public API +#[cfg(soc_has_mcpwm1)] +pub mod mcpwm1 { + use crate::{mcpwm::*, peripherals::MCPWM1 as MCPWMPerfipheral}; + /// MCPWM Driver for MCPWM1 + pub type McPwm<'d> = super::McPwm<'d, MCPWMPerfipheral<'d>>; + /// Capture channel creator for MCPWM1 + pub type CaptureChannelCreator<'d, const NUM: u8> = + capture::CaptureChannelCreator<'d, NUM, MCPWMPerfipheral<'d>>; + /// Capture Channel for MCPWM1 + pub type CaptureChannel<'d, const NUM: u8> = + capture::CaptureChannel<'d, NUM, MCPWMPerfipheral<'d>>; + /// Capture timer for MCPWM1 + pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPerfipheral<'d>>; + /// Timer for MCPWM1 + pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPerfipheral<'d>>; + /// Operator for MCPWM1 + pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPerfipheral<'d>>; + /// Pwm Pin for MCPWM1 + pub type PwmPin<'d, const NUM: u8, const IS_A: bool> = + operator::PwmPin<'d, MCPWMPerfipheral<'d>, NUM, IS_A>; + /// Linked Pins for MCPWM1 + pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPerfipheral<'d>, NUM>; + /// Sync source for MCPWM1 + pub type SyncSource<'d> = dyn sync::SyncSource>; +} + /// The MCPWM peripheral #[non_exhaustive] pub struct McPwm<'d, PWM: Instance> { @@ -179,7 +234,7 @@ pub struct McPwm<'d, PWM: Instance> { } impl<'d, PWM: Instance> McPwm<'d, PWM> { - /// `pwm_clk = clocks.crypto_pwm_clock / (prescaler + 1)` + /// Create a new instance generics pub fn new(_peripheral: PWM, peripheral_clock: PeripheralClockConfig) -> Self { let (info, _) = PWM::split(); let guard = PeripheralGuard::new(info.peripheral()); diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 1bf9b398822..335c1e9f8c8 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -191,19 +191,11 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { /// /// ### Note: /// By default TIMER0 is used - pub fn set_timer(&mut self, timer: &Timer<'d, TIM, PWM>) { - let _ = timer; + pub fn set_timer(&mut self, _timer: &Timer<'d, TIM, PWM>) { // SAFETY: // We only write to our OPERATORx_TIMERSEL register - let (info, _) = PWM::split(); - info.regs().operator_timersel().modify(|_, w| match OP { - 0 => unsafe { w.operator0_timersel().bits(TIM) }, - 1 => unsafe { w.operator1_timersel().bits(TIM) }, - 2 => unsafe { w.operator2_timersel().bits(TIM) }, - _ => { - unreachable!() - } - }); + let timer_select = unsafe { Self::timesel() }; + timer_select.modify(|_, w| unsafe { w.operator_timersel(OP).bits(TIM) }); } /// Use the A output with the given pin and configuration @@ -249,6 +241,13 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { ) -> LinkedPins<'d, PWM, OP> { LinkedPins::new(pin_a, config_a, pin_b, config_b, config_dt) } + + /// Unsafe access to the OPERATORx_TIMERSEL register + /// Caller must ensure they only write to the bits corresponding to their operator + unsafe fn timesel() -> &'static pac::mcpwm0::OPERATOR_TIMERSEL { + let (info, _) = PWM::split(); + info.regs().operator_timersel() + } } /// Configuration describing how the operator generates a signal on a connected diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index f604e1879ab..de29dd246c7 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -215,6 +215,14 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { }); } + /// Update period of the timer on the fly. How the new period is applied depends on the + /// [`PeriodUpdatingMethod`] set in the [`TimerClockConfig`]. + #[doc(hidden)] + pub fn update_period(&mut self, new_period: u16) { + self.cfg0() + .modify(|_r, w| unsafe { w.period().bits(new_period) }); + } + fn configure(&mut self) { // write prescaler and period let (prescaler, period, period_updating_method) = ( From 43a6172cc5db1b9898a715d49ea7fb93546af02b Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:08:53 -0600 Subject: [PATCH 16/37] Comments and updating capture API names --- esp-hal/src/mcpwm/capture.rs | 53 +++++++++++++++++++++++++++++++++-- esp-hal/src/mcpwm/operator.rs | 2 +- esp-hal/src/mcpwm/sync.rs | 18 ++++++------ 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index efc476772b3..8007ee85bb4 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -31,7 +31,56 @@ //! This example shows configuring MCPWM for receiving //! rising and falling edges from a GPIO pin. //! -//! TODO Write code example for this +//! ```rust, no_run +//! use critical_section::Mutex; +//! use esp_hal::{ +//! mcpwm::{ +//! McPwm, +//! PeripheralClockConfig, +//! capture::{CaptureChannelConfig, CaptureMode, CaptureTimerConfig}, +//! mcpwm0, +//! }, +//! time::Rate, +//! }; +//! +//! static CAP0: Mutex>>> = +//! Mutex::new(RefCell::new(None)); +//! +//! // initialize peripheral +//! let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(__mcpwm_freq__))?; +//! let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg); +//! +//! // capture rising edges +//! let capture_cfg = CaptureChannelConfig::default().with_capture_mode(CaptureMode::RisingEdge); +//! +//! // initalize capture timer +//! let cap_timer_cfg = CaptureTimerConfig::default(); +//! mcpwm.capture_timer.set_config(cap_timer_cfg); +//! mcpwm.capture_timer.start(); +//! +//! // create capture channel with given config and `pin` +//! let mut capture = mcpwm.capture0.configure(capture_cfg).with_signal_input(pin); +//! capture.set_enable(true); +//! capture.listen(); +//! +//! critical_section::with(|cs| CAP0.borrow_ref_mut(cs).replace(capture)); +//! +//! #[esp_hal::handler] +//! fn interrupt_handler() { +//! critical_section::with(|cs| { +//! let mut capture = CAP0.borrow_ref_mut(cs); +//! if let Some(capture) = capture.as_mut() { +//! if capture.interrupt_is_set() { +//! let event = capture.events(); +//! let time = event.time(); +//! let edge = event.edge(); +//! // do something with edge and time +//! capture.reset_interrupt(); +//! } +//! } +//! }); +//! } +//! ``` use core::marker::PhantomData; use enumset::EnumSet; @@ -338,7 +387,7 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// Gets the last captured event #[instability::unstable] - pub fn get_event(&self) -> CaptureEvent { + pub fn events(&self) -> CaptureEvent { let (info, _) = PWM::split(); let time = info.regs().cap_ch(CHAN as usize).read().value().bits(); let edge = info.regs().cap_status().read().cap_edge(CHAN).variant(); diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 335c1e9f8c8..83ccc217df6 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -7,7 +7,7 @@ //! ## Configuration //! This module provides flexibility in configuring the PWM outputs. Its //! implementation allows for motor control and other applications that demand -//! accurate pulse timing and sophisticated modulation techniques. +//! accurate pulse timing and modulation techniques. use core::marker::PhantomData; diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index 14b7a99c93d..caa0a2859d4 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -30,7 +30,7 @@ //! for 3 phase PWM. //! //! ```rust, no_run -//! use esp_hal::mcpwm::{McPwm, PeripheralClockConfig, Sync::SyncLine}; +//! use esp_hal::mcpwm::{McPwm, PeripheralClockConfig}; //! //! // initialize peripheral //! let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(__mcpwm_freq__))?; @@ -38,13 +38,13 @@ //! //! // connect sync line 0 to take input from `pin` //! mcpwm.sync0.set_signal(pin); +//! //! // connecting sync line 0 for a timer0's sync in -//! mcpwm.timer0.set_sync_in(mcpwm.sync0); +//! mcpwm.timer0.set_sync_in(&mcpwm.sync0); //! ``` //! //! ### Chaining 2 or more timers sync events -//! This shows how to configure timer 1 and timer 2 to take in -//! sync events from timer 0. This is useful when many timers require +//! This is useful when many timers require //! to be phase aligned for proper timing. //! //! ```rust, no_run @@ -54,12 +54,10 @@ //! let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(__mcpwm_freq__))?; //! let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg); //! -//! // get timer0's sync out -//! let sync_out = mcpwm.timer0.get_sync_out(); -//! // set timer1's sync in source from timer0's sync out -//! mcpwm.timer1.set_sync_in(sync_out); -//! // Optionally set timer2's sync in -//! mcpwm.timer2.set_sync_in(sync_out); +//! // set timer1's sync in +//! mcpwm.timer1.set_sync_in(&mcpwm.timer0.sync_out); +//! // set timer2's sync in +//! mcpwm.timer2.set_sync_in(&mcpwm.timer1.sync_out); //! ``` use core::marker::PhantomData; From c2fa021f317d631b3a9717877e4252f419bd0871 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 10:13:04 -0600 Subject: [PATCH 17/37] Delete build_all.ps1 Perfer to use cargo xtask check-packages esp-hal instead --- build_all.ps1 | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 build_all.ps1 diff --git a/build_all.ps1 b/build_all.ps1 deleted file mode 100644 index 114bd9882d9..00000000000 --- a/build_all.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -$builds = @( - @{ Chip = "esp32"; Target = "xtensa-esp32-none-elf" }, - @{ Chip = "esp32s2"; Target = "xtensa-esp32s2-none-elf" }, - @{ Chip = "esp32s3"; Target = "xtensa-esp32s3-none-elf" }, - @{ Chip = "esp32c2"; Target = "riscv32imc-unknown-none-elf" }, - @{ Chip = "esp32c3"; Target = "riscv32imc-unknown-none-elf" }, - @{ Chip = "esp32c5"; Target = "riscv32imac-unknown-none-elf" }, - @{ Chip = "esp32c6"; Target = "riscv32imac-unknown-none-elf" }, - @{ Chip = "esp32h2"; Target = "riscv32imac-unknown-none-elf" } -) - -foreach ($b in $builds) { - cargo +esp build ` - --manifest-path esp-hal/Cargo.toml ` - --features "$($b.Chip),unstable" ` - --target $b.Target ` - -Zbuild-std - - if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } -} \ No newline at end of file From a2aaa6bd7727a24624622341c4c555029c735367 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:33:31 -0600 Subject: [PATCH 18/37] Fixed formatting, typos, comment docs --- esp-hal/Cargo.toml | 271 ++++----- esp-hal/src/mcpwm/capture.rs | 14 +- esp-hal/src/mcpwm/mod.rs | 40 +- esp-hal/src/mcpwm/sync.rs | 12 +- esp-hal/src/mcpwm/timer.rs | 6 +- esp-metadata/devices/esp32c5.toml | 500 +++++++-------- esp-metadata/devices/esp32c6.toml | 619 +++++++++---------- esp-metadata/devices/esp32h2.toml | 510 ++++++++-------- esp-metadata/devices/esp32s3.toml | 973 ++++++++++++++---------------- 9 files changed, 1330 insertions(+), 1615 deletions(-) diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 26709665008..daba24ad469 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -1,199 +1,128 @@ [package] -name = "esp-hal" -version = "1.0.0" -edition = "2024" -rust-version = "1.88.0" -description = "Bare-metal HAL for Espressif devices" +name = "esp-hal" +version = "1.0.0" +edition = "2024" +rust-version = "1.88.0" +description = "Bare-metal HAL for Espressif devices" documentation = "https://docs.espressif.com/projects/rust/esp-hal/latest/" -keywords = ["embedded", "embedded-hal", "esp32", "espressif", "hal"] -categories = ["embedded", "hardware-support", "no-std"] -repository = "https://github.com/esp-rs/esp-hal" -license = "MIT OR Apache-2.0" -exclude = ["api-baseline", "MIGRATING-*", "CHANGELOG.md"] +keywords = ["embedded", "embedded-hal", "esp32", "espressif", "hal"] +categories = ["embedded", "hardware-support", "no-std"] +repository = "https://github.com/esp-rs/esp-hal" +license = "MIT OR Apache-2.0" +exclude = [ "api-baseline", "MIGRATING-*", "CHANGELOG.md" ] [package.metadata.espressif] semver-checked = true -doc-config = { features = [ - "unstable", - "rt", -], append = [ - { if = 'chip_has("psram")', features = [ - "psram", - ] }, - { if = 'chip_has("usb_otg_driver_supported")', features = [ - "__usb_otg", - ] }, - { if = 'chip_has("bt_driver_supported")', features = [ - "__bluetooth", - ] }, +doc-config = { features = ["unstable", "rt"], append = [ + { if = 'chip_has("usb_otg_driver_supported")', features = ["__usb_otg"] }, + { if = 'chip_has("bt_driver_supported")', features = ["__bluetooth"] }, ] } check-configs = [ - { features = [ - ] }, - { features = [ - "rt", - ] }, - { features = [ - "unstable", - "rt", - ] }, - { features = [ - "unstable", - "rt", - "psram", - ], if = 'chip_has("psram")' }, - { features = [ - "unstable", - "rt", - "__usb_otg", - ], if = 'chip_has("usb_otg_driver_supported")' }, - { features = [ - "unstable", - "rt", - "__bluetooth", - ], if = 'chip_has("bt_driver_supported")' }, + { features = [] }, + { features = ["rt"] }, + { features = ["unstable", "rt"] }, + { features = ["unstable", "rt", "__usb_otg"], if = 'chip_has("usb_otg_driver_supported")' }, + { features = ["unstable", "rt", "__bluetooth"], if = 'chip_has("bt_driver_supported")' }, ] # Prefer fewer, but more complex clippy rules. A clippy run should cover as much code as possible. clippy-configs = [ - { features = [ - "unstable", - "rt", - ], append = [ - { if = 'chip_has("psram")', features = [ - "psram", - ] }, - { if = 'chip_has("usb_otg_driver_supported")', features = [ - "__usb_otg", - ] }, - { if = 'chip_has("bt_driver_supported")', features = [ - "__bluetooth", - ] }, + { features = ["unstable", "rt"], append = [ + { if = 'chip_has("usb_otg_driver_supported")', features = ["__usb_otg"] }, + { if = 'chip_has("bt_driver_supported")', features = ["__bluetooth"] }, ] }, ] [package.metadata.docs.rs] default-target = "riscv32imac-unknown-none-elf" -features = ["esp32c6", "unstable"] -rustdoc-args = ["--cfg", "docsrs"] +features = ["esp32c6", "unstable"] +rustdoc-args = ["--cfg", "docsrs"] [lib] bench = false -test = false +test = false [dependencies] -bitflags = "2.9" -bytemuck = "1.24" -cfg-if = "1" -critical-section = { version = "1", features = [ - "restore-state-u32", -], optional = true } -embedded-hal = "1.0.0" -embedded-hal-async = "1.0.0" -enumset = "1.1" -paste = "1.0.15" -portable-atomic = { version = "1.11", default-features = false } - -esp-rom-sys = { version = "0.1.3", path = "../esp-rom-sys" } +bitflags = "2.9" +bytemuck = "1.24" +cfg-if = "1" +critical-section = { version = "1", features = ["restore-state-u32"], optional = true } +embedded-hal = "1.0.0" +embedded-hal-async = "1.0.0" +enumset = "1.1" +paste = "1.0.15" +portable-atomic = { version = "1.11", default-features = false } + +esp-rom-sys = { version = "0.1.3", path = "../esp-rom-sys" } # Unstable dependencies that are not (strictly) part of the public API -bitfield = "0.19" -delegate = "0.13" -document-features = "0.2" -embassy-futures = "0.1" -embassy-sync = "0.7" -fugit = "0.3.7" -instability = "0.3.9" -strum = { version = "0.27.1", default-features = false, features = ["derive"] } - -esp-config = { version = "0.6.1", path = "../esp-config" } -esp-metadata-generated = { version = "0.3.0", path = "../esp-metadata-generated" } -esp-sync = { version = "0.1.1", path = "../esp-sync" } -procmacros = { version = "0.21.0", package = "esp-hal-procmacros", path = "../esp-hal-procmacros" } +bitfield = "0.19" +delegate = "0.13" +document-features = "0.2" +embassy-futures = "0.1" +embassy-sync = "0.8" +fugit = "0.3.7" +instability = "0.3.12" +strum = { version = "0.27.1", default-features = false, features = ["derive"] } + +esp-config = { version = "0.6.1", path = "../esp-config" } +esp-metadata-generated = { version = "0.3.0", path = "../esp-metadata-generated" } +esp-sync = { version = "0.1.1", path = "../esp-sync" } +procmacros = { version = "0.21.0", package = "esp-hal-procmacros", path = "../esp-hal-procmacros" } # Dependencies that are optional because they are used by unstable drivers. # They are needed when using the `unstable` feature. -digest = { version = "0.10.7", default-features = false, features = [ - "core-api", -], optional = true } -embassy-usb-driver = { version = "0.2", optional = true } +digest = { version = "0.10.7", default-features = false, features = ["core-api"], optional = true } +embassy-usb-driver = { version = "0.2", optional = true } embassy-usb-synopsys-otg = { version = "0.3", optional = true } -embedded-can = { version = "0.4.1", optional = true } -esp-synopsys-usb-otg = { version = "0.4.2", optional = true } -nb = { version = "1.1", optional = true } +embedded-can = { version = "0.4.1", optional = true } +esp-synopsys-usb-otg = { version = "0.4.2", optional = true } +nb = { version = "1.1", optional = true } # Logging interfaces, they are mutually exclusive so they need to be behind separate features. -defmt = { version = "1.0.1", optional = true } -log-04 = { package = "log", version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +log-04 = { package = "log", version = "0.4", optional = true } # ESP32-only fallback SHA algorithms -sha1 = { version = "0.10", default-features = false, optional = true } -sha2 = { version = "0.10", default-features = false, optional = true } +sha1 = { version = "0.10", default-features = false, optional = true } +sha2 = { version = "0.10", default-features = false, optional = true } # Optional dependencies that enable ecosystem support. # We could support individually enabling them, but there is no big downside to just # enabling them all via the `unstable` feature. -embassy-embedded-hal = { version = "0.5", optional = true } -embedded-io-06 = { package = "embedded-io", version = "0.6", optional = true } -embedded-io-async-06 = { package = "embedded-io-async", version = "0.6", optional = true } -embedded-io-07 = { package = "embedded-io", version = "0.7", optional = true } -embedded-io-async-07 = { package = "embedded-io-async", version = "0.7", optional = true } -rand_core-06 = { package = "rand_core", version = "0.6", optional = true } -rand_core-09 = { package = "rand_core", version = "0.9", optional = true } -ufmt-write = { version = "0.1", optional = true } +embassy-embedded-hal = { version = "0.6", optional = true } +embedded-io-06 = { package = "embedded-io", version = "0.6", optional = true } +embedded-io-async-06 = { package = "embedded-io-async", version = "0.6", optional = true } +embedded-io-07 = { package = "embedded-io", version = "0.7", optional = true } +embedded-io-async-07 = { package = "embedded-io-async", version = "0.7", optional = true } +rand_core-06 = { package = "rand_core", version = "0.6", optional = true } +rand_core-09 = { package = "rand_core", version = "0.9", optional = true } +rand_core-010 = { package = "rand_core", version = "0.10", optional = true } +ufmt-write = { version = "0.1", optional = true } # IMPORTANT: # Each supported device MUST have its PAC included below along with a # corresponding feature. -esp32 = { features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32" } -esp32c2 = { version = "0.28", features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32c2" } -esp32c3 = { version = "0.31", features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32c3" } -esp32c5 = { version = "0.1", features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32c5" } -esp32c6 = { features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32c6" } -esp32c61 = { version = "0.1", features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32c61" } -esp32h2 = { version = "0.18", features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32h2" } -esp32s2 = { version = "0.30", features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32s2" } -esp32s3 = { features = [ - "critical-section", - "rt", -], optional = true, path = "../../esp-pacs-mcpwm/esp32s3" } +esp32 = { version = "0.39", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } +esp32c2 = { version = "0.28", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } +esp32c3 = { version = "0.31", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } +esp32c5 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } +esp32c6 = { version = "0.22", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } +esp32c61 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } +esp32h2 = { version = "0.18", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } +esp32s2 = { version = "0.30", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } +esp32s3 = { version = "0.34", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } [target.'cfg(target_arch = "riscv32")'.dependencies] -riscv = { version = "0.15.0" } -esp-riscv-rt = { version = "0.13.0", path = "../esp-riscv-rt", optional = true } +riscv = { version = "0.15.0" } +esp-riscv-rt = { version = "0.13.0", path = "../esp-riscv-rt", optional = true } [target.'cfg(target_arch = "xtensa")'.dependencies] -xtensa-lx = { version = "0.13.0", path = "../xtensa-lx" } -xtensa-lx-rt = { version = "0.21.0", path = "../xtensa-lx-rt", optional = true } +xtensa-lx = { version = "0.13.0", path = "../xtensa-lx" } +xtensa-lx-rt = { version = "0.21.0", path = "../xtensa-lx-rt", optional = true } [build-dependencies] -esp-metadata-generated = { version = "0.3.0", path = "../esp-metadata-generated", features = [ - "build-script", -] } -esp-config = { version = "0.6.1", path = "../esp-config", features = ["build"] } +esp-metadata-generated = { version = "0.3.0", path = "../esp-metadata-generated", features = ["build-script"] } +esp-config = { version = "0.6.1", path = "../esp-config", features = ["build"] } [dev-dependencies] crypto-bigint = { version = "0.5.5", default-features = false } @@ -251,14 +180,15 @@ float-save-restore = ["xtensa-lx-rt/float-save-restore"] #! One of the following features must be enabled to select the target chip: ## -esp32 = [ +esp32 = [ "dep:esp32", "procmacros/rtc-slow", + "procmacros/rtc-fast", "esp-rom-sys/esp32", "esp-sync/esp32", "esp-metadata-generated/esp32", "dep:sha1", - "dep:sha2", + "dep:sha2" ] ## esp32c2 = [ @@ -274,6 +204,7 @@ esp32c3 = [ "dep:esp32c3", "esp-riscv-rt/no-mie-mip", "esp-riscv-rt/rtc-ram", + "procmacros/rtc-fast", "portable-atomic/unsafe-assume-single-core", "esp-rom-sys/esp32c3", "esp-sync/esp32c3", @@ -284,6 +215,7 @@ esp32c5 = [ "dep:esp32c5", "esp-riscv-rt/rtc-ram", "esp-riscv-rt/clic-48", + "procmacros/rtc-fast", "procmacros/has-lp-core", "esp-rom-sys/esp32c5", "esp-sync/esp32c5", @@ -293,6 +225,7 @@ esp32c5 = [ esp32c6 = [ "dep:esp32c6", "esp-riscv-rt/rtc-ram", + "procmacros/rtc-fast", "procmacros/has-lp-core", "esp-rom-sys/esp32c6", "esp-sync/esp32c6", @@ -311,6 +244,7 @@ esp32c61 = [ esp32h2 = [ "dep:esp32h2", "esp-riscv-rt/rtc-ram", + "procmacros/rtc-fast", "esp-rom-sys/esp32h2", "esp-sync/esp32h2", "esp-metadata-generated/esp32h2", @@ -321,6 +255,7 @@ esp32s2 = [ "portable-atomic/unsafe-assume-single-core", "procmacros/has-ulp-core", "procmacros/rtc-slow", + "procmacros/rtc-fast", "__usb_otg", "esp-rom-sys/esp32s2", "esp-sync/esp32s2", @@ -331,6 +266,7 @@ esp32s3 = [ "dep:esp32s3", "procmacros/has-ulp-core", "procmacros/rtc-slow", + "procmacros/rtc-fast", "__usb_otg", "esp-rom-sys/esp32s3", "esp-sync/esp32s3", @@ -363,17 +299,9 @@ defmt = [ "fugit/defmt", "esp-riscv-rt?/defmt", "xtensa-lx-rt?/defmt", - "esp-sync/defmt", + "esp-sync/defmt" ] -#DOC_IF has("psram") -#! ### PSRAM Feature Flags - -## Use externally connected PSRAM (`quad` by default, can be configured to `octal` via ESP_HAL_CONFIG_PSRAM_MODE) -psram = [] - -#DOC_ENDIF - #! ### Unstable APIs #! Unstable APIs are drivers and features that are not yet ready for general use. #! They may be incomplete, have bugs, or be subject to change without notice. @@ -391,6 +319,7 @@ unstable = [ "dep:embedded-io-async-07", "dep:rand_core-06", "dep:rand_core-09", + "dep:rand_core-010", "dep:nb", "dep:ufmt-write", ] @@ -405,6 +334,16 @@ requires-unstable = [] mixed_attributes_style = "allow" [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = [ - 'cfg(host_os, values("windows"))', -] } +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(host_os, values("windows"))'] } + +## Temp patch till esp-pacs-mcpwm pull request is accepted. +[patch."https://github.com/esp-rs/esp-pacs"] +esp32 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } +esp32c2 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } +esp32c3 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } +esp32c5 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } +esp32c6 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } +esp32c61 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } +esp32h2 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } +esp32s2 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } +esp32s3 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } \ No newline at end of file diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 8007ee85bb4..9e4e68dab44 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -2,12 +2,6 @@ "mcpwm_freq" => { cfg(not(esp32h2)) => "40", cfg(esp32h2) => "32" - }, - "clock_src" => { - cfg(esp32) => "ADB-CLK (80 MHz)", - cfg(esp32s3) => "ADB-CLK (80 MHz)", - cfg(esp32c6) => "ADB-CLK (80 MHz)", - cfg(esp32h2) => "ADB-CLK (80 MHz)", } ))] //! # MCPWM Capture Module @@ -32,6 +26,8 @@ //! rising and falling edges from a GPIO pin. //! //! ```rust, no_run +//! use core::cell::RefCell; +//! //! use critical_section::Mutex; //! use esp_hal::{ //! mcpwm::{ @@ -53,7 +49,7 @@ //! // capture rising edges //! let capture_cfg = CaptureChannelConfig::default().with_capture_mode(CaptureMode::RisingEdge); //! -//! // initalize capture timer +//! // initialize capture timer //! let cap_timer_cfg = CaptureTimerConfig::default(); //! mcpwm.capture_timer.set_config(cap_timer_cfg); //! mcpwm.capture_timer.start(); @@ -70,12 +66,12 @@ //! critical_section::with(|cs| { //! let mut capture = CAP0.borrow_ref_mut(cs); //! if let Some(capture) = capture.as_mut() { -//! if capture.interrupt_is_set() { +//! if capture.is_interrupt_set() { //! let event = capture.events(); //! let time = event.time(); //! let edge = event.edge(); //! // do something with edge and time -//! capture.reset_interrupt(); +//! capture.clear_interrupt(); //! } //! } //! }); diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index a7c05064733..29552208eb6 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -145,56 +145,56 @@ pub mod timer; /// Provides nice types for public API #[cfg(soc_has_mcpwm0)] pub mod mcpwm0 { - use crate::{mcpwm::*, peripherals::MCPWM0 as MCPWMPerfipheral}; + use crate::{mcpwm::*, peripherals::MCPWM0 as MCPWMPeripheral}; /// MCPWM Driver for MCPWM0 - pub type McPwm<'d> = super::McPwm<'d, MCPWMPerfipheral<'d>>; + pub type McPwm<'d> = super::McPwm<'d, MCPWMPeripheral<'d>>; /// Capture channel creator for MCPWM0 pub type CaptureChannelCreator<'d, const NUM: u8> = - capture::CaptureChannelCreator<'d, NUM, MCPWMPerfipheral<'d>>; + capture::CaptureChannelCreator<'d, NUM, MCPWMPeripheral<'d>>; /// Capture Channel for MCPWM0 pub type CaptureChannel<'d, const NUM: u8> = - capture::CaptureChannel<'d, NUM, MCPWMPerfipheral<'d>>; + capture::CaptureChannel<'d, NUM, MCPWMPeripheral<'d>>; /// Capture timer for MCPWM0 - pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPerfipheral<'d>>; + pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPeripheral<'d>>; /// Timer for MCPWM0 - pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPerfipheral<'d>>; + pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPeripheral<'d>>; /// Operator for MCPWM0 - pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPerfipheral<'d>>; + pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPeripheral<'d>>; /// Pwm Pin for MCPWM0 pub type PwmPin<'d, const NUM: u8, const IS_A: bool> = - operator::PwmPin<'d, MCPWMPerfipheral<'d>, NUM, IS_A>; + operator::PwmPin<'d, MCPWMPeripheral<'d>, NUM, IS_A>; /// Linked Pins for MCPWM0 - pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPerfipheral<'d>, NUM>; + pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPeripheral<'d>, NUM>; /// Sync source for MCPWM0 - pub type SyncSource<'d> = dyn sync::SyncSource>; + pub type SyncSource<'d> = dyn sync::SyncSource>; } /// Provides nice types for public API #[cfg(soc_has_mcpwm1)] pub mod mcpwm1 { - use crate::{mcpwm::*, peripherals::MCPWM1 as MCPWMPerfipheral}; + use crate::{mcpwm::*, peripherals::MCPWM1 as MCPWMPeripheral}; /// MCPWM Driver for MCPWM1 - pub type McPwm<'d> = super::McPwm<'d, MCPWMPerfipheral<'d>>; + pub type McPwm<'d> = super::McPwm<'d, MCPWMPeripheral<'d>>; /// Capture channel creator for MCPWM1 pub type CaptureChannelCreator<'d, const NUM: u8> = - capture::CaptureChannelCreator<'d, NUM, MCPWMPerfipheral<'d>>; + capture::CaptureChannelCreator<'d, NUM, MCPWMPeripheral<'d>>; /// Capture Channel for MCPWM1 pub type CaptureChannel<'d, const NUM: u8> = - capture::CaptureChannel<'d, NUM, MCPWMPerfipheral<'d>>; + capture::CaptureChannel<'d, NUM, MCPWMPeripheral<'d>>; /// Capture timer for MCPWM1 - pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPerfipheral<'d>>; + pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPeripheral<'d>>; /// Timer for MCPWM1 - pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPerfipheral<'d>>; + pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPeripheral<'d>>; /// Operator for MCPWM1 - pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPerfipheral<'d>>; + pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPeripheral<'d>>; /// Pwm Pin for MCPWM1 pub type PwmPin<'d, const NUM: u8, const IS_A: bool> = - operator::PwmPin<'d, MCPWMPerfipheral<'d>, NUM, IS_A>; + operator::PwmPin<'d, MCPWMPeripheral<'d>, NUM, IS_A>; /// Linked Pins for MCPWM1 - pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPerfipheral<'d>, NUM>; + pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPeripheral<'d>, NUM>; /// Sync source for MCPWM1 - pub type SyncSource<'d> = dyn sync::SyncSource>; + pub type SyncSource<'d> = dyn sync::SyncSource>; } /// The MCPWM peripheral diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index caa0a2859d4..c4008bf824e 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -2,12 +2,6 @@ "mcpwm_freq" => { cfg(not(esp32h2)) => "40", cfg(esp32h2) => "32" - }, - "clock_src" => { - cfg(esp32) => "PLL_F160M (160 MHz)", - cfg(esp32s3) => "CRYPTO_PWM_CLK (160 MHz)", - cfg(esp32c6) => "PLL_F160M (160 MHz)", - cfg(esp32h2) => "PLL_F96M_CLK (96 MHz)", } ))] //! # MCPWM Sync Module @@ -18,7 +12,7 @@ //! sync sources. One is a [`SyncOut`] that comes from [`super::Timer::get_sync_out`], //! or from a [`SyncLine`]. //! -//! This module provides the flexability to map any of the +//! This module provides the flexibility to map any of the //! MCPWM's [`SyncLine`] to any GPIO signal. //! //! ## Example @@ -64,7 +58,7 @@ use core::marker::PhantomData; use crate::{gpio::interconnect::PeripheralInput, mcpwm::Instance}; #[allow(private_bounds)] -/// Public trait to repersent a sync source for a PWM +/// Public trait to represent a sync source for a PWM pub trait SyncSource: InternalSyncSource {} /// Sync out created by timers @@ -134,7 +128,7 @@ pub(crate) enum SyncKind { TimerSyncOut(u8), } -/// Internal trait to repersent which pwm unit and +/// Internal trait to represent which pwm unit and /// sync out it came from. Broadly represents sync lines, /// and timer sync out. pub(crate) trait InternalSyncSource: crate::private::Sealed { diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index de29dd246c7..6d031f983fb 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -98,7 +98,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { timer } - /// Start the given timer with the provided configurationn + /// Start the given timer with the provided configuration pub fn start(&mut self) { // set timer to run with a stop condition let stop_condition = self.config.stop_condition as u8; @@ -135,7 +135,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// ## Overview /// Internally we set the timers phase and direction /// Then trigger a software sync event. - #[cfg(soc_has_mcpwm_swsync_can_propagate)] + #[cfg_attr(soc_has_mcpwm_swsync_can_propagate, doc(hidden))] /// **Note** This will cause the timer to fire a sync out event to other timers pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { self.set_sync_phase(phase); @@ -144,7 +144,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } /// Trigger a software sync event - #[cfg(soc_has_mcpwm_swsync_can_propagate)] + #[cfg_attr(soc_has_mcpwm_swsync_can_propagate, doc(hidden))] /// **Note** This will cause the timer to fire a sync out event to other timers pub fn trigger_sync(&mut self) { // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const diff --git a/esp-metadata/devices/esp32c5.toml b/esp-metadata/devices/esp32c5.toml index 1c7460889c0..c59ef033350 100644 --- a/esp-metadata/devices/esp32c5.toml +++ b/esp-metadata/devices/esp32c5.toml @@ -6,17 +6,17 @@ # update the table in the esp-hal README. [device] -name = "esp32c5" -arch = "riscv" +name = "esp32c5" +arch = "riscv" target = "riscv32imac-unknown-none-elf" -cores = 1 -trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c5_technical_reference_manual_en.pdf" +cores = 1 +trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c5_technical_reference_manual_en.pdf" symbols = [ # Additional peripherals defined by us (the developers): # "lp_core", - # MCPWM capabilites + # MCPWM capabilities "soc_has_mcpwm_swsync_can_propagate", "soc_has_mcpwm_capture_clk_from_group", "soc_has_mcpwm_support_etm", @@ -109,8 +109,8 @@ peripherals = [ { name = "SHA", interrupts = { peri = "SHA" }, dma_peripheral = 7 }, { name = "SLC" }, # { name = "SLCHOST" }, TODO: add PAC manually later - # { name = "SPI0" }, - # { name = "SPI1" }, + { name = "SPI0" }, + { name = "SPI1" }, { name = "SPI2", interrupts = { peri = "SPI2" }, dma_peripheral = 1, stable = true }, { name = "SYSTEM", pac = "PCR" }, { name = "SYSTIMER" }, @@ -146,34 +146,36 @@ peripherals = [ { name = "MEM2MEM6", virtual = true, dma_peripheral = 13 }, { name = "MEM2MEM7", virtual = true, dma_peripheral = 14 }, { name = "MEM2MEM8", virtual = true, dma_peripheral = 15 }, + + { name = "PSRAM", virtual = true }, ] clocks = { system_clocks = { clock_tree = [ # High-speed clock sources - { name = "XTAL_CLK", type = "source", values = "40, 48", output = "VALUE * 1_000_000", always_on = true }, # TODO: not user-configurable - { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, - { name = "RC_FAST_CLK", type = "source", output = "20_000_000" }, + { name = "XTAL_CLK", type = "source", values = "40, 48", output = "VALUE * 1_000_000", always_on = true }, # TODO: not user-configurable + { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, + { name = "RC_FAST_CLK", type = "source", output = "20_000_000" }, # Low-speed clocks - { name = "XTAL32K_CLK", type = "source", output = "32768" }, - { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, - { name = "RC_SLOW_CLK", type = "source", output = "130_000" }, + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "130_000" }, # { name = "EXT32K_CLK", type = "source", output = "32768" }, # currently unimplemented # PLL divider taps - { name = "PLL_F12M", type = "generic", output = "PLL_CLK / 40" }, - { name = "PLL_F20M", type = "generic", output = "PLL_CLK / 24" }, - { name = "PLL_F40M", type = "generic", output = "PLL_CLK / 12" }, - { name = "PLL_F48M", type = "generic", output = "PLL_CLK / 10" }, - { name = "PLL_F60M", type = "generic", output = "PLL_CLK / 8" }, - { name = "PLL_F80M", type = "generic", output = "PLL_CLK / 6" }, - { name = "PLL_F120M", type = "generic", output = "PLL_CLK / 4" }, - { name = "PLL_F160M", type = "generic", output = "PLL_CLK / 3" }, - { name = "PLL_F240M", type = "generic", output = "PLL_CLK / 2" }, + { name = "PLL_F12M", type = "generic", output = "PLL_CLK / 40" }, + { name = "PLL_F20M", type = "generic", output = "PLL_CLK / 24" }, + { name = "PLL_F40M", type = "generic", output = "PLL_CLK / 12" }, + { name = "PLL_F48M", type = "generic", output = "PLL_CLK / 10" }, + { name = "PLL_F60M", type = "generic", output = "PLL_CLK / 8" }, + { name = "PLL_F80M", type = "generic", output = "PLL_CLK / 6" }, + { name = "PLL_F120M", type = "generic", output = "PLL_CLK / 4" }, + { name = "PLL_F160M", type = "generic", output = "PLL_CLK / 3" }, + { name = "PLL_F240M", type = "generic", output = "PLL_CLK / 2" }, # HP SOC clock root (PCR_SOC_CLK_SEL: XTAL, RC_FAST, PLL_F160M, PLL_F240M) { name = "HP_ROOT_CLK", type = "mux", variants = [ - { name = "XTAL", outputs = "XTAL_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, { name = "PLL_F160M", outputs = "PLL_F160M" }, { name = "PLL_F240M", outputs = "PLL_F240M" }, ] }, @@ -191,67 +193,67 @@ clocks = { system_clocks = { clock_tree = [ { name = "LP_FAST_CLK", type = "mux", variants = [ { name = "RC_FAST", outputs = "RC_FAST_CLK" }, { name = "XTAL_D2", outputs = "XTAL_D2_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, ] }, { name = "LP_SLOW_CLK", type = "mux", variants = [ - { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, - { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, #{ name = "EXT32K", outputs = "EXT32K_CLK" }, { name = "OSC_SLOW", outputs = "OSC_SLOW_CLK" }, ] }, - + # Global peripheral-related clocks { name = "CRYPTO_CLK", type = "mux", variants = [ # PCR_SEC_CONF - { name = "XTAL", outputs = "XTAL_CLK" }, - { name = "FOSC", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "FOSC", outputs = "RC_FAST_CLK" }, { name = "PLL_F480M", outputs = "PLL_CLK" }, ] }, { name = "TIMG_CALIBRATION_CLOCK", type = "mux", variants = [ # PCR_32K_SEL / clk_tg_xtal32k - { name = "OSC_SLOW_CLK", outputs = "OSC_SLOW_CLK" }, - { name = "RC_SLOW_CLK", outputs = "RC_SLOW_CLK" }, + { name = "OSC_SLOW_CLK", outputs = "OSC_SLOW_CLK" }, + { name = "RC_SLOW_CLK", outputs = "RC_SLOW_CLK" }, # EXT32K not modeled { name = "RC_FAST_DIV_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, + { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, ] }, ], template_groups = [ { group = "UART", clocks = [ { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ - { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "XTAL", outputs = "XTAL_CLK", default = true }, { name = "PLL_F80M", outputs = "PLL_F80M" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, ], div_num = "0 .. 0x100" } }, { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, ] }, { group = "TIMG", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, ] }, { name = "WDT_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, ] }, ] }, { group = "RMT", clocks = [ { name = "SCLK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F80M", outputs = "PLL_F80M", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M", default = true }, ] }, ] }, { group = "PARL_IO", clocks = [ { name = "RX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, + { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, # TODO: external clock ] }, { name = "TX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, + { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, ] }, ] }, ] }, peripheral_clocks = { templates = [ @@ -265,14 +267,14 @@ clocks = { system_clocks = { clock_tree = [ { name = "clk_en_field", value = "{{peripheral}}_clk_en" }, { name = "rst_field", value = "{{peripheral}}_rst_en" }, ], peripheral_clocks = [ - { name = "Uart0", template_params = { conf_register = "uart(0).conf", clk_en_field = "clk_en", rst_field = "rst_en" }, keep_enabled = true }, + { name = "Uart0", template_params = { conf_register = "uart(0).conf", clk_en_field = "clk_en", rst_field = "rst_en" }, keep_enabled = true}, { name = "Uart1", template_params = { conf_register = "uart(1).conf", clk_en_field = "clk_en", rst_field = "rst_en" } }, { name = "Timg0", template_params = { conf_register = "timergroup(0).conf", clk_en_field = "clk_en", rst_field = "rst_en" }, keep_enabled = true }, { name = "Timg1", template_params = { conf_register = "timergroup(1).conf", clk_en_field = "clk_en", rst_field = "rst_en" } }, { name = "I2cExt0", template_params = { peripheral = "i2c0" } }, { name = "Pcnt" }, { name = "Rmt" }, - { name = "Systimer", keep_enabled = true }, # can be clocked from XTAL_CLK or RC_FAST_CLK, the latter has no divider? + { 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" } }, { name = "Dma", template_params = { peripheral = "gdma" } }, @@ -298,7 +300,7 @@ dma = true dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"] key_length = { options = [ { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, - { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 } ] } [device.dma] @@ -324,12 +326,12 @@ working_modes = [ { id = 8, mode = "modular_addition" }, { id = 9, mode = "modular_subtraction" }, { id = 10, mode = "modular_multiplication" }, - { id = 11, mode = "modular_division" }, + { id = 11, mode = "modular_division" } ] curves = [ { id = 0, curve = 192 }, { id = 1, curve = 256 }, - { id = 2, curve = 384 }, + { id = 2, curve = 384 } ] separate_jacobian_point_memory = true has_memory_clock_gate = true @@ -341,119 +343,105 @@ gpio_function = 1 constant_0_input = 0x60 constant_1_input = 0x40 pins = [ - { pin = 0, analog = { 0 = "XTAL_32K_P" }, lp = { 0 = "LP_UART_DTRN", 1 = "LP_GPIO0" } }, - { pin = 1, analog = { 0 = "XTAL_32K_N", 1 = "ADC1_CH0" }, lp = { 0 = "LP_UART_DSRN", 1 = "LP_GPIO1" } }, - { pin = 2, functions = { 0 = "MTMS", 2 = "FSPIQ" }, limitations = [ - "strapping", - ], analog = { 1 = "ADC1_CH1" }, lp = { 0 = "LP_UART_RTSN", 1 = "LP_GPIO2", 3 = "LP_I2C_SDA" } }, - { pin = 3, functions = { 0 = "MTDI" }, limitations = [ - "strapping", - ], analog = { 1 = "ADC1_CH2" }, lp = { 0 = "LP_UART_CTSN", 1 = "LP_GPIO3", 3 = "LP_I2C_SCL" } }, - { pin = 4, functions = { 0 = "MTCK", 2 = "FSPIHD" }, analog = { 1 = "ADC1_CH3" }, lp = { 0 = "LP_UART_RXD_PAD", 1 = "LP_GPIO4" } }, - { pin = 5, functions = { 0 = "MTDO", 2 = "FSPIWP" }, analog = { 1 = "ADC1_CH4" }, lp = { 0 = "LP_UART_TXD_PAD", 1 = "LP_GPIO5" } }, - { pin = 6, functions = { 2 = "FSPICLK" }, analog = { 1 = "ADC1_CH5" }, lp = { 1 = "LP_GPIO6" } }, - { pin = 7, functions = { 0 = "SDIO_DATA1", 2 = "FSPID" }, limitations = [ - "strapping", - ] }, - { pin = 8, functions = { 0 = "SDIO_DATA0" }, analog = { 0 = "ZCD0" } }, - { pin = 9, functions = { 0 = "SDIO_CLK" }, analog = { 0 = "ZCD1" } }, - { pin = 10, functions = { 0 = "SDIO_CMD", 2 = "FSPICS0" } }, - { pin = 11, functions = { 0 = "U0TXD" } }, - { pin = 12, functions = { 0 = "U0RXD" } }, - { pin = 13, functions = { 0 = "SDIO_DATA3" }, analog = { 0 = "USB_DM" } }, - { pin = 14, functions = { 0 = "SDIO_DATA2" }, analog = { 0 = "USB_DP" } }, - { pin = 23 }, - { pin = 24 }, - { pin = 25, limitations = [ - "strapping", - ] }, - { pin = 26, limitations = [ - "strapping", - ] }, - { pin = 27, limitations = [ - "strapping", - ] }, - { pin = 28, limitations = [ - "strapping", - ] }, + { pin = 0, analog = { 0 = "XTAL_32K_P" }, lp = { 0 = "LP_UART_DTRN", 1 = "LP_GPIO0" } }, + { pin = 1, analog = { 0 = "XTAL_32K_N", 1 = "ADC1_CH0" }, lp = { 0 = "LP_UART_DSRN", 1 = "LP_GPIO1" } }, + { pin = 2, functions = { 0 = "MTMS", 2 = "FSPIQ" }, limitations = ["strapping"], analog = { 1 = "ADC1_CH1" }, lp = { 0 = "LP_UART_RTSN", 1 = "LP_GPIO2", 3 = "LP_I2C_SDA" } }, + { pin = 3, functions = { 0 = "MTDI" }, limitations = ["strapping"], analog = { 1 = "ADC1_CH2" }, lp = { 0 = "LP_UART_CTSN", 1 = "LP_GPIO3", 3 = "LP_I2C_SCL" } }, + { pin = 4, functions = { 0 = "MTCK", 2 = "FSPIHD" }, analog = { 1 = "ADC1_CH3" }, lp = { 0 = "LP_UART_RXD_PAD", 1 = "LP_GPIO4" } }, + { pin = 5, functions = { 0 = "MTDO", 2 = "FSPIWP" }, analog = { 1 = "ADC1_CH4" }, lp = { 0 = "LP_UART_TXD_PAD", 1 = "LP_GPIO5" } }, + { pin = 6, functions = { 2 = "FSPICLK" }, analog = { 1 = "ADC1_CH5" }, lp = { 1 = "LP_GPIO6" } }, + { pin = 7, functions = { 0 = "SDIO_DATA1", 2 = "FSPID" }, limitations = ["strapping"] }, + { pin = 8, functions = { 0 = "SDIO_DATA0" }, analog = { 0 = "ZCD0" } }, + { pin = 9, functions = { 0 = "SDIO_CLK" }, analog = { 0 = "ZCD1" } }, + { pin = 10, functions = { 0 = "SDIO_CMD", 2 = "FSPICS0" } }, + { pin = 11, functions = { 0 = "U0TXD" } }, + { pin = 12, functions = { 0 = "U0RXD" } }, + { pin = 13, functions = { 0 = "SDIO_DATA3" }, analog = { 0 = "USB_DM" } }, + { pin = 14, functions = { 0 = "SDIO_DATA2" }, analog = { 0 = "USB_DP" } }, + { pin = 23 }, + { pin = 24 }, + { pin = 25, limitations = ["strapping"] }, + { pin = 26, limitations = ["strapping"] }, + { pin = 27, limitations = ["strapping"] }, + { pin = 28, limitations = ["strapping"] }, ] input_signals = [ - { name = "U0RXD", id = 6 }, - { name = "U0CTS", id = 7 }, - { name = "U0DSR", id = 8 }, - { name = "U1RXD", id = 9 }, - { name = "U1CTS", id = 10 }, - { name = "U1DSR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SI_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, - { name = "CPU_GPIO_0", id = 27 }, - { name = "CPU_GPIO_1", id = 28 }, - { name = "CPU_GPIO_2", id = 29 }, - { name = "CPU_GPIO_3", id = 30 }, - { name = "CPU_GPIO_4", id = 31 }, - { name = "CPU_GPIO_5", id = 32 }, - { name = "CPU_GPIO_6", id = 33 }, - { name = "CPU_GPIO_7", id = 34 }, + { name = "U0RXD", id = 6 }, + { name = "U0CTS", id = 7 }, + { name = "U0DSR", id = 8 }, + { name = "U1RXD", id = 9 }, + { name = "U1CTS", id = 10 }, + { name = "U1DSR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SI_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, + { name = "CPU_GPIO_0", id = 27 }, + { name = "CPU_GPIO_1", id = 28 }, + { name = "CPU_GPIO_2", id = 29 }, + { name = "CPU_GPIO_3", id = 30 }, + { name = "CPU_GPIO_4", id = 31 }, + { name = "CPU_GPIO_5", id = 32 }, + { name = "CPU_GPIO_6", id = 33 }, + { name = "CPU_GPIO_7", id = 34 }, { name = "USB_JTAG_TDO_BRIDGE", id = 35 }, - { name = "I2CEXT0_SCL", id = 46 }, - { name = "I2CEXT0_SDA", id = 47 }, - { name = "PARL_RX_DATA0", id = 48 }, - { name = "PARL_RX_DATA1", id = 49 }, - { name = "PARL_RX_DATA2", id = 50 }, - { name = "PARL_RX_DATA3", id = 51 }, - { name = "PARL_RX_DATA4", id = 52 }, - { name = "PARL_RX_DATA5", id = 53 }, - { name = "PARL_RX_DATA6", id = 54 }, - { name = "PARL_RX_DATA7", id = 55 }, - { name = "FSPICLK", id = 56 }, - { name = "FSPIQ", id = 57 }, - { name = "FSPID", id = 58 }, - { name = "FSPIHD", id = 59 }, - { name = "FSPIWP", id = 60 }, - { name = "FSPICS0", id = 61 }, - { name = "PARL_RX_CLK", id = 62 }, - { name = "PARL_TX_CLK", id = 63 }, - { name = "RMT_SIG_0", id = 64 }, - { name = "RMT_SIG_1", id = 65 }, - { name = "TWAI0_RX", id = 66 }, - { name = "TWAI1_RX", id = 70 }, - { name = "PCNT0_RST", id = 76 }, - { name = "PCNT1_RST", id = 77 }, - { name = "PCNT2_RST", id = 78 }, - { name = "PCNT3_RST", id = 79 }, - { name = "PWM0_SYNC0", id = 80 }, - { name = "PWM0_SYNC1", id = 81 }, - { name = "PWM0_SYNC2", id = 82 }, - { name = "PWM0_F0", id = 83 }, - { name = "PWM0_F1", id = 84 }, - { name = "PWM0_F2", id = 85 }, - { name = "PWM0_CAP0", id = 86 }, - { name = "PWM0_CAP1", id = 87 }, - { name = "PWM0_CAP2", id = 88 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "PCNT0_SIG_CH0", id = 101 }, - { name = "PCNT0_SIG_CH1", id = 102 }, - { name = "PCNT0_CTRL_CH0", id = 103 }, - { name = "PCNT0_CTRL_CH1", id = 104 }, - { name = "PCNT1_SIG_CH0", id = 105 }, - { name = "PCNT1_SIG_CH1", id = 106 }, - { name = "PCNT1_CTRL_CH0", id = 107 }, - { name = "PCNT1_CTRL_CH1", id = 108 }, - { name = "PCNT2_SIG_CH0", id = 109 }, - { name = "PCNT2_SIG_CH1", id = 110 }, - { name = "PCNT2_CTRL_CH0", id = 111 }, - { name = "PCNT2_CTRL_CH1", id = 112 }, - { name = "PCNT3_SIG_CH0", id = 113 }, - { name = "PCNT3_SIG_CH1", id = 114 }, - { name = "PCNT3_CTRL_CH0", id = 115 }, - { name = "PCNT3_CTRL_CH1", id = 116 }, + { name = "I2CEXT0_SCL", id = 46 }, + { name = "I2CEXT0_SDA", id = 47 }, + { name = "PARL_RX_DATA0", id = 48 }, + { name = "PARL_RX_DATA1", id = 49 }, + { name = "PARL_RX_DATA2", id = 50 }, + { name = "PARL_RX_DATA3", id = 51 }, + { name = "PARL_RX_DATA4", id = 52 }, + { name = "PARL_RX_DATA5", id = 53 }, + { name = "PARL_RX_DATA6", id = 54 }, + { name = "PARL_RX_DATA7", id = 55 }, + { name = "FSPICLK", id = 56 }, + { name = "FSPIQ", id = 57 }, + { name = "FSPID", id = 58 }, + { name = "FSPIHD", id = 59 }, + { name = "FSPIWP", id = 60 }, + { name = "FSPICS0", id = 61 }, + { name = "PARL_RX_CLK", id = 62 }, + { name = "PARL_TX_CLK", id = 63 }, + { name = "RMT_SIG_0", id = 64 }, + { name = "RMT_SIG_1", id = 65 }, + { name = "TWAI0_RX", id = 66 }, + { name = "TWAI1_RX", id = 70 }, + { name = "PCNT0_RST", id = 76 }, + { name = "PCNT1_RST", id = 77 }, + { name = "PCNT2_RST", id = 78 }, + { name = "PCNT3_RST", id = 79 }, + { name = "PWM0_SYNC0", id = 80 }, + { name = "PWM0_SYNC1", id = 81 }, + { name = "PWM0_SYNC2", id = 82 }, + { name = "PWM0_F0", id = 83 }, + { name = "PWM0_F1", id = 84 }, + { name = "PWM0_F2", id = 85 }, + { name = "PWM0_CAP0", id = 86 }, + { name = "PWM0_CAP1", id = 87 }, + { name = "PWM0_CAP2", id = 88 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "PCNT0_SIG_CH0", id = 101 }, + { name = "PCNT0_SIG_CH1", id = 102 }, + { name = "PCNT0_CTRL_CH0", id = 103 }, + { name = "PCNT0_CTRL_CH1", id = 104 }, + { name = "PCNT1_SIG_CH0", id = 105 }, + { name = "PCNT1_SIG_CH1", id = 106 }, + { name = "PCNT1_CTRL_CH0", id = 107 }, + { name = "PCNT1_CTRL_CH1", id = 108 }, + { name = "PCNT2_SIG_CH0", id = 109 }, + { name = "PCNT2_SIG_CH1", id = 110 }, + { name = "PCNT2_CTRL_CH0", id = 111 }, + { name = "PCNT2_CTRL_CH1", id = 112 }, + { name = "PCNT3_SIG_CH0", id = 113 }, + { name = "PCNT3_SIG_CH1", id = 114 }, + { name = "PCNT3_CTRL_CH0", id = 115 }, + { name = "PCNT3_CTRL_CH1", id = 116 }, { name = "SDIO_CLK" }, { name = "SDIO_CMD" }, @@ -468,115 +456,104 @@ input_signals = [ { name = "MTMS" }, ] output_signals = [ - { name = "LEDC_LS_SIG0", id = 0 }, - { name = "LEDC_LS_SIG1", id = 1 }, - { name = "LEDC_LS_SIG2", id = 2 }, - { name = "LEDC_LS_SIG3", id = 3 }, - { name = "LEDC_LS_SIG4", id = 4 }, - { name = "LEDC_LS_SIG5", id = 5 }, - { name = "U0TXD", id = 6 }, - { name = "U0RTS", id = 7 }, - { name = "U0DTR", id = 8 }, - { name = "U1TXD", id = 9 }, - { name = "U1RTS", id = 10 }, - { name = "U1DTR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SO_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, - { name = "I2SO_SD1", id = 18 }, - { name = "CPU_GPIO_0", id = 27 }, - { name = "CPU_GPIO_1", id = 28 }, - { name = "CPU_GPIO_2", id = 29 }, - { name = "CPU_GPIO_3", id = 30 }, - { name = "CPU_GPIO_4", id = 31 }, - { name = "CPU_GPIO_5", id = 32 }, - { name = "CPU_GPIO_6", id = 33 }, - { name = "CPU_GPIO_7", id = 34 }, - { name = "I2CEXT0_SCL", id = 46 }, - { name = "I2CEXT0_SDA", id = 47 }, - { name = "PARL_TX_DATA0", id = 48 }, - { name = "PARL_TX_DATA1", id = 49 }, - { name = "PARL_TX_DATA2", id = 50 }, - { name = "PARL_TX_DATA3", id = 51 }, - { name = "PARL_TX_DATA4", id = 52 }, - { name = "PARL_TX_DATA5", id = 53 }, - { name = "PARL_TX_DATA6", id = 54 }, - { name = "PARL_TX_DATA7", id = 55 }, - { name = "FSPICLK", id = 56 }, - { name = "FSPIQ", id = 57 }, - { name = "FSPID", id = 58 }, - { name = "FSPIHD", id = 59 }, - { name = "FSPIWP", id = 60 }, - { name = "FSPICS0", id = 61 }, - { name = "PARL_RX_CLK", id = 62 }, - { name = "PARL_TX_CLK", id = 63 }, - { name = "RMT_SIG_0", id = 64 }, - { name = "RMT_SIG_1", id = 65 }, - { name = "TWAI0_TX", id = 66 }, + { name = "LEDC_LS_SIG0", id = 0 }, + { name = "LEDC_LS_SIG1", id = 1 }, + { name = "LEDC_LS_SIG2", id = 2 }, + { name = "LEDC_LS_SIG3", id = 3 }, + { name = "LEDC_LS_SIG4", id = 4 }, + { name = "LEDC_LS_SIG5", id = 5 }, + { name = "U0TXD", id = 6 }, + { name = "U0RTS", id = 7 }, + { name = "U0DTR", id = 8 }, + { name = "U1TXD", id = 9 }, + { name = "U1RTS", id = 10 }, + { name = "U1DTR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SO_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, + { name = "I2SO_SD1", id = 18 }, + { name = "CPU_GPIO_0", id = 27 }, + { name = "CPU_GPIO_1", id = 28 }, + { name = "CPU_GPIO_2", id = 29 }, + { name = "CPU_GPIO_3", id = 30 }, + { name = "CPU_GPIO_4", id = 31 }, + { name = "CPU_GPIO_5", id = 32 }, + { name = "CPU_GPIO_6", id = 33 }, + { name = "CPU_GPIO_7", id = 34 }, + { name = "I2CEXT0_SCL", id = 46 }, + { name = "I2CEXT0_SDA", id = 47 }, + { name = "PARL_TX_DATA0", id = 48 }, + { name = "PARL_TX_DATA1", id = 49 }, + { name = "PARL_TX_DATA2", id = 50 }, + { name = "PARL_TX_DATA3", id = 51 }, + { name = "PARL_TX_DATA4", id = 52 }, + { name = "PARL_TX_DATA5", id = 53 }, + { name = "PARL_TX_DATA6", id = 54 }, + { name = "PARL_TX_DATA7", id = 55 }, + { name = "FSPICLK", id = 56 }, + { name = "FSPIQ", id = 57 }, + { name = "FSPID", id = 58 }, + { name = "FSPIHD", id = 59 }, + { name = "FSPIWP", id = 60 }, + { name = "FSPICS0", id = 61 }, + { name = "PARL_RX_CLK", id = 62 }, + { name = "PARL_TX_CLK", id = 63 }, + { name = "RMT_SIG_0", id = 64 }, + { name = "RMT_SIG_1", id = 65 }, + { name = "TWAI0_TX", id = 66 }, { name = "TWAI0_BUS_OFF_ON", id = 67 }, - { name = "TWAI0_CLKOUT", id = 68 }, - { name = "TWAI0_STANDBY", id = 69 }, - { name = "TWAI1_TX", id = 70 }, + { name = "TWAI0_CLKOUT", id = 68 }, + { name = "TWAI0_STANDBY", id = 69 }, + { name = "TWAI1_TX", id = 70 }, { name = "TWAI1_BUS_OFF_ON", id = 71 }, - { name = "TWAI1_CLKOUT", id = 72 }, - { name = "TWAI1_STANDBY", id = 73 }, - { name = "GPIO_SD0", id = 76 }, - { name = "GPIO_SD1", id = 77 }, - { name = "GPIO_SD2", id = 78 }, - { name = "GPIO_SD3", id = 79 }, - { name = "PWM0_0A", id = 80 }, - { name = "PWM0_0B", id = 81 }, - { name = "PWM0_1A", id = 82 }, - { name = "PWM0_1B", id = 83 }, - { name = "PWM0_2A", id = 84 }, - { name = "PWM0_2B", id = 85 }, - { name = "PARL_TX_CS", id = 86 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "FSPICS1", id = 101 }, - { name = "FSPICS2", id = 102 }, - { name = "FSPICS3", id = 103 }, - { name = "FSPICS4", id = 104 }, - { name = "FSPICS5", id = 105 }, - { name = "GPIO", id = 256 }, + { name = "TWAI1_CLKOUT", id = 72 }, + { name = "TWAI1_STANDBY", id = 73 }, + { name = "GPIO_SD0", id = 76 }, + { name = "GPIO_SD1", id = 77 }, + { name = "GPIO_SD2", id = 78 }, + { name = "GPIO_SD3", id = 79 }, + { name = "PWM0_0A", id = 80 }, + { name = "PWM0_0B", id = 81 }, + { name = "PWM0_1A", id = 82 }, + { name = "PWM0_1B", id = 83 }, + { name = "PWM0_2A", id = 84 }, + { name = "PWM0_2B", id = 85 }, + { name = "PARL_TX_CS", id = 86 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "FSPICS1", id = 101 }, + { name = "FSPICS2", id = 102 }, + { name = "FSPICS3", id = 103 }, + { name = "FSPICS4", id = 104 }, + { name = "FSPICS5", id = 105 }, + { name = "GPIO", id = 256 } ] [device.dedicated_gpio] support_status = "partial" -channels = [ - [ - "CPU_GPIO_0", - "CPU_GPIO_1", - "CPU_GPIO_2", - "CPU_GPIO_3", - "CPU_GPIO_4", - "CPU_GPIO_5", - "CPU_GPIO_6", - "CPU_GPIO_7", - ], -] +channels = [["CPU_GPIO_0", "CPU_GPIO_1", "CPU_GPIO_2", "CPU_GPIO_3", "CPU_GPIO_4", "CPU_GPIO_5", "CPU_GPIO_6", "CPU_GPIO_7"]] [device.i2c_master] support_status = "supported" instances = [ { name = "i2c0", sys_instance = "I2cExt0", scl = "I2CEXT0_SCL", sda = "I2CEXT0_SDA" }, ] -has_fsm_timeouts = true # why not S2? -# has_hw_bus_clear = true +has_fsm_timeouts = true +has_hw_bus_clear = true # I2C_SCL_SP_CONF_REG is present ll_intr_mask = 0x3ffff fifo_size = 32 has_bus_timeout_enable = true max_bus_timeout = 0x1F -can_estimate_nack_reason = true # not documented +can_estimate_nack_reason = true # txfifo_raddr is present has_conf_update = true has_reliable_fsm_reset = true has_arbitration_en = true -has_tx_fifo_watermark = true # why not s2 +has_tx_fifo_watermark = true bus_timeout_is_exponential = true [device.i2c_slave] @@ -596,7 +573,7 @@ algo = { sha1 = 0, sha224 = 1, sha256 = 2 } support_status = "partial" status_registers = 3 software_interrupt_count = 4 -software_interrupt_delay = 24 # CPU speed dependent +software_interrupt_delay = 24 # CPU speed dependent controller = { Riscv = { flavour = "clic", interrupts = 48, priority_levels = 8 } } [device.rmt] @@ -621,19 +598,7 @@ has_app_interrupts = true has_dma_segmented_transfer = true has_clk_pre_div = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = [ - "FSPID", - "FSPIQ", - "FSPIWP", - "FSPIHD", - ], cs = [ - "FSPICS0", - "FSPICS1", - "FSPICS2", - "FSPICS3", - "FSPICS4", - "FSPICS5", - ] }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = ["FSPID", "FSPIQ", "FSPIWP", "FSPIHD"], cs = ["FSPICS0", "FSPICS1", "FSPICS2", "FSPICS3", "FSPICS4", "FSPICS5"] }, ] [device.spi_slave] @@ -692,8 +657,8 @@ fifo_size = 16 [device.rng] support_status = "partial" -trng_supported = false # TODO -apb_cycle_wait_num = 16 # TODO +trng_supported = false # TODO +apb_cycle_wait_num = 16 # TODO ## Radio [device.wifi] @@ -744,7 +709,6 @@ support_status = { status = "not_supported", issue = 5172 } [device.io_mux] [device.psram] -support_status = { status = "not_supported", issue = 5141 } [device.sd_slave] support_status = { status = "not_supported", issue = 5169 } @@ -756,4 +720,4 @@ support_status = { status = "not_supported", issue = 5160 } support_status = { status = "not_supported", issue = 5162 } [device.temp_sensor] -support_status = { status = "not_supported", issue = 5153 } +support_status = { status = "not_supported", issue = 5153 } \ No newline at end of file diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index cfe301a9c82..cf9e118d962 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -6,11 +6,11 @@ # update the table in the esp-hal README. [device] -name = "esp32c6" -arch = "riscv" +name = "esp32c6" +arch = "riscv" target = "riscv32imac-unknown-none-elf" -cores = 1 -trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf" +cores = 1 +trm = "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf" symbols = [ # Additional peripherals defined by us (the developers): @@ -144,48 +144,33 @@ peripherals = [ clocks = { system_clocks = { clock_tree = [ # High-speed clock sources - { name = "XTAL_CLK", type = "source", values = "40", output = "VALUE * 1_000_000", always_on = true }, - { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, - { name = "RC_FAST_CLK", type = "source", output = "17_500_000" }, + { name = "XTAL_CLK", type = "source", values = "40", output = "VALUE * 1_000_000", always_on = true }, + { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, + { name = "RC_FAST_CLK", type = "source", output = "17_500_000" }, # Low-speed clocks - { name = "XTAL32K_CLK", type = "source", output = "32768" }, - { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, - { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, { name = "SOC_ROOT_CLK", type = "mux", variants = [ - { name = "XTAL", outputs = "XTAL_CLK", configures = [ - "HP_ROOT_CLK = 1", - "CPU_CLK = LS", - "AHB_CLK = LS", - "MSPI_FAST_CLK = LS", - ] }, - { name = "RC_FAST", outputs = "RC_FAST_CLK", configures = [ - "HP_ROOT_CLK = 1", - "CPU_CLK = LS", - "AHB_CLK = LS", - "MSPI_FAST_CLK = LS", - ] }, - { name = "PLL", outputs = "PLL_CLK", configures = [ - "HP_ROOT_CLK = 3", - "CPU_CLK = HS", - "AHB_CLK = HS", - "MSPI_FAST_CLK = HS", - ] }, + { name = "XTAL", outputs = "XTAL_CLK", configures = ["HP_ROOT_CLK = 1", "CPU_CLK = LS", "AHB_CLK = LS", "MSPI_FAST_CLK = LS"] }, + { name = "RC_FAST", outputs = "RC_FAST_CLK", configures = ["HP_ROOT_CLK = 1", "CPU_CLK = LS", "AHB_CLK = LS", "MSPI_FAST_CLK = LS"] }, + { name = "PLL", outputs = "PLL_CLK", configures = ["HP_ROOT_CLK = 3", "CPU_CLK = HS", "AHB_CLK = HS", "MSPI_FAST_CLK = HS"] }, ] }, { name = "HP_ROOT_CLK", type = "generic", params = { divisor = "1, 3" }, output = "SOC_ROOT_CLK / divisor" }, # AUTO_DIV, only divides when using PLL_CLK # TODO: model by-4 divider for 120MHz CPU clock { name = "CPU_HS_DIV", type = "generic", params = { divisor = "0, 1, 3" }, output = "HP_ROOT_CLK / (divisor + 1)" }, { name = "CPU_LS_DIV", type = "generic", params = { divisor = "0, 1, 3, 7, 15, 31" }, output = "HP_ROOT_CLK / (divisor + 1)" }, - { name = "CPU_CLK", type = "mux", always_on = true, variants = [ + { name = "CPU_CLK", type = "mux", always_on = true, variants = [ { name = "HS", outputs = "CPU_HS_DIV" }, { name = "LS", outputs = "CPU_LS_DIV" }, ] }, { name = "AHB_HS_DIV", type = "generic", params = { divisor = "3, 7, 15" }, output = "HP_ROOT_CLK / (divisor + 1)" }, { name = "AHB_LS_DIV", type = "generic", params = { divisor = "0, 1, 3, 7, 15, 31" }, output = "HP_ROOT_CLK / (divisor + 1)" }, - { name = "AHB_CLK", type = "mux", always_on = true, variants = [ + { name = "AHB_CLK", type = "mux", always_on = true, variants = [ { name = "HS", outputs = "AHB_HS_DIV" }, { name = "LS", outputs = "AHB_LS_DIV" }, ] }, @@ -195,19 +180,19 @@ clocks = { system_clocks = { clock_tree = [ { name = "MSPI_FAST_HS_CLK", type = "generic", params = { divisor = "3, 4, 5" }, output = "HP_ROOT_CLK / (divisor + 1)" }, { name = "MSPI_FAST_LS_CLK", type = "generic", params = { divisor = "0, 1, 2" }, output = "HP_ROOT_CLK / (divisor + 1)" }, - { name = "MSPI_FAST_CLK", type = "mux", variants = [ + { name = "MSPI_FAST_CLK", type = "mux", variants = [ { name = "HS", outputs = "MSPI_FAST_HS_CLK" }, { name = "LS", outputs = "MSPI_FAST_LS_CLK" }, ] }, - { name = "PLL_F48M", type = "derived", from = "PLL_CLK", output = "48_000_000" }, - { name = "PLL_F80M", type = "derived", from = "PLL_CLK", output = "80_000_000" }, + { name = "PLL_F48M", type = "derived", from = "PLL_CLK", output = "48_000_000" }, + { name = "PLL_F80M", type = "derived", from = "PLL_CLK", output = "80_000_000" }, { name = "PLL_F160M", type = "derived", from = "PLL_CLK", output = "160_000_000" }, { name = "PLL_F240M", type = "derived", from = "PLL_CLK", output = "240_000_000" }, { name = "LEDC_SCLK", type = "mux", variants = [ - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, # LP clocks @@ -217,8 +202,8 @@ clocks = { system_clocks = { clock_tree = [ { name = "XTAL_D2_CLK", outputs = "XTAL_D2_CLK" }, ] }, { name = "LP_SLOW_CLK", type = "mux", variants = [ - { name = "XTAL32K", outputs = "XTAL32K_CLK" }, - { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, { name = "OSC_SLOW", outputs = "OSC_SLOW_CLK" }, ] }, # LP_DYN_SLOW_CLK is LP_SLOW_CLK @@ -227,63 +212,63 @@ clocks = { system_clocks = { clock_tree = [ # There are separate clock muxes for each TIMG instance, but esp-hal only uses one. Only modelling # one makes the HAL code simpler. { name = "TIMG_CALIBRATION_CLOCK", type = "mux", variants = [ - { name = "RC_SLOW_CLK", outputs = "LP_SLOW_CLK" }, + { name = "RC_SLOW_CLK", outputs = "LP_SLOW_CLK" }, { name = "RC_FAST_DIV_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, + { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, ] }, ], template_groups = [ { group = "UART", clocks = [ { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ { name = "PLL_F80M", outputs = "PLL_F80M" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK", default = true }, ], div_num = "0 .. 0x100" } }, { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, ] }, { group = "RMT", clocks = [ { name = "SCLK", type = "mux", variants = [ - { name = "PLL_F80M", outputs = "PLL_F80M", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, ] }, { group = "TIMG", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, ] }, { name = "WDT_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, - { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, ] }, ] }, { group = "MCPWM", clocks = [ # TODO: MCPWM divider? { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "PLL_F160M", outputs = "PLL_F160M", default = true }, + { name = "PLL_F160M", outputs = "PLL_F160M", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, ] }, { group = "PARL_IO", clocks = [ { name = "RX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, + { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, # TODO: external clock ] }, { name = "TX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, + { name = "PLL_F240M", outputs = "PLL_F240M", default = true }, ] }, ] }, ] }, peripheral_clocks = { templates = [ # templates { name = "default_clk_en_template", value = "{{control}}::regs().{{conf_register}}().modify(|_, w| w.{{clk_en_field}}().bit(enable));" }, - { name = "clk_en_template", value = "{{default_clk_en_template}}" }, # Indirection allows appending to the template for TWAI + { name = "clk_en_template", value = "{{default_clk_en_template}}" }, # Indirection allows appending to the template for TWAI { name = "rst_template", value = "{{control}}::regs().{{conf_register}}().modify(|_, w| w.{{rst_field}}().bit(reset));" }, # substitutions { name = "control", value = "crate::peripherals::SYSTEM" }, @@ -305,7 +290,7 @@ clocks = { system_clocks = { clock_tree = [ { name = "Twai0", template_params = { clk_en_template = "{{default_clk_en_template}} {{func_clk_template}}", func_clk_template = "{{control}}::regs().twai0_func_clk_conf().modify(|_, w| w.twai0_func_clk_en().bit(enable));" } }, { name = "Twai1", template_params = { clk_en_template = "{{default_clk_en_template}} {{func_clk_template}}", func_clk_template = "{{control}}::regs().twai1_func_clk_conf().modify(|_, w| w.twai1_func_clk_en().bit(enable));" } }, { name = "I2s0", template_params = { peripheral = "i2s" } }, - { name = "ApbSarAdc", template_params = { peripheral = "saradc", clk_en_field = "saradc_reg_clk_en", rst_field = "saradc_reg_rst_en" }, keep_enabled = true }, # used by some wifi calibration steps. + { name = "ApbSarAdc", template_params = { peripheral = "saradc", clk_en_field = "saradc_reg_clk_en", rst_field = "saradc_reg_rst_en" }, keep_enabled = true }, # used by some wifi calibration steps. { name = "Tsens", template_params = { conf_register = "tsens_clk_conf" } }, { name = "UsbDevice", keep_enabled = true }, # { name = "Intmtx" }, @@ -329,13 +314,15 @@ clocks = { system_clocks = { clock_tree = [ #{ name = "Cache" }, #{ name = "ModemApb" }, #{ name = "Timeout" }, - + # Radio clocks not modeled here. ] } } [device.adc] support_status = "partial" -instances = [{ name = "adc1" }] +instances = [ + { name = "adc1" }, +] [device.aes] support_status = "partial" @@ -345,7 +332,7 @@ dma = true dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"] key_length = { options = [ { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, - { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 } ] } [device.assist_debug] @@ -369,9 +356,12 @@ working_modes = [ { id = 3, mode = "affine_point_verification_and_multiplication" }, { id = 4, mode = "jacobian_point_multiplication" }, { id = 6, mode = "jacobian_point_verification" }, - { id = 7, mode = "affine_point_verification_and_jacobian_point_multiplication" }, + { id = 7, mode = "affine_point_verification_and_jacobian_point_multiplication" } +] +curves = [ + { id = 0, curve = 192 }, + { id = 1, curve = 256 } ] -curves = [{ id = 0, curve = 192 }, { id = 1, curve = 256 }] zero_extend_writes = true has_memory_clock_gate = true @@ -381,160 +371,136 @@ gpio_function = 1 constant_0_input = 0x3c constant_1_input = 0x38 pins = [ - { pin = 0, analog = { 0 = "XTAL_32K_P", 1 = "ADC0_CH0" }, lp = { 0 = "LP_GPIO0", 1 = "LP_UART_DTRN" } }, - { pin = 1, analog = { 0 = "XTAL_32K_N", 1 = "ADC0_CH1" }, lp = { 0 = "LP_GPIO1", 1 = "LP_UART_DSRN" } }, - { pin = 2, functions = { 2 = "FSPIQ" }, analog = { 1 = "ADC0_CH2" }, lp = { 0 = "LP_GPIO2", 1 = "LP_UART_RTSN" } }, - { pin = 3, analog = { 1 = "ADC0_CH3" }, lp = { 0 = "LP_GPIO3", 1 = "LP_UART_CTSN" } }, - { pin = 4, functions = { 0 = "MTMS", 2 = "FSPIHD" }, limitations = [ - "strapping", - ], analog = { 1 = "ADC0_CH4" }, lp = { 0 = "LP_GPIO4", 1 = "LP_UART_RXD" } }, - { pin = 5, functions = { 0 = "MTDI", 2 = "FSPIWP" }, limitations = [ - "strapping", - ], analog = { 1 = "ADC0_CH5" }, lp = { 0 = "LP_GPIO5", 1 = "LP_UART_TXD" } }, - { pin = 6, functions = { 0 = "MTCK", 2 = "FSPICLK" }, analog = { 1 = "ADC0_CH6" }, lp = { 0 = "LP_GPIO6", 1 = "LP_I2C_SDA" } }, - { pin = 7, functions = { 0 = "MTDO", 2 = "FSPID" }, lp = { 0 = "LP_GPIO7", 1 = "LP_I2C_SCL" } }, - { pin = 8, limitations = [ - "strapping", - ] }, - { pin = 9, limitations = [ - "strapping", - ] }, + { pin = 0, analog = { 0 = "XTAL_32K_P", 1 = "ADC0_CH0" }, lp = { 0 = "LP_GPIO0", 1 = "LP_UART_DTRN" } }, + { pin = 1, analog = { 0 = "XTAL_32K_N", 1 = "ADC0_CH1" }, lp = { 0 = "LP_GPIO1", 1 = "LP_UART_DSRN" } }, + { pin = 2, functions = { 2 = "FSPIQ" }, analog = { 1 = "ADC0_CH2" }, lp = { 0 = "LP_GPIO2", 1 = "LP_UART_RTSN" } }, + { pin = 3, analog = { 1 = "ADC0_CH3" }, lp = { 0 = "LP_GPIO3", 1 = "LP_UART_CTSN" } }, + { pin = 4, functions = { 0 = "MTMS", 2 = "FSPIHD" }, limitations = ["strapping"], analog = { 1 = "ADC0_CH4" }, lp = { 0 = "LP_GPIO4", 1 = "LP_UART_RXD" } }, + { pin = 5, functions = { 0 = "MTDI", 2 = "FSPIWP" }, limitations = ["strapping"], analog = { 1 = "ADC0_CH5" }, lp = { 0 = "LP_GPIO5", 1 = "LP_UART_TXD" } }, + { pin = 6, functions = { 0 = "MTCK", 2 = "FSPICLK" }, analog = { 1 = "ADC0_CH6" }, lp = { 0 = "LP_GPIO6", 1 = "LP_I2C_SDA" } }, + { pin = 7, functions = { 0 = "MTDO", 2 = "FSPID" }, lp = { 0 = "LP_GPIO7", 1 = "LP_I2C_SCL" } }, + { pin = 8, limitations = ["strapping"] }, + { pin = 9, limitations = ["strapping"] }, { pin = 10 }, { pin = 11 }, { pin = 12, analog = { 0 = "USB_DM" } }, { pin = 13, analog = { 0 = "USB_DP" } }, { pin = 14 }, - { pin = 15, limitations = [ - "strapping", - ] }, - { pin = 16, functions = { 0 = "U0TXD", 2 = "FSPICS0" } }, - { pin = 17, functions = { 0 = "U0RXD", 2 = "FSPICS1" } }, - { pin = 18, functions = { 0 = "SDIO_CMD", 2 = "FSPICS2" } }, - { pin = 19, functions = { 0 = "SDIO_CLK", 2 = "FSPICS3" } }, + { pin = 15, limitations = ["strapping"] }, + { pin = 16, functions = { 0 = "U0TXD", 2 = "FSPICS0" } }, + { pin = 17, functions = { 0 = "U0RXD", 2 = "FSPICS1" } }, + { pin = 18, functions = { 0 = "SDIO_CMD", 2 = "FSPICS2" } }, + { pin = 19, functions = { 0 = "SDIO_CLK", 2 = "FSPICS3" } }, { pin = 20, functions = { 0 = "SDIO_DATA0", 2 = "FSPICS4" } }, { pin = 21, functions = { 0 = "SDIO_DATA1", 2 = "FSPICS5" } }, { pin = 22, functions = { 0 = "SDIO_DATA2" } }, { pin = 23, functions = { 0 = "SDIO_DATA3" } }, - { pin = 24, functions = { 0 = "SPICS0" }, limitations = [ - "spi_flash", - ] }, - { pin = 25, functions = { 0 = "SPIQ" }, limitations = [ - "spi_flash", - ] }, - { pin = 26, functions = { 0 = "SPIWP" }, limitations = [ - "spi_flash", - ] }, - { pin = 27, limitations = [ - "spi_flash", - ] }, - { pin = 28, functions = { 0 = "SPIHD" }, limitations = [ - "spi_flash", - ] }, - { pin = 29, functions = { 0 = "SPICLK" }, limitations = [ - "spi_flash", - ] }, - { pin = 30, functions = { 0 = "SPID" }, limitations = [ - "spi_flash", - ] }, + { pin = 24, functions = { 0 = "SPICS0" }, limitations = ["spi_flash"] }, + { pin = 25, functions = { 0 = "SPIQ" }, limitations = ["spi_flash"] }, + { pin = 26, functions = { 0 = "SPIWP" }, limitations = ["spi_flash"] }, + { pin = 27, limitations = ["spi_flash"] }, + { pin = 28, functions = { 0 = "SPIHD" }, limitations = ["spi_flash"] }, + { pin = 29, functions = { 0 = "SPICLK" }, limitations = ["spi_flash"] }, + { pin = 30, functions = { 0 = "SPID" }, limitations = ["spi_flash"] }, ] input_signals = [ - { name = "EXT_ADC_START", id = 0 }, - { name = "U0RXD", id = 6 }, - { name = "U0CTS", id = 7 }, - { name = "U0DSR", id = 8 }, - { name = "U1RXD", id = 9 }, - { name = "U1CTS", id = 10 }, - { name = "U1DSR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SI_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, + { name = "EXT_ADC_START", id = 0 }, + { name = "U0RXD", id = 6 }, + { name = "U0CTS", id = 7 }, + { name = "U0DSR", id = 8 }, + { name = "U1RXD", id = 9 }, + { name = "U1CTS", id = 10 }, + { name = "U1DSR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SI_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, { name = "USB_JTAG_TDO_BRIDGE", id = 19 }, - { name = "CPU_TESTBUS0", id = 20 }, - { name = "CPU_TESTBUS1", id = 21 }, - { name = "CPU_TESTBUS2", id = 22 }, - { name = "CPU_TESTBUS3", id = 23 }, - { name = "CPU_TESTBUS4", id = 24 }, - { name = "CPU_TESTBUS5", id = 25 }, - { name = "CPU_TESTBUS6", id = 26 }, - { name = "CPU_TESTBUS7", id = 27 }, - { name = "CPU_GPIO_0", id = 28 }, - { name = "CPU_GPIO_1", id = 29 }, - { name = "CPU_GPIO_2", id = 30 }, - { name = "CPU_GPIO_3", id = 31 }, - { name = "CPU_GPIO_4", id = 32 }, - { name = "CPU_GPIO_5", id = 33 }, - { name = "CPU_GPIO_6", id = 34 }, - { name = "CPU_GPIO_7", id = 35 }, - { name = "USB_JTAG_TMS", id = 37 }, - { name = "USB_EXTPHY_OEN", id = 40 }, - { name = "USB_EXTPHY_VM", id = 41 }, - { name = "USB_EXTPHY_VPO", id = 42 }, - { name = "I2CEXT0_SCL", id = 45 }, - { name = "I2CEXT0_SDA", id = 46 }, - { name = "PARL_RX_DATA0", id = 47 }, - { name = "PARL_RX_DATA1", id = 48 }, - { name = "PARL_RX_DATA2", id = 49 }, - { name = "PARL_RX_DATA3", id = 50 }, - { name = "PARL_RX_DATA4", id = 51 }, - { name = "PARL_RX_DATA5", id = 52 }, - { name = "PARL_RX_DATA6", id = 53 }, - { name = "PARL_RX_DATA7", id = 54 }, - { name = "PARL_RX_DATA8", id = 55 }, - { name = "PARL_RX_DATA9", id = 56 }, - { name = "PARL_RX_DATA10", id = 57 }, - { name = "PARL_RX_DATA11", id = 58 }, - { name = "PARL_RX_DATA12", id = 59 }, - { name = "PARL_RX_DATA13", id = 60 }, - { name = "PARL_RX_DATA14", id = 61 }, - { name = "PARL_RX_DATA15", id = 62 }, - { name = "FSPICLK", id = 63 }, - { name = "FSPIQ", id = 64 }, - { name = "FSPID", id = 65 }, - { name = "FSPIHD", id = 66 }, - { name = "FSPIWP", id = 67 }, - { name = "FSPICS0", id = 68 }, - { name = "PARL_RX_CLK", id = 69 }, - { name = "PARL_TX_CLK", id = 70 }, - { name = "RMT_SIG_0", id = 71 }, - { name = "RMT_SIG_1", id = 72 }, - { name = "TWAI0_RX", id = 73 }, - { name = "TWAI1_RX", id = 77 }, - { name = "PWM0_SYNC0", id = 87 }, - { name = "PWM0_SYNC1", id = 88 }, - { name = "PWM0_SYNC2", id = 89 }, - { name = "PWM0_F0", id = 90 }, - { name = "PWM0_F1", id = 91 }, - { name = "PWM0_F2", id = 92 }, - { name = "PWM0_CAP0", id = 93 }, - { name = "PWM0_CAP1", id = 94 }, - { name = "PWM0_CAP2", id = 95 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "PCNT0_SIG_CH0", id = 101 }, - { name = "PCNT0_SIG_CH1", id = 102 }, - { name = "PCNT0_CTRL_CH0", id = 103 }, - { name = "PCNT0_CTRL_CH1", id = 104 }, - { name = "PCNT1_SIG_CH0", id = 105 }, - { name = "PCNT1_SIG_CH1", id = 106 }, - { name = "PCNT1_CTRL_CH0", id = 107 }, - { name = "PCNT1_CTRL_CH1", id = 108 }, - { name = "PCNT2_SIG_CH0", id = 109 }, - { name = "PCNT2_SIG_CH1", id = 110 }, - { name = "PCNT2_CTRL_CH0", id = 111 }, - { name = "PCNT2_CTRL_CH1", id = 112 }, - { name = "PCNT3_SIG_CH0", id = 113 }, - { name = "PCNT3_SIG_CH1", id = 114 }, - { name = "PCNT3_CTRL_CH0", id = 115 }, - { name = "PCNT3_CTRL_CH1", id = 116 }, - { name = "SPIQ", id = 121 }, - { name = "SPID", id = 122 }, - { name = "SPIHD", id = 123 }, - { name = "SPIWP", id = 124 }, + { name = "CPU_TESTBUS0", id = 20 }, + { name = "CPU_TESTBUS1", id = 21 }, + { name = "CPU_TESTBUS2", id = 22 }, + { name = "CPU_TESTBUS3", id = 23 }, + { name = "CPU_TESTBUS4", id = 24 }, + { name = "CPU_TESTBUS5", id = 25 }, + { name = "CPU_TESTBUS6", id = 26 }, + { name = "CPU_TESTBUS7", id = 27 }, + { name = "CPU_GPIO_0", id = 28 }, + { name = "CPU_GPIO_1", id = 29 }, + { name = "CPU_GPIO_2", id = 30 }, + { name = "CPU_GPIO_3", id = 31 }, + { name = "CPU_GPIO_4", id = 32 }, + { name = "CPU_GPIO_5", id = 33 }, + { name = "CPU_GPIO_6", id = 34 }, + { name = "CPU_GPIO_7", id = 35 }, + { name = "USB_JTAG_TMS", id = 37 }, + { name = "USB_EXTPHY_OEN", id = 40 }, + { name = "USB_EXTPHY_VM", id = 41 }, + { name = "USB_EXTPHY_VPO", id = 42 }, + { name = "I2CEXT0_SCL", id = 45 }, + { name = "I2CEXT0_SDA", id = 46 }, + { name = "PARL_RX_DATA0", id = 47 }, + { name = "PARL_RX_DATA1", id = 48 }, + { name = "PARL_RX_DATA2", id = 49 }, + { name = "PARL_RX_DATA3", id = 50 }, + { name = "PARL_RX_DATA4", id = 51 }, + { name = "PARL_RX_DATA5", id = 52 }, + { name = "PARL_RX_DATA6", id = 53 }, + { name = "PARL_RX_DATA7", id = 54 }, + { name = "PARL_RX_DATA8", id = 55 }, + { name = "PARL_RX_DATA9", id = 56 }, + { name = "PARL_RX_DATA10", id = 57 }, + { name = "PARL_RX_DATA11", id = 58 }, + { name = "PARL_RX_DATA12", id = 59 }, + { name = "PARL_RX_DATA13", id = 60 }, + { name = "PARL_RX_DATA14", id = 61 }, + { name = "PARL_RX_DATA15", id = 62 }, + { name = "FSPICLK", id = 63 }, + { name = "FSPIQ", id = 64 }, + { name = "FSPID", id = 65 }, + { name = "FSPIHD", id = 66 }, + { name = "FSPIWP", id = 67 }, + { name = "FSPICS0", id = 68 }, + { name = "PARL_RX_CLK", id = 69 }, + { name = "PARL_TX_CLK", id = 70 }, + { name = "RMT_SIG_0", id = 71 }, + { name = "RMT_SIG_1", id = 72 }, + { name = "TWAI0_RX", id = 73 }, + { name = "TWAI1_RX", id = 77 }, + { name = "PWM0_SYNC0", id = 87 }, + { name = "PWM0_SYNC1", id = 88 }, + { name = "PWM0_SYNC2", id = 89 }, + { name = "PWM0_F0", id = 90 }, + { name = "PWM0_F1", id = 91 }, + { name = "PWM0_F2", id = 92 }, + { name = "PWM0_CAP0", id = 93 }, + { name = "PWM0_CAP1", id = 94 }, + { name = "PWM0_CAP2", id = 95 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "PCNT0_SIG_CH0", id = 101 }, + { name = "PCNT0_SIG_CH1", id = 102 }, + { name = "PCNT0_CTRL_CH0", id = 103 }, + { name = "PCNT0_CTRL_CH1", id = 104 }, + { name = "PCNT1_SIG_CH0", id = 105 }, + { name = "PCNT1_SIG_CH1", id = 106 }, + { name = "PCNT1_CTRL_CH0", id = 107 }, + { name = "PCNT1_CTRL_CH1", id = 108 }, + { name = "PCNT2_SIG_CH0", id = 109 }, + { name = "PCNT2_SIG_CH1", id = 110 }, + { name = "PCNT2_CTRL_CH0", id = 111 }, + { name = "PCNT2_CTRL_CH1", id = 112 }, + { name = "PCNT3_SIG_CH0", id = 113 }, + { name = "PCNT3_SIG_CH1", id = 114 }, + { name = "PCNT3_CTRL_CH0", id = 115 }, + { name = "PCNT3_CTRL_CH1", id = 116 }, + { name = "SPIQ", id = 121 }, + { name = "SPID", id = 122 }, + { name = "SPIHD", id = 123 }, + { name = "SPIWP", id = 124 }, { name = "SDIO_CMD" }, { name = "SDIO_DATA0" }, @@ -547,116 +513,116 @@ input_signals = [ { name = "MTMS" }, ] output_signals = [ - { name = "LEDC_LS_SIG0", id = 0 }, - { name = "LEDC_LS_SIG1", id = 1 }, - { name = "LEDC_LS_SIG2", id = 2 }, - { name = "LEDC_LS_SIG3", id = 3 }, - { name = "LEDC_LS_SIG4", id = 4 }, - { name = "LEDC_LS_SIG5", id = 5 }, - { name = "U0TXD", id = 6 }, - { name = "U0RTS", id = 7 }, - { name = "U0DTR", id = 8 }, - { name = "U1TXD", id = 9 }, - { name = "U1RTS", id = 10 }, - { name = "U1DTR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SO_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, - { name = "I2SO_SD1", id = 18 }, - { name = "USB_JTAG_TDO_BRIDGE", id = 19 }, - { name = "CPU_TESTBUS0", id = 20 }, - { name = "CPU_TESTBUS1", id = 21 }, - { name = "CPU_TESTBUS2", id = 22 }, - { name = "CPU_TESTBUS3", id = 23 }, - { name = "CPU_TESTBUS4", id = 24 }, - { name = "CPU_TESTBUS5", id = 25 }, - { name = "CPU_TESTBUS6", id = 26 }, - { name = "CPU_TESTBUS7", id = 27 }, - { name = "CPU_GPIO_0", id = 28 }, - { name = "CPU_GPIO_1", id = 29 }, - { name = "CPU_GPIO_2", id = 30 }, - { name = "CPU_GPIO_3", id = 31 }, - { name = "CPU_GPIO_4", id = 32 }, - { name = "CPU_GPIO_5", id = 33 }, - { name = "CPU_GPIO_6", id = 34 }, - { name = "CPU_GPIO_7", id = 35 }, - { name = "USB_JTAG_TCK", id = 36 }, - { name = "USB_JTAG_TMS", id = 37 }, - { name = "USB_JTAG_TDI", id = 38 }, - { name = "USB_JTAG_TDO", id = 39 }, - { name = "I2CEXT0_SCL", id = 45 }, - { name = "I2CEXT0_SDA", id = 46 }, - { name = "PARL_TX_DATA0", id = 47 }, - { name = "PARL_TX_DATA1", id = 48 }, - { name = "PARL_TX_DATA2", id = 49 }, - { name = "PARL_TX_DATA3", id = 50 }, - { name = "PARL_TX_DATA4", id = 51 }, - { name = "PARL_TX_DATA5", id = 52 }, - { name = "PARL_TX_DATA6", id = 53 }, - { name = "PARL_TX_DATA7", id = 54 }, - { name = "PARL_TX_DATA8", id = 55 }, - { name = "PARL_TX_DATA9", id = 56 }, - { name = "PARL_TX_DATA10", id = 57 }, - { name = "PARL_TX_DATA11", id = 58 }, - { name = "PARL_TX_DATA12", id = 59 }, - { name = "PARL_TX_DATA13", id = 60 }, - { name = "PARL_TX_DATA14", id = 61 }, - { name = "PARL_TX_DATA15", id = 62 }, - { name = "FSPICLK", id = 63 }, - { name = "FSPIQ", id = 64 }, - { name = "FSPID", id = 65 }, - { name = "FSPIHD", id = 66 }, - { name = "FSPIWP", id = 67 }, - { name = "FSPICS0", id = 68 }, - { name = "SDIO_TOHOST_INT", id = 69 }, - { name = "PARL_TX_CLK", id = 70 }, - { name = "RMT_SIG_0", id = 71 }, - { name = "RMT_SIG_1", id = 72 }, - { name = "TWAI0_TX", id = 73 }, - { name = "TWAI0_BUS_OFF_ON", id = 74 }, - { name = "TWAI0_CLKOUT", id = 75 }, - { name = "TWAI0_STANDBY", id = 76 }, - { name = "TWAI1_TX", id = 77 }, - { name = "TWAI1_BUS_OFF_ON", id = 78 }, - { name = "TWAI1_CLKOUT", id = 79 }, - { name = "TWAI1_STANDBY", id = 80 }, - { name = "GPIO_SD0", id = 83 }, - { name = "GPIO_SD1", id = 84 }, - { name = "GPIO_SD2", id = 85 }, - { name = "GPIO_SD3", id = 86 }, - { name = "PWM0_0A", id = 87 }, - { name = "PWM0_0B", id = 88 }, - { name = "PWM0_1A", id = 89 }, - { name = "PWM0_1B", id = 90 }, - { name = "PWM0_2A", id = 91 }, - { name = "PWM0_2B", id = 92 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "FSPICS1", id = 101 }, - { name = "FSPICS2", id = 102 }, - { name = "FSPICS3", id = 103 }, - { name = "FSPICS4", id = 104 }, - { name = "FSPICS5", id = 105 }, - { name = "SPICLK", id = 114 }, - { name = "SPICS0", id = 115 }, - { name = "SPICS1", id = 116 }, + { name = "LEDC_LS_SIG0", id = 0 }, + { name = "LEDC_LS_SIG1", id = 1 }, + { name = "LEDC_LS_SIG2", id = 2 }, + { name = "LEDC_LS_SIG3", id = 3 }, + { name = "LEDC_LS_SIG4", id = 4 }, + { name = "LEDC_LS_SIG5", id = 5 }, + { name = "U0TXD", id = 6 }, + { name = "U0RTS", id = 7 }, + { name = "U0DTR", id = 8 }, + { name = "U1TXD", id = 9 }, + { name = "U1RTS", id = 10 }, + { name = "U1DTR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SO_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, + { name = "I2SO_SD1", id = 18 }, + { name = "USB_JTAG_TDO_BRIDGE", id = 19 }, + { name = "CPU_TESTBUS0", id = 20 }, + { name = "CPU_TESTBUS1", id = 21 }, + { name = "CPU_TESTBUS2", id = 22 }, + { name = "CPU_TESTBUS3", id = 23 }, + { name = "CPU_TESTBUS4", id = 24 }, + { name = "CPU_TESTBUS5", id = 25 }, + { name = "CPU_TESTBUS6", id = 26 }, + { name = "CPU_TESTBUS7", id = 27 }, + { name = "CPU_GPIO_0", id = 28 }, + { name = "CPU_GPIO_1", id = 29 }, + { name = "CPU_GPIO_2", id = 30 }, + { name = "CPU_GPIO_3", id = 31 }, + { name = "CPU_GPIO_4", id = 32 }, + { name = "CPU_GPIO_5", id = 33 }, + { name = "CPU_GPIO_6", id = 34 }, + { name = "CPU_GPIO_7", id = 35 }, + { name = "USB_JTAG_TCK", id = 36 }, + { name = "USB_JTAG_TMS", id = 37 }, + { name = "USB_JTAG_TDI", id = 38 }, + { name = "USB_JTAG_TDO", id = 39 }, + { name = "I2CEXT0_SCL", id = 45 }, + { name = "I2CEXT0_SDA", id = 46 }, + { name = "PARL_TX_DATA0", id = 47 }, + { name = "PARL_TX_DATA1", id = 48 }, + { name = "PARL_TX_DATA2", id = 49 }, + { name = "PARL_TX_DATA3", id = 50 }, + { name = "PARL_TX_DATA4", id = 51 }, + { name = "PARL_TX_DATA5", id = 52 }, + { name = "PARL_TX_DATA6", id = 53 }, + { name = "PARL_TX_DATA7", id = 54 }, + { name = "PARL_TX_DATA8", id = 55 }, + { name = "PARL_TX_DATA9", id = 56 }, + { name = "PARL_TX_DATA10", id = 57 }, + { name = "PARL_TX_DATA11", id = 58 }, + { name = "PARL_TX_DATA12", id = 59 }, + { name = "PARL_TX_DATA13", id = 60 }, + { name = "PARL_TX_DATA14", id = 61 }, + { name = "PARL_TX_DATA15", id = 62 }, + { name = "FSPICLK", id = 63 }, + { name = "FSPIQ", id = 64 }, + { name = "FSPID", id = 65 }, + { name = "FSPIHD", id = 66 }, + { name = "FSPIWP", id = 67 }, + { name = "FSPICS0", id = 68 }, + { name = "SDIO_TOHOST_INT", id = 69 }, + { name = "PARL_TX_CLK", id = 70 }, + { name = "RMT_SIG_0", id = 71 }, + { name = "RMT_SIG_1", id = 72 }, + { name = "TWAI0_TX", id = 73 }, + { name = "TWAI0_BUS_OFF_ON", id = 74 }, + { name = "TWAI0_CLKOUT", id = 75 }, + { name = "TWAI0_STANDBY", id = 76 }, + { name = "TWAI1_TX", id = 77 }, + { name = "TWAI1_BUS_OFF_ON", id = 78 }, + { name = "TWAI1_CLKOUT", id = 79 }, + { name = "TWAI1_STANDBY", id = 80 }, + { name = "GPIO_SD0", id = 83 }, + { name = "GPIO_SD1", id = 84 }, + { name = "GPIO_SD2", id = 85 }, + { name = "GPIO_SD3", id = 86 }, + { name = "PWM0_0A", id = 87 }, + { name = "PWM0_0B", id = 88 }, + { name = "PWM0_1A", id = 89 }, + { name = "PWM0_1B", id = 90 }, + { name = "PWM0_2A", id = 91 }, + { name = "PWM0_2B", id = 92 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "FSPICS1", id = 101 }, + { name = "FSPICS2", id = 102 }, + { name = "FSPICS3", id = 103 }, + { name = "FSPICS4", id = 104 }, + { name = "FSPICS5", id = 105 }, + { name = "SPICLK", id = 114 }, + { name = "SPICS0", id = 115 }, + { name = "SPICS1", id = 116 }, { name = "GPIO_TASK_MATRIX_OUT0", id = 117 }, { name = "GPIO_TASK_MATRIX_OUT1", id = 118 }, { name = "GPIO_TASK_MATRIX_OUT2", id = 119 }, { name = "GPIO_TASK_MATRIX_OUT3", id = 120 }, - { name = "SPIQ", id = 121 }, - { name = "SPID", id = 122 }, - { name = "SPIHD", id = 123 }, - { name = "SPIWP", id = 124 }, - { name = "CLK_OUT_OUT1", id = 125 }, - { name = "CLK_OUT_OUT2", id = 126 }, - { name = "CLK_OUT_OUT3", id = 127 }, - { name = "GPIO", id = 128 }, + { name = "SPIQ", id = 121 }, + { name = "SPID", id = 122 }, + { name = "SPIHD", id = 123 }, + { name = "SPIWP", id = 124 }, + { name = "CLK_OUT_OUT1", id = 125 }, + { name = "CLK_OUT_OUT2", id = 126 }, + { name = "CLK_OUT_OUT3", id = 127 }, + { name = "GPIO", id = 128 }, { name = "SDIO_CLK" }, { name = "SDIO_CMD" }, @@ -670,18 +636,7 @@ output_signals = [ [device.dedicated_gpio] support_status = "partial" -channels = [ - [ - "CPU_GPIO_0", - "CPU_GPIO_1", - "CPU_GPIO_2", - "CPU_GPIO_3", - "CPU_GPIO_4", - "CPU_GPIO_5", - "CPU_GPIO_6", - "CPU_GPIO_7", - ], -] +channels = [["CPU_GPIO_0", "CPU_GPIO_1", "CPU_GPIO_2", "CPU_GPIO_3", "CPU_GPIO_4", "CPU_GPIO_5", "CPU_GPIO_6", "CPU_GPIO_7"]] [device.i2c_master] support_status = "supported" @@ -712,7 +667,7 @@ support_status = "not_supported" support_status = "partial" status_registers = 3 software_interrupt_count = 4 -software_interrupt_delay = 14 # CPU-speed sensitive - what's clocked from where? +software_interrupt_delay = 14 # CPU-speed sensitive - what's clocked from where? controller = { Riscv = { flavour = "plic", interrupts = 32, priority_levels = 15 } } [device.rmt] @@ -727,7 +682,7 @@ has_tx_carrier_data_only = true has_tx_sync = true has_rx_wrap = true has_rx_demodulation = true -clock_sources.supported = ["None", "Pll80MHz", "RcFast", "Xtal"] +clock_sources.supported = [ "None", "Pll80MHz", "RcFast", "Xtal" ] clock_sources.default = "Pll80MHz" [device.rsa] @@ -746,26 +701,14 @@ supports_dma = true has_app_interrupts = true has_dma_segmented_transfer = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = [ - "FSPID", - "FSPIQ", - "FSPIWP", - "FSPIHD", - ], cs = [ - "FSPICS0", - "FSPICS1", - "FSPICS2", - "FSPICS3", - "FSPICS4", - "FSPICS5", - ] }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = ["FSPID", "FSPIQ", "FSPIWP", "FSPIHD"], cs = ["FSPICS0", "FSPICS1", "FSPICS2", "FSPICS3", "FSPICS4", "FSPICS5"] }, ] [device.spi_slave] support_status = "partial" supports_dma = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, ] [device.timergroup] @@ -796,7 +739,7 @@ support_status = "not_supported" [device.rng] support_status = "partial" trng_supported = true -apb_cycle_wait_num = 16 # TODO +apb_cycle_wait_num = 16 # TODO [device.sleep] support_status = "partial" @@ -843,4 +786,4 @@ controller = "npl" [device.ieee802154] [device.phy] -combo_module = true +combo_module = true \ No newline at end of file diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index a98ca0626cf..93626938f1b 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -6,11 +6,11 @@ # update the table in the esp-hal README. [device] -name = "esp32h2" -arch = "riscv" +name = "esp32h2" +arch = "riscv" target = "riscv32imac-unknown-none-elf" -cores = 1 -trm = "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf" +cores = 1 +trm = "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf" symbols = [ # Additional peripherals defined by us (the developers): @@ -82,7 +82,7 @@ peripherals = [ { name = "PLIC_MX" }, { name = "PMU" }, { name = "RMT", clock_group = "RMT" }, - { name = "RNG", virtual = true }, # a) RNG is LP_PERI in truth. b) we need to offset the rng_data register at runtime for newer revisions. + { name = "RNG", virtual = true }, # a) RNG is LP_PERI in truth. b) we need to offset the rng_data register at runtime for newer revisions. { name = "RSA", interrupts = { peri = "RSA" } }, { name = "SHA", interrupts = { peri = "SHA" }, dma_peripheral = 7 }, { name = "ETM", pac = "SOC_ETM" }, @@ -123,23 +123,23 @@ peripherals = [ clocks = { system_clocks = { clock_tree = [ # High-speed clock sources - { name = "XTAL_CLK", type = "source", values = "32", output = "VALUE * 1_000_000", always_on = true }, + { name = "XTAL_CLK", type = "source", values = "32", output = "VALUE * 1_000_000", always_on = true }, { name = "PLL_F96M_CLK", type = "derived", from = "XTAL_CLK", output = "96_000_000" }, - { name = "PLL_F64M_CLK", type = "generic", output = "PLL_F96M_CLK * 2 / 3" }, - { name = "PLL_F48M_CLK", type = "generic", output = "PLL_F96M_CLK / 2" }, - { name = "RC_FAST_CLK", type = "source", output = "8_000_000" }, - + { name = "PLL_F64M_CLK", type = "generic", output = "PLL_F96M_CLK * 2 / 3" }, + { name = "PLL_F48M_CLK", type = "generic", output = "PLL_F96M_CLK / 2" }, + { name = "RC_FAST_CLK", type = "source", output = "8_000_000" }, + # Low-speed clocks - { name = "XTAL32K_CLK", type = "source", output = "32768" }, - { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, - { name = "RC_SLOW_CLK", type = "source", output = "130_000" }, - { name = "PLL_LP_CLK", type = "derived", from = "XTAL32K_CLK", output = "8_000_000" }, + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "130_000" }, + { name = "PLL_LP_CLK", type = "derived", from = "XTAL32K_CLK", output = "8_000_000" }, { name = "HP_ROOT_CLK", type = "mux", variants = [ - { name = "PLL96", outputs = "PLL_F96M_CLK" }, - { name = "PLL64", outputs = "PLL_F64M_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "PLL96", outputs = "PLL_F96M_CLK" }, + { name = "PLL64", outputs = "PLL_F64M_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, ] }, { name = "CPU_CLK", type = "generic", params = { divisor = "0..=255" }, output = "HP_ROOT_CLK / (divisor + 1)", always_on = true }, # AHB_CLK * integer @@ -152,12 +152,12 @@ clocks = { system_clocks = { clock_tree = [ { name = "XTAL_D2_CLK", type = "generic", output = "XTAL_CLK / 2" }, { name = "LP_FAST_CLK", type = "mux", variants = [ { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_LP_CLK", outputs = "PLL_LP_CLK" }, + { name = "PLL_LP_CLK", outputs = "PLL_LP_CLK" }, { name = "XTAL_D2_CLK", outputs = "XTAL_D2_CLK" }, ] }, { name = "LP_SLOW_CLK", type = "mux", variants = [ - { name = "XTAL32K", outputs = "XTAL32K_CLK" }, - { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, { name = "OSC_SLOW", outputs = "OSC_SLOW_CLK" }, ] }, # LP_DYN_SLOW_CLK is LP_SLOW_CLK @@ -166,62 +166,62 @@ clocks = { system_clocks = { clock_tree = [ # There are separate clock muxes for each TIMG instance, but esp-hal only uses one. Only modelling # one makes the HAL code simpler. { name = "TIMG_CALIBRATION_CLOCK", type = "mux", variants = [ - { name = "RC_SLOW_CLK", outputs = "LP_SLOW_CLK" }, + { name = "RC_SLOW_CLK", outputs = "LP_SLOW_CLK" }, { name = "RC_FAST_DIV_CLK", outputs = "RC_FAST_CLK" }, #? - { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, + { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, ] }, ], template_groups = [ { group = "UART", clocks = [ { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK", default = true }, ], div_num = "0 .. 0x100" } }, { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, ] }, { group = "RMT", clocks = [ { name = "SCLK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, ] }, ] }, { group = "TIMG", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, + { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, ] }, { name = "WDT_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, + { name = "PLL_F48M", outputs = "PLL_F48M_CLK" }, ] }, ] }, { group = "MCPWM", clocks = [ # TODO: MCPWM divider? { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, + { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, ] }, { group = "PARL_IO", clocks = [ { name = "RX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, + { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, # TODO: external clock ] }, { name = "TX_CLOCK", type = "mux", variants = [ - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, + { name = "PLL_F96M", outputs = "PLL_F96M_CLK", default = true }, ] }, ] }, ] }, peripheral_clocks = { templates = [ # templates { name = "default_clk_en_template", value = "{{control}}::regs().{{conf_register}}().modify(|_, w| w.{{clk_en_field}}().bit(enable));" }, - { name = "clk_en_template", value = "{{default_clk_en_template}}" }, # Indirection allows appending to the template for TWAI + { name = "clk_en_template", value = "{{default_clk_en_template}}" }, # Indirection allows appending to the template for TWAI { name = "rst_template", value = "{{control}}::regs().{{conf_register}}().modify(|_, w| w.{{rst_field}}().bit(reset));" }, # substitutions { name = "control", value = "crate::peripherals::SYSTEM" }, @@ -273,7 +273,9 @@ clocks = { system_clocks = { clock_tree = [ [device.adc] support_status = "partial" -instances = [{ name = "adc1" }] +instances = [ + { name = "adc1" }, +] [device.aes] support_status = "partial" @@ -283,7 +285,7 @@ dma = true dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"] key_length = { options = [ { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, - { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 } ] } [device.assist_debug] @@ -312,9 +314,12 @@ working_modes = [ { id = 8, mode = "modular_addition" }, { id = 9, mode = "modular_subtraction" }, { id = 10, mode = "modular_multiplication" }, - { id = 11, mode = "modular_division" }, + { id = 11, mode = "modular_division" } +] +curves = [ + { id = 0, curve = 192 }, + { id = 1, curve = 256 } ] -curves = [{ id = 0, curve = 192 }, { id = 1, curve = 256 }] zero_extend_writes = true separate_jacobian_point_memory = true has_memory_clock_gate = true @@ -326,234 +331,213 @@ gpio_function = 1 constant_0_input = 0x3c constant_1_input = 0x38 pins = [ - { pin = 0, functions = { 2 = "FSPIQ" } }, - { pin = 1, functions = { 2 = "FSPICS0" }, analog = { 1 = "ADC1_CH0" } }, - { pin = 2, functions = { 0 = "MTMS", 2 = "FSPIWP" }, analog = { 1 = "ADC1_CH1" } }, - { pin = 3, functions = { 0 = "MTDI", 2 = "FSPIHD" }, analog = { 1 = "ADC1_CH2" } }, - { pin = 4, functions = { 0 = "MTCK", 2 = "FSPICLK" }, analog = { 1 = "ADC1_CH3" } }, - { pin = 5, functions = { 0 = "MTDO", 2 = "FSPID" }, analog = { 1 = "ADC1_CH4" } }, - { pin = 6, limitations = [ - "spi_flash", - ] }, - { pin = 7, lp = { 0 = "LP_GPIO0" }, limitations = [ - "spi_flash", - ] }, - { pin = 8, lp = { 0 = "LP_GPIO1" }, limitations = [ - "strapping", - ] }, - { pin = 9, lp = { 0 = "LP_GPIO2" }, limitations = [ - "strapping", - ] }, - { pin = 10, lp = { 0 = "LP_GPIO3" }, analog = { 0 = "ZCD0" } }, - { pin = 11, lp = { 0 = "LP_GPIO4" }, analog = { 0 = "ZCD1" } }, + { pin = 0, functions = { 2 = "FSPIQ" } }, + { pin = 1, functions = { 2 = "FSPICS0" }, analog = { 1 = "ADC1_CH0" } }, + { pin = 2, functions = { 0 = "MTMS", 2 = "FSPIWP" }, analog = { 1 = "ADC1_CH1" } }, + { pin = 3, functions = { 0 = "MTDI", 2 = "FSPIHD" }, analog = { 1 = "ADC1_CH2" } }, + { pin = 4, functions = { 0 = "MTCK", 2 = "FSPICLK" }, analog = { 1 = "ADC1_CH3" } }, + { pin = 5, functions = { 0 = "MTDO", 2 = "FSPID" }, analog = { 1 = "ADC1_CH4" } }, + { pin = 6, limitations = ["spi_flash"] }, + { pin = 7, lp = { 0 = "LP_GPIO0" }, limitations = ["spi_flash"] }, + { pin = 8, lp = { 0 = "LP_GPIO1" }, limitations = ["strapping"] }, + { pin = 9, lp = { 0 = "LP_GPIO2" }, limitations = ["strapping"] }, + { pin = 10, lp = { 0 = "LP_GPIO3" }, analog = { 0 = "ZCD0" } }, + { pin = 11, lp = { 0 = "LP_GPIO4" }, analog = { 0 = "ZCD1" } }, { pin = 12, lp = { 0 = "LP_GPIO5" } }, - { pin = 13, lp = { 0 = "LP_GPIO6" }, analog = { 0 = "XTAL_32K_P" } }, - { pin = 14, lp = { 0 = "LP_GPIO7" }, analog = { 0 = "XTAL_32K_N" } }, + { pin = 13, lp = { 0 = "LP_GPIO6" }, analog = { 0 = "XTAL_32K_P" } }, + { pin = 14, lp = { 0 = "LP_GPIO7" }, analog = { 0 = "XTAL_32K_N" } }, { pin = 22 }, { pin = 23, functions = { 0 = "U0RXD", 2 = "FSPICS1" } }, { pin = 24, functions = { 0 = "U0TXD", 2 = "FSPICS2" } }, - { pin = 25, functions = { 2 = "FSPICS3" }, limitations = [ - "strapping", - ] }, - { pin = 26, functions = { 2 = "FSPICS4" }, analog = { 0 = "USB_DM" } }, - { pin = 27, functions = { 2 = "FSPICS5" }, analog = { 0 = "USB_DP" } }, + { pin = 25, functions = { 2 = "FSPICS3" }, limitations = ["strapping"] }, + { pin = 26, functions = { 2 = "FSPICS4" }, analog = { 0 = "USB_DM" } }, + { pin = 27, functions = { 2 = "FSPICS5" }, analog = { 0 = "USB_DP" } }, ] input_signals = [ - { name = "EXT_ADC_START", id = 0 }, - { name = "U0RXD", id = 6 }, - { name = "U0CTS", id = 7 }, - { name = "U0DSR", id = 8 }, - { name = "U1RXD", id = 9 }, - { name = "U1CTS", id = 10 }, - { name = "U1DSR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SI_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, + { name = "EXT_ADC_START", id = 0 }, + { name = "U0RXD", id = 6 }, + { name = "U0CTS", id = 7 }, + { name = "U0DSR", id = 8 }, + { name = "U1RXD", id = 9 }, + { name = "U1CTS", id = 10 }, + { name = "U1DSR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SI_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, { name = "USB_JTAG_TDO_BRIDGE", id = 19 }, - { name = "CPU_GPIO_0", id = 28 }, - { name = "CPU_GPIO_1", id = 29 }, - { name = "CPU_GPIO_2", id = 30 }, - { name = "CPU_GPIO_3", id = 31 }, - { name = "CPU_GPIO_4", id = 32 }, - { name = "CPU_GPIO_5", id = 33 }, - { name = "CPU_GPIO_6", id = 34 }, - { name = "CPU_GPIO_7", id = 35 }, - { name = "I2CEXT0_SCL", id = 45 }, - { name = "I2CEXT0_SDA", id = 46 }, - { name = "PARL_RX_DATA0", id = 47 }, - { name = "PARL_RX_DATA1", id = 48 }, - { name = "PARL_RX_DATA2", id = 49 }, - { name = "PARL_RX_DATA3", id = 50 }, - { name = "PARL_RX_DATA4", id = 51 }, - { name = "PARL_RX_DATA5", id = 52 }, - { name = "PARL_RX_DATA6", id = 53 }, - { name = "PARL_RX_DATA7", id = 54 }, - { name = "I2CEXT1_SCL", id = 55 }, - { name = "I2CEXT1_SDA", id = 56 }, - { name = "FSPICLK", id = 63 }, - { name = "FSPIQ", id = 64 }, - { name = "FSPID", id = 65 }, - { name = "FSPIHD", id = 66 }, - { name = "FSPIWP", id = 67 }, - { name = "FSPICS0", id = 68 }, - { name = "PARL_RX_CLK", id = 69 }, - { name = "PARL_TX_CLK", id = 70 }, - { name = "RMT_SIG_0", id = 71 }, - { name = "RMT_SIG_1", id = 72 }, - { name = "TWAI0_RX", id = 73 }, - { name = "PWM0_SYNC0", id = 87 }, - { name = "PWM0_SYNC1", id = 88 }, - { name = "PWM0_SYNC2", id = 89 }, - { name = "PWM0_F0", id = 90 }, - { name = "PWM0_F1", id = 91 }, - { name = "PWM0_F2", id = 92 }, - { name = "PWM0_CAP0", id = 93 }, - { name = "PWM0_CAP1", id = 94 }, - { name = "PWM0_CAP2", id = 95 }, - { name = "SIG_FUNC_97", id = 97 }, - { name = "SIG_FUNC_98", id = 98 }, - { name = "SIG_FUNC_99", id = 99 }, - { name = "SIG_FUNC_100", id = 100 }, - { name = "PCNT0_SIG_CH0", id = 101 }, - { name = "PCNT0_SIG_CH1", id = 102 }, - { name = "PCNT0_CTRL_CH0", id = 103 }, - { name = "PCNT0_CTRL_CH1", id = 104 }, - { name = "PCNT1_SIG_CH0", id = 105 }, - { name = "PCNT1_SIG_CH1", id = 106 }, - { name = "PCNT1_CTRL_CH0", id = 107 }, - { name = "PCNT1_CTRL_CH1", id = 108 }, - { name = "PCNT2_SIG_CH0", id = 109 }, - { name = "PCNT2_SIG_CH1", id = 110 }, - { name = "PCNT2_CTRL_CH0", id = 111 }, - { name = "PCNT2_CTRL_CH1", id = 112 }, - { name = "PCNT3_SIG_CH0", id = 113 }, - { name = "PCNT3_SIG_CH1", id = 114 }, - { name = "PCNT3_CTRL_CH0", id = 115 }, - { name = "PCNT3_CTRL_CH1", id = 116 }, - { name = "SPIQ", id = 121 }, - { name = "SPID", id = 122 }, - { name = "SPIHD", id = 123 }, - { name = "SPIWP", id = 124 }, + { name = "CPU_GPIO_0", id = 28 }, + { name = "CPU_GPIO_1", id = 29 }, + { name = "CPU_GPIO_2", id = 30 }, + { name = "CPU_GPIO_3", id = 31 }, + { name = "CPU_GPIO_4", id = 32 }, + { name = "CPU_GPIO_5", id = 33 }, + { name = "CPU_GPIO_6", id = 34 }, + { name = "CPU_GPIO_7", id = 35 }, + { name = "I2CEXT0_SCL", id = 45 }, + { name = "I2CEXT0_SDA", id = 46 }, + { name = "PARL_RX_DATA0", id = 47 }, + { name = "PARL_RX_DATA1", id = 48 }, + { name = "PARL_RX_DATA2", id = 49 }, + { name = "PARL_RX_DATA3", id = 50 }, + { name = "PARL_RX_DATA4", id = 51 }, + { name = "PARL_RX_DATA5", id = 52 }, + { name = "PARL_RX_DATA6", id = 53 }, + { name = "PARL_RX_DATA7", id = 54 }, + { name = "I2CEXT1_SCL", id = 55 }, + { name = "I2CEXT1_SDA", id = 56 }, + { name = "FSPICLK", id = 63 }, + { name = "FSPIQ", id = 64 }, + { name = "FSPID", id = 65 }, + { name = "FSPIHD", id = 66 }, + { name = "FSPIWP", id = 67 }, + { name = "FSPICS0", id = 68 }, + { name = "PARL_RX_CLK", id = 69 }, + { name = "PARL_TX_CLK", id = 70 }, + { name = "RMT_SIG_0", id = 71 }, + { name = "RMT_SIG_1", id = 72 }, + { name = "TWAI0_RX", id = 73 }, + { name = "PWM0_SYNC0", id = 87 }, + { name = "PWM0_SYNC1", id = 88 }, + { name = "PWM0_SYNC2", id = 89 }, + { name = "PWM0_F0", id = 90 }, + { name = "PWM0_F1", id = 91 }, + { name = "PWM0_F2", id = 92 }, + { name = "PWM0_CAP0", id = 93 }, + { name = "PWM0_CAP1", id = 94 }, + { name = "PWM0_CAP2", id = 95 }, + { name = "SIG_FUNC_97", id = 97 }, + { name = "SIG_FUNC_98", id = 98 }, + { name = "SIG_FUNC_99", id = 99 }, + { name = "SIG_FUNC_100", id = 100 }, + { name = "PCNT0_SIG_CH0", id = 101 }, + { name = "PCNT0_SIG_CH1", id = 102 }, + { name = "PCNT0_CTRL_CH0", id = 103 }, + { name = "PCNT0_CTRL_CH1", id = 104 }, + { name = "PCNT1_SIG_CH0", id = 105 }, + { name = "PCNT1_SIG_CH1", id = 106 }, + { name = "PCNT1_CTRL_CH0", id = 107 }, + { name = "PCNT1_CTRL_CH1", id = 108 }, + { name = "PCNT2_SIG_CH0", id = 109 }, + { name = "PCNT2_SIG_CH1", id = 110 }, + { name = "PCNT2_CTRL_CH0", id = 111 }, + { name = "PCNT2_CTRL_CH1", id = 112 }, + { name = "PCNT3_SIG_CH0", id = 113 }, + { name = "PCNT3_SIG_CH1", id = 114 }, + { name = "PCNT3_CTRL_CH0", id = 115 }, + { name = "PCNT3_CTRL_CH1", id = 116 }, + { name = "SPIQ", id = 121 }, + { name = "SPID", id = 122 }, + { name = "SPIHD", id = 123 }, + { name = "SPIWP", id = 124 }, { name = "MTDI" }, { name = "MTCK" }, { name = "MTMS" }, ] output_signals = [ - { name = "LEDC_LS_SIG0", id = 0 }, - { name = "LEDC_LS_SIG1", id = 1 }, - { name = "LEDC_LS_SIG2", id = 2 }, - { name = "LEDC_LS_SIG3", id = 3 }, - { name = "LEDC_LS_SIG4", id = 4 }, - { name = "LEDC_LS_SIG5", id = 5 }, - { name = "U0TXD", id = 6 }, - { name = "U0RTS", id = 7 }, - { name = "U0DTR", id = 8 }, - { name = "U1TXD", id = 9 }, - { name = "U1RTS", id = 10 }, - { name = "U1DTR", id = 11 }, - { name = "I2S_MCLK", id = 12 }, - { name = "I2SO_BCK", id = 13 }, - { name = "I2SO_WS", id = 14 }, - { name = "I2SO_SD", id = 15 }, - { name = "I2SI_BCK", id = 16 }, - { name = "I2SI_WS", id = 17 }, - { name = "I2SO_SD1", id = 18 }, - { name = "USB_JTAG_TRST", id = 19 }, - { name = "CPU_GPIO_0", id = 28 }, - { name = "CPU_GPIO_1", id = 29 }, - { name = "CPU_GPIO_2", id = 30 }, - { name = "CPU_GPIO_3", id = 31 }, - { name = "CPU_GPIO_4", id = 32 }, - { name = "CPU_GPIO_5", id = 33 }, - { name = "CPU_GPIO_6", id = 34 }, - { name = "CPU_GPIO_7", id = 35 }, - { name = "I2CEXT0_SCL", id = 45 }, - { name = "I2CEXT0_SDA", id = 46 }, - { name = "PARL_TX_DATA0", id = 47 }, - { name = "PARL_TX_DATA1", id = 48 }, - { name = "PARL_TX_DATA2", id = 49 }, - { name = "PARL_TX_DATA3", id = 50 }, - { name = "PARL_TX_DATA4", id = 51 }, - { name = "PARL_TX_DATA5", id = 52 }, - { name = "PARL_TX_DATA6", id = 53 }, - { name = "PARL_TX_DATA7", id = 54 }, - { name = "I2CEXT1_SCL", id = 55 }, - { name = "I2CEXT1_SDA", id = 56 }, - { name = "FSPICLK", id = 63 }, - { name = "FSPIQ", id = 64 }, - { name = "FSPID", id = 65 }, - { name = "FSPIHD", id = 66 }, - { name = "FSPIWP", id = 67 }, - { name = "FSPICS0", id = 68 }, - { name = "PARL_RX_CLK", id = 69 }, - { name = "PARL_TX_CLK", id = 70 }, - { name = "RMT_SIG_0", id = 71 }, - { name = "RMT_SIG_1", id = 72 }, - { name = "TWAI0_TX", id = 73 }, + { name = "LEDC_LS_SIG0", id = 0 }, + { name = "LEDC_LS_SIG1", id = 1 }, + { name = "LEDC_LS_SIG2", id = 2 }, + { name = "LEDC_LS_SIG3", id = 3 }, + { name = "LEDC_LS_SIG4", id = 4 }, + { name = "LEDC_LS_SIG5", id = 5 }, + { name = "U0TXD", id = 6 }, + { name = "U0RTS", id = 7 }, + { name = "U0DTR", id = 8 }, + { name = "U1TXD", id = 9 }, + { name = "U1RTS", id = 10 }, + { name = "U1DTR", id = 11 }, + { name = "I2S_MCLK", id = 12 }, + { name = "I2SO_BCK", id = 13 }, + { name = "I2SO_WS", id = 14 }, + { name = "I2SO_SD", id = 15 }, + { name = "I2SI_BCK", id = 16 }, + { name = "I2SI_WS", id = 17 }, + { name = "I2SO_SD1", id = 18 }, + { name = "USB_JTAG_TRST", id = 19 }, + { name = "CPU_GPIO_0", id = 28 }, + { name = "CPU_GPIO_1", id = 29 }, + { name = "CPU_GPIO_2", id = 30 }, + { name = "CPU_GPIO_3", id = 31 }, + { name = "CPU_GPIO_4", id = 32 }, + { name = "CPU_GPIO_5", id = 33 }, + { name = "CPU_GPIO_6", id = 34 }, + { name = "CPU_GPIO_7", id = 35 }, + { name = "I2CEXT0_SCL", id = 45 }, + { name = "I2CEXT0_SDA", id = 46 }, + { name = "PARL_TX_DATA0", id = 47 }, + { name = "PARL_TX_DATA1", id = 48 }, + { name = "PARL_TX_DATA2", id = 49 }, + { name = "PARL_TX_DATA3", id = 50 }, + { name = "PARL_TX_DATA4", id = 51 }, + { name = "PARL_TX_DATA5", id = 52 }, + { name = "PARL_TX_DATA6", id = 53 }, + { name = "PARL_TX_DATA7", id = 54 }, + { name = "I2CEXT1_SCL", id = 55 }, + { name = "I2CEXT1_SDA", id = 56 }, + { name = "FSPICLK", id = 63 }, + { name = "FSPIQ", id = 64 }, + { name = "FSPID", id = 65 }, + { name = "FSPIHD", id = 66 }, + { name = "FSPIWP", id = 67 }, + { name = "FSPICS0", id = 68 }, + { name = "PARL_RX_CLK", id = 69 }, + { name = "PARL_TX_CLK", id = 70 }, + { name = "RMT_SIG_0", id = 71 }, + { name = "RMT_SIG_1", id = 72 }, + { name = "TWAI0_TX", id = 73 }, { name = "TWAI0_BUS_OFF_ON", id = 74 }, - { name = "TWAI0_CLKOUT", id = 75 }, - { name = "TWAI0_STANDBY", id = 76 }, - { name = "CTE_ANT7", id = 78 }, - { name = "CTE_ANT8", id = 79 }, - { name = "CTE_ANT9", id = 80 }, - { name = "GPIO_SD0", id = 83 }, - { name = "GPIO_SD1", id = 84 }, - { name = "GPIO_SD2", id = 85 }, - { name = "GPIO_SD3", id = 86 }, - { name = "PWM0_0A", id = 87 }, - { name = "PWM0_0B", id = 88 }, - { name = "PWM0_1A", id = 89 }, - { name = "PWM0_1B", id = 90 }, - { name = "PWM0_2A", id = 91 }, - { name = "PWM0_2B", id = 92 }, - { name = "SIG_IN_FUNC97", id = 97 }, - { name = "SIG_IN_FUNC98", id = 98 }, - { name = "SIG_IN_FUNC99", id = 99 }, - { name = "SIG_IN_FUNC100", id = 100 }, - { name = "FSPICS1", id = 101 }, - { name = "FSPICS2", id = 102 }, - { name = "FSPICS3", id = 103 }, - { name = "FSPICS4", id = 104 }, - { name = "FSPICS5", id = 105 }, - { name = "CTE_ANT10", id = 106 }, - { name = "CTE_ANT11", id = 107 }, - { name = "CTE_ANT12", id = 108 }, - { name = "CTE_ANT13", id = 109 }, - { name = "CTE_ANT14", id = 110 }, - { name = "CTE_ANT15", id = 111 }, - { name = "SPICLK", id = 114 }, - { name = "SPICS0", id = 115 }, - { name = "SPICS1", id = 116 }, - { name = "SPIQ", id = 121 }, - { name = "SPID", id = 122 }, - { name = "SPIHD", id = 123 }, - { name = "SPIWP", id = 124 }, - { name = "CLK_OUT_OUT1", id = 125 }, - { name = "CLK_OUT_OUT2", id = 126 }, - { name = "CLK_OUT_OUT3", id = 127 }, - { name = "GPIO", id = 128 }, - - { name = "MTDO" }, + { name = "TWAI0_CLKOUT", id = 75 }, + { name = "TWAI0_STANDBY", id = 76 }, + { name = "CTE_ANT7", id = 78 }, + { name = "CTE_ANT8", id = 79 }, + { name = "CTE_ANT9", id = 80 }, + { name = "GPIO_SD0", id = 83 }, + { name = "GPIO_SD1", id = 84 }, + { name = "GPIO_SD2", id = 85 }, + { name = "GPIO_SD3", id = 86 }, + { name = "PWM0_0A", id = 87 }, + { name = "PWM0_0B", id = 88 }, + { name = "PWM0_1A", id = 89 }, + { name = "PWM0_1B", id = 90 }, + { name = "PWM0_2A", id = 91 }, + { name = "PWM0_2B", id = 92 }, + { name = "SIG_IN_FUNC97", id = 97 }, + { name = "SIG_IN_FUNC98", id = 98 }, + { name = "SIG_IN_FUNC99", id = 99 }, + { name = "SIG_IN_FUNC100", id = 100 }, + { name = "FSPICS1", id = 101 }, + { name = "FSPICS2", id = 102 }, + { name = "FSPICS3", id = 103 }, + { name = "FSPICS4", id = 104 }, + { name = "FSPICS5", id = 105 }, + { name = "CTE_ANT10", id = 106 }, + { name = "CTE_ANT11", id = 107 }, + { name = "CTE_ANT12", id = 108 }, + { name = "CTE_ANT13", id = 109 }, + { name = "CTE_ANT14", id = 110 }, + { name = "CTE_ANT15", id = 111 }, + { name = "SPICLK", id = 114 }, + { name = "SPICS0", id = 115 }, + { name = "SPICS1", id = 116 }, + { name = "SPIQ", id = 121 }, + { name = "SPID", id = 122 }, + { name = "SPIHD", id = 123 }, + { name = "SPIWP", id = 124 }, + { name = "CLK_OUT_OUT1", id = 125 }, + { name = "CLK_OUT_OUT2", id = 126 }, + { name = "CLK_OUT_OUT3", id = 127 }, + { name = "GPIO", id = 128 }, + + { name = "MTDO" } ] [device.dedicated_gpio] support_status = "partial" -channels = [ - [ - "CPU_GPIO_0", - "CPU_GPIO_1", - "CPU_GPIO_2", - "CPU_GPIO_3", - "CPU_GPIO_4", - "CPU_GPIO_5", - "CPU_GPIO_6", - "CPU_GPIO_7", - ], -] +channels = [["CPU_GPIO_0", "CPU_GPIO_1", "CPU_GPIO_2", "CPU_GPIO_3", "CPU_GPIO_4", "CPU_GPIO_5", "CPU_GPIO_6", "CPU_GPIO_7"]] [device.i2c_master] support_status = "supported" @@ -596,7 +580,7 @@ has_tx_carrier_data_only = true has_tx_sync = true has_rx_wrap = true has_rx_demodulation = true -clock_sources.supported = ["Xtal", "RcFast"] +clock_sources.supported = ["Xtal", "RcFast" ] # Power-on value is RcFast! clock_sources.default = "Xtal" @@ -616,33 +600,21 @@ supports_dma = true has_app_interrupts = true has_dma_segmented_transfer = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = [ - "FSPID", - "FSPIQ", - "FSPIWP", - "FSPIHD", - ], cs = [ - "FSPICS0", - "FSPICS1", - "FSPICS2", - "FSPICS3", - "FSPICS4", - "FSPICS5", - ] }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = ["FSPID", "FSPIQ", "FSPIWP", "FSPIHD"], cs = ["FSPICS0", "FSPICS1", "FSPICS2", "FSPICS3", "FSPICS4", "FSPICS5"] }, ] [device.spi_slave] support_status = "partial" supports_dma = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, ] [device.timergroup] support_status = "partial" instances = [{ name = "timg0" }, { name = "timg1" }] timg_has_divcnt_rst = true -rc_fast_calibration = { divider = 32, min_rev = 2 } +rc_fast_calibration = { divider = 32, min_rev = 2, tick_enable = true } [device.uart] support_status = "supported" @@ -662,7 +634,7 @@ support_status = "not_supported" [device.rng] support_status = "partial" trng_supported = true -apb_cycle_wait_num = 16 # TODO +apb_cycle_wait_num = 16 # TODO [device.parl_io] support_status = "partial" @@ -700,4 +672,4 @@ controller = "npl" [device.ieee802154] -[device.phy] +[device.phy] \ No newline at end of file diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index b01dee69f4b..1dbc0a05b68 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -6,29 +6,26 @@ # update the table in the esp-hal README. [device] -name = "esp32s3" -arch = "xtensa" +name = "esp32s3" +arch = "xtensa" target = "xtensa-esp32s3-none-elf" -cores = 2 -trm = "https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf" +cores = 2 +trm = "https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf" symbols = [ # Additional peripherals defined by us (the developers): "phy", - "psram", - "psram_dma", - "octal_psram", "swd", "ulp_riscv_core", - # MCPWM capabilities - "soc_has_mcpwm_swsync_can_propagate", - # ROM capabilities "rom_crc_le", "rom_crc_be", "rom_md5_bsd", + # MCPWM capabilities + "soc_has_mcpwm_swsync_can_propagate", + # Wakeup SOC based on ESP-IDF: "pm_support_ext0_wakeup", "pm_support_ext1_wakeup", @@ -125,45 +122,34 @@ peripherals = [ clocks = { system_clocks = { clock_tree = [ # High-speed clock sources - { name = "XTAL_CLK", type = "source", values = "40", output = "VALUE * 1_000_000", always_on = true }, - { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", values = "320, 480", output = "VALUE * 1_000_000", reject = "VALUE == 320_000_000 && CPU_PLL_DIV_OUT == 240_000_000" }, - { name = "RC_FAST_CLK", type = "source", output = "17_500_000" }, + { name = "XTAL_CLK", type = "source", values = "40", output = "VALUE * 1_000_000", always_on = true }, + { name = "PLL_CLK", type = "derived", from = "XTAL_CLK", values = "320, 480", output = "VALUE * 1_000_000", reject = "VALUE == 320_000_000 && CPU_PLL_DIV_OUT == 240_000_000" }, + { name = "RC_FAST_CLK", type = "source", output = "17_500_000" }, # Low-speed clocks - { name = "XTAL32K_CLK", type = "source", output = "32768" }, - { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, { name = "RC_FAST_DIV_CLK", type = "generic", output = "RC_FAST_CLK / 256" }, # CPU clock source dividers { name = "SYSTEM_PRE_DIV_IN", type = "mux", variants = [ - { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, { name = "RC_FAST", outputs = "RC_FAST_CLK" }, ] }, - { name = "SYSTEM_PRE_DIV", type = "generic", params = { divisor = "0 .. 1024" }, output = "SYSTEM_PRE_DIV_IN / (divisor + 1)" }, + { name = "SYSTEM_PRE_DIV", type = "generic", params = { divisor = "0 .. 1024" }, output = "SYSTEM_PRE_DIV_IN / (divisor + 1)" }, # PLL CLK divider, modeled as a generic derived source because valid divider values depend on the PLL frequency { name = "CPU_PLL_DIV_OUT", type = "derived", from = "PLL_CLK", values = "80, 160, 240", output = "VALUE * 1_000_000", reject = "VALUE == 240_000_000 && PLL_CLK == 320_000_000" }, # The meta-switch { name = "CPU_CLK", type = "mux", always_on = true, variants = [ # source clock CPU clock additional config (mux = variant name, divider = divisor expression) - { name = "XTAL", outputs = "SYSTEM_PRE_DIV", configures = [ - "APB_CLK = CPU", - "CRYPTO_PWM_CLK = CPU", - "SYSTEM_PRE_DIV_IN = XTAL", - ] }, - { name = "RC_FAST", outputs = "SYSTEM_PRE_DIV", configures = [ - "APB_CLK = CPU", - "CRYPTO_PWM_CLK = CPU", - "SYSTEM_PRE_DIV_IN = RC_FAST", - ] }, - { name = "PLL", outputs = "CPU_PLL_DIV_OUT", configures = [ - "APB_CLK = PLL", - "CRYPTO_PWM_CLK = PLL", - ] }, + { name = "XTAL", outputs = "SYSTEM_PRE_DIV", configures = [ "APB_CLK = CPU", "CRYPTO_PWM_CLK = CPU", "SYSTEM_PRE_DIV_IN = XTAL" ] }, + { name = "RC_FAST", outputs = "SYSTEM_PRE_DIV", configures = [ "APB_CLK = CPU", "CRYPTO_PWM_CLK = CPU", "SYSTEM_PRE_DIV_IN = RC_FAST" ] }, + { name = "PLL", outputs = "CPU_PLL_DIV_OUT", configures = [ "APB_CLK = PLL", "CRYPTO_PWM_CLK = PLL" ] }, ] }, # CPU-dependent clock signals - { name = "PLL_D2", type = "generic", output = "PLL_CLK / 2" }, + { name = "PLL_D2", type = "generic", output = "PLL_CLK / 2" }, { name = "PLL_160M", type = "derived", from = "CPU_CLK", output = "160_000_000" }, { name = "APB_80M", type = "derived", from = "CPU_CLK", output = "80_000_000" }, @@ -173,12 +159,12 @@ clocks = { system_clocks = { clock_tree = [ ] }, { name = "CRYPTO_PWM_CLK", type = "mux", variants = [ { name = "PLL", outputs = "PLL_160M" }, - { name = "CPU", outputs = "CPU_CLK" }, + { name = "CPU", outputs = "CPU_CLK" }, ] }, # Low-power clocks { name = "RC_FAST_CLK_DIV_N", type = "generic", params = { divisor = "0 ..= 3" }, output = "RC_FAST_CLK / (divisor + 1)" }, - { name = "XTAL_DIV_CLK", type = "generic", output = "XTAL_CLK / 2" }, + { name = "XTAL_DIV_CLK", type = "generic", output = "XTAL_CLK / 2" }, { name = "RTC_SLOW_CLK", type = "mux", variants = [ { name = "XTAL32K", outputs = "XTAL32K_CLK" }, { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, @@ -186,14 +172,14 @@ clocks = { system_clocks = { clock_tree = [ ] }, { name = "RTC_FAST_CLK", type = "mux", variants = [ { name = "XTAL", outputs = "XTAL_DIV_CLK" }, - { name = "RC", outputs = "RC_FAST_CLK_DIV_N" }, + { name = "RC", outputs = "RC_FAST_CLK_DIV_N" }, ] }, # Low-power wireless clock source { name = "LOW_POWER_CLK", type = "mux", variants = [ - { name = "XTAL", outputs = "XTAL_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, - { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, { name = "RTC_SLOW", outputs = "RTC_SLOW_CLK" }, ] }, @@ -206,34 +192,34 @@ clocks = { system_clocks = { clock_tree = [ # There are separate clock muxes for each TIMG instance, but esp-hal only uses one. Only modelling # one makes the HAL code simpler. { name = "TIMG_CALIBRATION_CLOCK", type = "mux", variants = [ - { name = "RC_SLOW_CLK", outputs = "RC_SLOW_CLK" }, + { name = "RC_SLOW_CLK", outputs = "RC_SLOW_CLK" }, { name = "RC_FAST_DIV_CLK", outputs = "RC_FAST_DIV_CLK" }, - { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, + { name = "XTAL32K_CLK", outputs = "XTAL32K_CLK" }, ] }, ], template_groups = [ { group = "MCPWM", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ - { name = "CRYPTO_PWM_CLK", outputs = "CRYPTO_PWM_CLK", default = true }, - ] }, + { name = "CRYPTO_PWM_CLK", outputs = "CRYPTO_PWM_CLK", default = true } + ] } ] }, { group = "TIMG", clocks = [ { name = "FUNCTION_CLOCK", type = "mux", variants = [ { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, - { name = "APB_CLK", outputs = "APB_CLK" }, + { name = "APB_CLK", outputs = "APB_CLK" }, ] }, ] }, { group = "RMT", clocks = [ { name = "SCLK", type = "mux", variants = [ - { name = "APB_CLK", outputs = "APB_CLK", default = true }, + { name = "APB_CLK", outputs = "APB_CLK", default = true }, { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, - { name = "XTAL_CLK", outputs = "XTAL_CLK" }, + { name = "XTAL_CLK", outputs = "XTAL_CLK" }, ] }, ] }, { group = "UART", clocks = [ { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ - { name = "APB", outputs = "APB_CLK" }, - { name = "RC_FAST", outputs = "RC_FAST_CLK" }, - { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "APB", outputs = "APB_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL", outputs = "XTAL_CLK", default = true }, ], div_num = "0 .. 0x100" } }, { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, { name = "MEM_CLOCK", type = "generic", output = "UART_MEM_CLK" }, @@ -266,7 +252,7 @@ clocks = { system_clocks = { clock_tree = [ #{ name = "Adc2Arb" }, { name = "Systimer", keep_enabled = true }, { name = "ApbSarAdc", template_params = { peripheral = "apb_saradc" } }, - { name = "UartMem", keep_enabled = true }, # TODO: keep_enabled can be removed once esp-println needs explicit initialization + { name = "UartMem", keep_enabled = true }, # TODO: keep_enabled can be removed once esp-println needs explicit initialization { name = "Usb" }, { name = "I2s1" }, { name = "Mcpwm1", template_params = { peripheral = "pwm1" } }, @@ -287,13 +273,16 @@ clocks = { system_clocks = { clock_tree = [ { name = "Uart0", template_params = { peripheral = "uart" }, keep_enabled = true }, #{ name = "Spi01" }, #{ name = "Timers" }, - + # Radio clocks not modeled here. ] } } [device.adc] support_status = "partial" -instances = [{ name = "adc1" }, { name = "adc2" }] +instances = [ + { name = "adc1" }, + { name = "adc2" }, +] [device.aes] support_status = "partial" @@ -303,7 +292,7 @@ dma = true dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"] key_length = { options = [ { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, - { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 } ] } [device.assist_debug] @@ -317,6 +306,7 @@ gdma_version = 1 separate_in_out_interrupts = true supports_mem2mem = true max_priority = 9 +can_access_psram = true [device.gpio] support_status = "supported" @@ -325,270 +315,228 @@ gpio_function = 1 constant_0_input = 0x3c constant_1_input = 0x38 pins = [ - { pin = 0, rtc = { 0 = "RTC_GPIO0", 1 = "SAR_I2C_SCL_0" }, limitations = [ - "strapping", - ] }, - { pin = 1, analog = { 0 = "TOUCH1", 1 = "ADC1_CH0" }, rtc = { 0 = "RTC_GPIO1", 1 = "SAR_I2C_SDA_0" } }, - { pin = 2, analog = { 0 = "TOUCH2", 1 = "ADC1_CH1" }, rtc = { 0 = "RTC_GPIO2", 1 = "SAR_I2C_SCL_1" } }, - { pin = 3, analog = { 0 = "TOUCH3", 1 = "ADC1_CH2" }, rtc = { 0 = "RTC_GPIO3", 1 = "SAR_I2C_SDA_1" }, limitations = [ - "strapping", - ] }, - { pin = 4, analog = { 0 = "TOUCH4", 1 = "ADC1_CH3" }, rtc = { 0 = "RTC_GPIO4" } }, - { pin = 5, analog = { 0 = "TOUCH5", 1 = "ADC1_CH4" }, rtc = { 0 = "RTC_GPIO5" } }, - { pin = 6, analog = { 0 = "TOUCH6", 1 = "ADC1_CH5" }, rtc = { 0 = "RTC_GPIO6" } }, - { pin = 7, analog = { 0 = "TOUCH7", 1 = "ADC1_CH6" }, rtc = { 0 = "RTC_GPIO7" } }, - { pin = 8, functions = { 3 = "SUBSPICS1" }, analog = { 0 = "TOUCH8", 1 = "ADC1_CH7" }, rtc = { 0 = "RTC_GPIO8" } }, - { pin = 9, functions = { 3 = "SUBSPIHD", 4 = "FSPIHD" }, analog = { 0 = "TOUCH9", 1 = "ADC1_CH8" }, rtc = { 0 = "RTC_GPIO9" } }, - { pin = 10, functions = { 2 = "FSPIIO4", 3 = "SUBSPICS0", 4 = "FSPICS0" }, analog = { 0 = "TOUCH10", 1 = "ADC1_CH9" }, rtc = { 0 = "RTC_GPIO10" } }, - { pin = 11, functions = { 2 = "FSPIIO5", 3 = "SUBSPID", 4 = "FSPID" }, analog = { 0 = "TOUCH11", 1 = "ADC2_CH0" }, rtc = { 0 = "RTC_GPIO11" } }, - { pin = 12, functions = { 2 = "FSPIIO6", 3 = "SUBSPICLK", 4 = "FSPICLK" }, analog = { 0 = "TOUCH12", 1 = "ADC2_CH1" }, rtc = { 0 = "RTC_GPIO12" } }, - { pin = 13, functions = { 2 = "FSPIIO7", 3 = "SUBSPIQ", 4 = "FSPIQ" }, analog = { 0 = "TOUCH13", 1 = "ADC2_CH2" }, rtc = { 0 = "RTC_GPIO13" } }, - { pin = 14, functions = { 2 = "FSPIDQS", 3 = "SUBSPIWP", 4 = "FSPIWP" }, analog = { 0 = "TOUCH14", 1 = "ADC2_CH3" }, rtc = { 0 = "RTC_GPIO14" } }, - { pin = 15, functions = { 2 = "U0RTS" }, analog = { 0 = "XTAL_32K_P", 1 = "ADC2_CH4" }, rtc = { 0 = "RTC_GPIO15" } }, - { pin = 16, functions = { 2 = "U0CTS" }, analog = { 0 = "XTAL_32K_N", 1 = "ADC2_CH5" }, rtc = { 0 = "RTC_GPIO16" } }, - { pin = 17, functions = { 2 = "U1TXD" }, analog = { 1 = "ADC2_CH6" }, rtc = { 0 = "RTC_GPIO17" } }, - { pin = 18, functions = { 2 = "U1RXD", 3 = "CLK_OUT3" }, analog = { 1 = "ADC2_CH7" }, rtc = { 0 = "RTC_GPIO18" } }, - { pin = 19, functions = { 2 = "U1RTS", 3 = "CLK_OUT2" }, analog = { 0 = "USB_DM", 1 = "ADC2_CH8" }, rtc = { 0 = "RTC_GPIO19" } }, - { pin = 20, functions = { 2 = "U1CTS", 3 = "CLK_OUT1" }, analog = { 0 = "USB_DP", 1 = "ADC2_CH9" }, rtc = { 0 = "RTC_GPIO20" } }, - { pin = 21, rtc = { 0 = "RTC_GPIO21" } }, - - { pin = 26, functions = { 0 = "SPICS1" }, limitations = [ - "spi_psram", - ] }, - { pin = 27, functions = { 0 = "SPIHD" }, limitations = [ - "spi_flash", - "spi_psram", - ] }, - { pin = 28, functions = { 0 = "SPIWP" }, limitations = [ - "spi_flash", - "spi_psram", - ] }, - { pin = 29, functions = { 0 = "SPICS0" }, limitations = [ - "spi_flash", - "spi_psram", - ] }, - { pin = 30, functions = { 0 = "SPICLK" }, limitations = [ - "spi_flash", - "spi_psram", - ] }, - { pin = 31, functions = { 0 = "SPIQ" }, limitations = [ - "spi_flash", - "spi_psram", - ] }, - { pin = 32, functions = { 0 = "SPID" }, limitations = [ - "spi_flash", - ] }, - { pin = 33, functions = { 2 = "FSPIHD", 3 = "SUBSPIHD", 4 = "SPIIO4" }, limitations = [ - "octal_flash", - "octal_psram", - ] }, - { pin = 34, functions = { 2 = "FSPICS0", 3 = "SUBSPICS0", 4 = "SPIIO5" }, limitations = [ - "octal_flash", - "octal_psram", - ] }, - { pin = 35, functions = { 2 = "FSPID", 3 = "SUBSPID", 4 = "SPIIO6" }, limitations = [ - "octal_flash", - "octal_psram", - ] }, - { pin = 36, functions = { 2 = "FSPICLK", 3 = "SUBSPICLK", 4 = "SPIIO7" }, limitations = [ - "octal_flash", - "octal_psram", - ] }, - { pin = 37, functions = { 2 = "FSPIQ", 3 = "SUBSPIQ", 4 = "SPIDQS" }, limitations = [ - "octal_flash", - "octal_psram", - ] }, - { pin = 38, functions = { 2 = "FSPIWP", 3 = "SUBSPIWP" } }, - { pin = 39, functions = { 0 = "MTCK", 2 = "CLK_OUT3", 3 = "SUBSPICS1" } }, + { pin = 0, rtc = { 0 = "RTC_GPIO0", 1 = "SAR_I2C_SCL_0" }, limitations = ["strapping"] }, + { pin = 1, analog = { 0 = "TOUCH1", 1 = "ADC1_CH0" }, rtc = { 0 = "RTC_GPIO1", 1 = "SAR_I2C_SDA_0" } }, + { pin = 2, analog = { 0 = "TOUCH2", 1 = "ADC1_CH1" }, rtc = { 0 = "RTC_GPIO2", 1 = "SAR_I2C_SCL_1" } }, + { pin = 3, analog = { 0 = "TOUCH3", 1 = "ADC1_CH2" }, rtc = { 0 = "RTC_GPIO3", 1 = "SAR_I2C_SDA_1" }, limitations = ["strapping"] }, + { pin = 4, analog = { 0 = "TOUCH4", 1 = "ADC1_CH3" }, rtc = { 0 = "RTC_GPIO4" } }, + { pin = 5, analog = { 0 = "TOUCH5", 1 = "ADC1_CH4" }, rtc = { 0 = "RTC_GPIO5" } }, + { pin = 6, analog = { 0 = "TOUCH6", 1 = "ADC1_CH5" }, rtc = { 0 = "RTC_GPIO6" } }, + { pin = 7, analog = { 0 = "TOUCH7", 1 = "ADC1_CH6" }, rtc = { 0 = "RTC_GPIO7" } }, + { pin = 8, functions = { 3 = "SUBSPICS1" }, analog = { 0 = "TOUCH8", 1 = "ADC1_CH7" }, rtc = { 0 = "RTC_GPIO8" } }, + { pin = 9, functions = { 3 = "SUBSPIHD", 4 = "FSPIHD" }, analog = { 0 = "TOUCH9", 1 = "ADC1_CH8" }, rtc = { 0 = "RTC_GPIO9" } }, + { pin = 10, functions = { 2 = "FSPIIO4", 3 = "SUBSPICS0", 4 = "FSPICS0" }, analog = { 0 = "TOUCH10", 1 = "ADC1_CH9" }, rtc = { 0 = "RTC_GPIO10" } }, + { pin = 11, functions = { 2 = "FSPIIO5", 3 = "SUBSPID", 4 = "FSPID" }, analog = { 0 = "TOUCH11", 1 = "ADC2_CH0" }, rtc = { 0 = "RTC_GPIO11" } }, + { pin = 12, functions = { 2 = "FSPIIO6", 3 = "SUBSPICLK", 4 = "FSPICLK" }, analog = { 0 = "TOUCH12", 1 = "ADC2_CH1" }, rtc = { 0 = "RTC_GPIO12" } }, + { pin = 13, functions = { 2 = "FSPIIO7", 3 = "SUBSPIQ", 4 = "FSPIQ" }, analog = { 0 = "TOUCH13", 1 = "ADC2_CH2" }, rtc = { 0 = "RTC_GPIO13" } }, + { pin = 14, functions = { 2 = "FSPIDQS", 3 = "SUBSPIWP", 4 = "FSPIWP" }, analog = { 0 = "TOUCH14", 1 = "ADC2_CH3" }, rtc = { 0 = "RTC_GPIO14" } }, + { pin = 15, functions = { 2 = "U0RTS" }, analog = { 0 = "XTAL_32K_P", 1 = "ADC2_CH4" }, rtc = { 0 = "RTC_GPIO15" } }, + { pin = 16, functions = { 2 = "U0CTS" }, analog = { 0 = "XTAL_32K_N", 1 = "ADC2_CH5" }, rtc = { 0 = "RTC_GPIO16" } }, + { pin = 17, functions = { 2 = "U1TXD" }, analog = { 1 = "ADC2_CH6" }, rtc = { 0 = "RTC_GPIO17" } }, + { pin = 18, functions = { 2 = "U1RXD", 3 = "CLK_OUT3" }, analog = { 1 = "ADC2_CH7" }, rtc = { 0 = "RTC_GPIO18" } }, + { pin = 19, functions = { 2 = "U1RTS", 3 = "CLK_OUT2" }, analog = { 0 = "USB_DM", 1 = "ADC2_CH8" }, rtc = { 0 = "RTC_GPIO19" } }, + { pin = 20, functions = { 2 = "U1CTS", 3 = "CLK_OUT1" }, analog = { 0 = "USB_DP", 1 = "ADC2_CH9" }, rtc = { 0 = "RTC_GPIO20" } }, + { pin = 21, rtc = { 0 = "RTC_GPIO21" } }, + + { pin = 26, functions = { 0 = "SPICS1" }, limitations = ["spi_psram"] }, + { pin = 27, functions = { 0 = "SPIHD" }, limitations = ["spi_flash", "spi_psram"] }, + { pin = 28, functions = { 0 = "SPIWP" }, limitations = ["spi_flash", "spi_psram"] }, + { pin = 29, functions = { 0 = "SPICS0" }, limitations = ["spi_flash", "spi_psram"] }, + { pin = 30, functions = { 0 = "SPICLK" }, limitations = ["spi_flash", "spi_psram"] }, + { pin = 31, functions = { 0 = "SPIQ" }, limitations = ["spi_flash", "spi_psram"] }, + { pin = 32, functions = { 0 = "SPID" }, limitations = ["spi_flash"] }, + { pin = 33, functions = { 2 = "FSPIHD", 3 = "SUBSPIHD", 4 = "SPIIO4" }, limitations = ["octal_flash", "octal_psram"] }, + { pin = 34, functions = { 2 = "FSPICS0", 3 = "SUBSPICS0", 4 = "SPIIO5" }, limitations = ["octal_flash", "octal_psram"] }, + { pin = 35, functions = { 2 = "FSPID", 3 = "SUBSPID", 4 = "SPIIO6" }, limitations = ["octal_flash", "octal_psram"] }, + { pin = 36, functions = { 2 = "FSPICLK", 3 = "SUBSPICLK", 4 = "SPIIO7" }, limitations = ["octal_flash", "octal_psram"] }, + { pin = 37, functions = { 2 = "FSPIQ", 3 = "SUBSPIQ", 4 = "SPIDQS" }, limitations = ["octal_flash", "octal_psram"] }, + { pin = 38, functions = { 2 = "FSPIWP", 3 = "SUBSPIWP" } }, + { pin = 39, functions = { 0 = "MTCK", 2 = "CLK_OUT3", 3 = "SUBSPICS1" } }, { pin = 40, functions = { 0 = "MTDO", 2 = "CLK_OUT2" } }, { pin = 41, functions = { 0 = "MTDI", 2 = "CLK_OUT1" } }, { pin = 42, functions = { 0 = "MTMS" } }, { pin = 43, functions = { 0 = "U0TXD", 2 = "CLK_OUT1" } }, { pin = 44, functions = { 0 = "U0RXD", 2 = "CLK_OUT2" } }, - { pin = 45, limitations = [ - "strapping", - ] }, - { pin = 46, limitations = [ - "strapping", - ] }, + { pin = 45, limitations = ["strapping"] }, + { pin = 46, limitations = ["strapping"] }, { pin = 47, functions = { 0 = "SPICLK_P_DIFF", 2 = "SUBSPICLK_P_DIFF" } }, { pin = 48, functions = { 0 = "SPICLK_N_DIFF", 2 = "SUBSPICLK_N_DIFF" } }, ] input_signals = [ - { name = "SPIQ", id = 0 }, - { name = "SPID", id = 1 }, - { name = "SPIHD", id = 2 }, - { name = "SPIWP", id = 3 }, - { name = "SPID4", id = 7 }, - { name = "SPID5", id = 8 }, - { name = "SPID6", id = 9 }, - { name = "SPID7", id = 10 }, - { name = "SPIDQS", id = 11 }, - { name = "U0RXD", id = 12 }, - { name = "U0CTS", id = 13 }, - { name = "U0DSR", id = 14 }, - { name = "U1RXD", id = 15 }, - { name = "U1CTS", id = 16 }, - { name = "U1DSR", id = 17 }, - { name = "U2RXD", id = 18 }, - { name = "U2CTS", id = 19 }, - { name = "U2DSR", id = 20 }, - { name = "I2S1_MCLK", id = 21 }, - { name = "I2S0O_BCK", id = 22 }, - { name = "I2S0_MCLK", id = 23 }, - { name = "I2S0O_WS", id = 24 }, - { name = "I2S0I_SD", id = 25 }, - { name = "I2S0I_BCK", id = 26 }, - { name = "I2S0I_WS", id = 27 }, - { name = "I2S1O_BCK", id = 28 }, - { name = "I2S1O_WS", id = 29 }, - { name = "I2S1I_SD", id = 30 }, - { name = "I2S1I_BCK", id = 31 }, - { name = "I2S1I_WS", id = 32 }, - { name = "PCNT0_SIG_CH0", id = 33 }, - { name = "PCNT0_SIG_CH1", id = 34 }, - { name = "PCNT0_CTRL_CH0", id = 35 }, - { name = "PCNT0_CTRL_CH1", id = 36 }, - { name = "PCNT1_SIG_CH0", id = 37 }, - { name = "PCNT1_SIG_CH1", id = 38 }, - { name = "PCNT1_CTRL_CH0", id = 39 }, - { name = "PCNT1_CTRL_CH1", id = 40 }, - { name = "PCNT2_SIG_CH0", id = 41 }, - { name = "PCNT2_SIG_CH1", id = 42 }, - { name = "PCNT2_CTRL_CH0", id = 43 }, - { name = "PCNT2_CTRL_CH1", id = 44 }, - { name = "PCNT3_SIG_CH0", id = 45 }, - { name = "PCNT3_SIG_CH1", id = 46 }, - { name = "PCNT3_CTRL_CH0", id = 47 }, - { name = "PCNT3_CTRL_CH1", id = 48 }, - { name = "I2S0I_SD1", id = 51 }, - { name = "I2S0I_SD2", id = 52 }, - { name = "I2S0I_SD3", id = 53 }, - { name = "CORE1_GPIO7", id = 54 }, - { name = "USB_EXTPHY_VP", id = 55 }, - { name = "USB_EXTPHY_VM", id = 56 }, - { name = "USB_EXTPHY_RCV", id = 57 }, - { name = "USB_OTG_IDDIG", id = 58 }, - { name = "USB_OTG_AVALID", id = 59 }, - { name = "USB_SRP_BVALID", id = 60 }, - { name = "USB_OTG_VBUSVALID", id = 61 }, - { name = "USB_SRP_SESSEND", id = 62 }, - { name = "SPI3_CLK", id = 66 }, - { name = "SPI3_Q", id = 67 }, - { name = "SPI3_D", id = 68 }, - { name = "SPI3_HD", id = 69 }, - { name = "SPI3_WP", id = 70 }, - { name = "SPI3_CS0", id = 71 }, - { name = "RMT_SIG_0", id = 81 }, - { name = "RMT_SIG_1", id = 82 }, - { name = "RMT_SIG_2", id = 83 }, - { name = "RMT_SIG_3", id = 84 }, - { name = "I2CEXT0_SCL", id = 89 }, - { name = "I2CEXT0_SDA", id = 90 }, - { name = "I2CEXT1_SCL", id = 91 }, - { name = "I2CEXT1_SDA", id = 92 }, - { name = "FSPICLK", id = 101 }, - { name = "FSPIQ", id = 102 }, - { name = "FSPID", id = 103 }, - { name = "FSPIHD", id = 104 }, - { name = "FSPIWP", id = 105 }, - { name = "FSPIIO4", id = 106 }, - { name = "FSPIIO5", id = 107 }, - { name = "FSPIIO6", id = 108 }, - { name = "FSPIIO7", id = 109 }, - { name = "FSPICS0", id = 110 }, - { name = "TWAI_RX", id = 116 }, - { name = "SUBSPIQ", id = 120 }, - { name = "SUBSPID", id = 121 }, - { name = "SUBSPIHD", id = 122 }, - { name = "SUBSPIWP", id = 123 }, - { name = "CORE1_GPIO0", id = 129 }, - { name = "CORE1_GPIO1", id = 130 }, - { name = "CORE1_GPIO2", id = 131 }, - { name = "CAM_DATA_0", id = 133 }, - { name = "CAM_DATA_1", id = 134 }, - { name = "CAM_DATA_2", id = 135 }, - { name = "CAM_DATA_3", id = 136 }, - { name = "CAM_DATA_4", id = 137 }, - { name = "CAM_DATA_5", id = 138 }, - { name = "CAM_DATA_6", id = 139 }, - { name = "CAM_DATA_7", id = 140 }, - { name = "CAM_DATA_8", id = 141 }, - { name = "CAM_DATA_9", id = 142 }, - { name = "CAM_DATA_10", id = 143 }, - { name = "CAM_DATA_11", id = 144 }, - { name = "CAM_DATA_12", id = 145 }, - { name = "CAM_DATA_13", id = 146 }, - { name = "CAM_DATA_14", id = 147 }, - { name = "CAM_DATA_15", id = 148 }, - { name = "CAM_PCLK", id = 149 }, - { name = "CAM_H_ENABLE", id = 150 }, - { name = "CAM_H_SYNC", id = 151 }, - { name = "CAM_V_SYNC", id = 152 }, - { name = "SUBSPID4", id = 155 }, - { name = "SUBSPID5", id = 156 }, - { name = "SUBSPID6", id = 157 }, - { name = "SUBSPID7", id = 158 }, - { name = "SUBSPIDQS", id = 159 }, - { name = "PWM0_SYNC0", id = 160 }, - { name = "PWM0_SYNC1", id = 161 }, - { name = "PWM0_SYNC2", id = 162 }, - { name = "PWM0_F0", id = 163 }, - { name = "PWM0_F1", id = 164 }, - { name = "PWM0_F2", id = 165 }, - { name = "PWM0_CAP0", id = 166 }, - { name = "PWM0_CAP1", id = 167 }, - { name = "PWM0_CAP2", id = 168 }, - { name = "PWM1_SYNC0", id = 169 }, - { name = "PWM1_SYNC1", id = 170 }, - { name = "PWM1_SYNC2", id = 171 }, - { name = "PWM1_F0", id = 172 }, - { name = "PWM1_F1", id = 173 }, - { name = "PWM1_F2", id = 174 }, - { name = "PWM1_CAP0", id = 175 }, - { name = "PWM1_CAP1", id = 176 }, - { name = "PWM1_CAP2", id = 177 }, - { name = "SDHOST_CCMD_IN_1", id = 178 }, - { name = "SDHOST_CCMD_IN_2", id = 179 }, - { name = "SDHOST_CDATA_IN_10", id = 180 }, - { name = "SDHOST_CDATA_IN_11", id = 181 }, - { name = "SDHOST_CDATA_IN_12", id = 182 }, - { name = "SDHOST_CDATA_IN_13", id = 183 }, - { name = "SDHOST_CDATA_IN_14", id = 184 }, - { name = "SDHOST_CDATA_IN_15", id = 185 }, - { name = "SDHOST_CDATA_IN_16", id = 186 }, - { name = "SDHOST_CDATA_IN_17", id = 187 }, - { name = "SDHOST_DATA_STROBE_1", id = 192 }, - { name = "SDHOST_DATA_STROBE_2", id = 193 }, - { name = "SDHOST_CARD_DETECT_N_1", id = 194 }, - { name = "SDHOST_CARD_DETECT_N_2", id = 195 }, + { name = "SPIQ", id = 0 }, + { name = "SPID", id = 1 }, + { name = "SPIHD", id = 2 }, + { name = "SPIWP", id = 3 }, + { name = "SPID4", id = 7 }, + { name = "SPID5", id = 8 }, + { name = "SPID6", id = 9 }, + { name = "SPID7", id = 10 }, + { name = "SPIDQS", id = 11 }, + { name = "U0RXD", id = 12 }, + { name = "U0CTS", id = 13 }, + { name = "U0DSR", id = 14 }, + { name = "U1RXD", id = 15 }, + { name = "U1CTS", id = 16 }, + { name = "U1DSR", id = 17 }, + { name = "U2RXD", id = 18 }, + { name = "U2CTS", id = 19 }, + { name = "U2DSR", id = 20 }, + { name = "I2S1_MCLK", id = 21 }, + { name = "I2S0O_BCK", id = 22 }, + { name = "I2S0_MCLK", id = 23 }, + { name = "I2S0O_WS", id = 24 }, + { name = "I2S0I_SD", id = 25 }, + { name = "I2S0I_BCK", id = 26 }, + { name = "I2S0I_WS", id = 27 }, + { name = "I2S1O_BCK", id = 28 }, + { name = "I2S1O_WS", id = 29 }, + { name = "I2S1I_SD", id = 30 }, + { name = "I2S1I_BCK", id = 31 }, + { name = "I2S1I_WS", id = 32 }, + { name = "PCNT0_SIG_CH0", id = 33 }, + { name = "PCNT0_SIG_CH1", id = 34 }, + { name = "PCNT0_CTRL_CH0", id = 35 }, + { name = "PCNT0_CTRL_CH1", id = 36 }, + { name = "PCNT1_SIG_CH0", id = 37 }, + { name = "PCNT1_SIG_CH1", id = 38 }, + { name = "PCNT1_CTRL_CH0", id = 39 }, + { name = "PCNT1_CTRL_CH1", id = 40 }, + { name = "PCNT2_SIG_CH0", id = 41 }, + { name = "PCNT2_SIG_CH1", id = 42 }, + { name = "PCNT2_CTRL_CH0", id = 43 }, + { name = "PCNT2_CTRL_CH1", id = 44 }, + { name = "PCNT3_SIG_CH0", id = 45 }, + { name = "PCNT3_SIG_CH1", id = 46 }, + { name = "PCNT3_CTRL_CH0", id = 47 }, + { name = "PCNT3_CTRL_CH1", id = 48 }, + { name = "I2S0I_SD1", id = 51 }, + { name = "I2S0I_SD2", id = 52 }, + { name = "I2S0I_SD3", id = 53 }, + { name = "CORE1_GPIO7", id = 54 }, + { name = "USB_EXTPHY_VP", id = 55 }, + { name = "USB_EXTPHY_VM", id = 56 }, + { name = "USB_EXTPHY_RCV", id = 57 }, + { name = "USB_OTG_IDDIG", id = 58 }, + { name = "USB_OTG_AVALID", id = 59 }, + { name = "USB_SRP_BVALID", id = 60 }, + { name = "USB_OTG_VBUSVALID", id = 61 }, + { name = "USB_SRP_SESSEND", id = 62 }, + { name = "SPI3_CLK", id = 66 }, + { name = "SPI3_Q", id = 67 }, + { name = "SPI3_D", id = 68 }, + { name = "SPI3_HD", id = 69 }, + { name = "SPI3_WP", id = 70 }, + { name = "SPI3_CS0", id = 71 }, + { name = "RMT_SIG_0", id = 81 }, + { name = "RMT_SIG_1", id = 82 }, + { name = "RMT_SIG_2", id = 83 }, + { name = "RMT_SIG_3", id = 84 }, + { name = "I2CEXT0_SCL", id = 89 }, + { name = "I2CEXT0_SDA", id = 90 }, + { name = "I2CEXT1_SCL", id = 91 }, + { name = "I2CEXT1_SDA", id = 92 }, + { name = "FSPICLK", id = 101 }, + { name = "FSPIQ", id = 102 }, + { name = "FSPID", id = 103 }, + { name = "FSPIHD", id = 104 }, + { name = "FSPIWP", id = 105 }, + { name = "FSPIIO4", id = 106 }, + { name = "FSPIIO5", id = 107 }, + { name = "FSPIIO6", id = 108 }, + { name = "FSPIIO7", id = 109 }, + { name = "FSPICS0", id = 110 }, + { name = "TWAI_RX", id = 116 }, + { name = "SUBSPIQ", id = 120 }, + { name = "SUBSPID", id = 121 }, + { name = "SUBSPIHD", id = 122 }, + { name = "SUBSPIWP", id = 123 }, + { name = "CORE1_GPIO0", id = 129 }, + { name = "CORE1_GPIO1", id = 130 }, + { name = "CORE1_GPIO2", id = 131 }, + { name = "CAM_DATA_0", id = 133 }, + { name = "CAM_DATA_1", id = 134 }, + { name = "CAM_DATA_2", id = 135 }, + { name = "CAM_DATA_3", id = 136 }, + { name = "CAM_DATA_4", id = 137 }, + { name = "CAM_DATA_5", id = 138 }, + { name = "CAM_DATA_6", id = 139 }, + { name = "CAM_DATA_7", id = 140 }, + { name = "CAM_DATA_8", id = 141 }, + { name = "CAM_DATA_9", id = 142 }, + { name = "CAM_DATA_10", id = 143 }, + { name = "CAM_DATA_11", id = 144 }, + { name = "CAM_DATA_12", id = 145 }, + { name = "CAM_DATA_13", id = 146 }, + { name = "CAM_DATA_14", id = 147 }, + { name = "CAM_DATA_15", id = 148 }, + { name = "CAM_PCLK", id = 149 }, + { name = "CAM_H_ENABLE", id = 150 }, + { name = "CAM_H_SYNC", id = 151 }, + { name = "CAM_V_SYNC", id = 152 }, + { name = "SUBSPID4", id = 155 }, + { name = "SUBSPID5", id = 156 }, + { name = "SUBSPID6", id = 157 }, + { name = "SUBSPID7", id = 158 }, + { name = "SUBSPIDQS", id = 159 }, + { name = "PWM0_SYNC0", id = 160 }, + { name = "PWM0_SYNC1", id = 161 }, + { name = "PWM0_SYNC2", id = 162 }, + { name = "PWM0_F0", id = 163 }, + { name = "PWM0_F1", id = 164 }, + { name = "PWM0_F2", id = 165 }, + { name = "PWM0_CAP0", id = 166 }, + { name = "PWM0_CAP1", id = 167 }, + { name = "PWM0_CAP2", id = 168 }, + { name = "PWM1_SYNC0", id = 169 }, + { name = "PWM1_SYNC1", id = 170 }, + { name = "PWM1_SYNC2", id = 171 }, + { name = "PWM1_F0", id = 172 }, + { name = "PWM1_F1", id = 173 }, + { name = "PWM1_F2", id = 174 }, + { name = "PWM1_CAP0", id = 175 }, + { name = "PWM1_CAP1", id = 176 }, + { name = "PWM1_CAP2", id = 177 }, + { name = "SDHOST_CCMD_IN_1", id = 178 }, + { name = "SDHOST_CCMD_IN_2", id = 179 }, + { name = "SDHOST_CDATA_IN_10", id = 180 }, + { name = "SDHOST_CDATA_IN_11", id = 181 }, + { name = "SDHOST_CDATA_IN_12", id = 182 }, + { name = "SDHOST_CDATA_IN_13", id = 183 }, + { name = "SDHOST_CDATA_IN_14", id = 184 }, + { name = "SDHOST_CDATA_IN_15", id = 185 }, + { name = "SDHOST_CDATA_IN_16", id = 186 }, + { name = "SDHOST_CDATA_IN_17", id = 187 }, + { name = "SDHOST_DATA_STROBE_1", id = 192 }, + { name = "SDHOST_DATA_STROBE_2", id = 193 }, + { name = "SDHOST_CARD_DETECT_N_1", id = 194 }, + { name = "SDHOST_CARD_DETECT_N_2", id = 195 }, { name = "SDHOST_CARD_WRITE_PRT_1", id = 196 }, { name = "SDHOST_CARD_WRITE_PRT_2", id = 197 }, - { name = "SDHOST_CARD_INT_N_1", id = 198 }, - { name = "SDHOST_CARD_INT_N_2", id = 199 }, - { name = "SDHOST_CDATA_IN_20", id = 213 }, - { name = "SDHOST_CDATA_IN_21", id = 214 }, - { name = "SDHOST_CDATA_IN_22", id = 215 }, - { name = "SDHOST_CDATA_IN_23", id = 216 }, - { name = "SDHOST_CDATA_IN_24", id = 217 }, - { name = "SDHOST_CDATA_IN_25", id = 218 }, - { name = "SDHOST_CDATA_IN_26", id = 219 }, - { name = "SDHOST_CDATA_IN_27", id = 220 }, - - { name = "PRO_ALONEGPIO0", id = 221 }, - { name = "PRO_ALONEGPIO1", id = 222 }, - { name = "PRO_ALONEGPIO2", id = 223 }, - { name = "PRO_ALONEGPIO3", id = 224 }, - { name = "PRO_ALONEGPIO4", id = 225 }, - { name = "PRO_ALONEGPIO5", id = 226 }, - { name = "PRO_ALONEGPIO6", id = 227 }, - { name = "PRO_ALONEGPIO7", id = 228 }, - - { name = "USB_JTAG_TDO_BRIDGE", id = 251 }, - { name = "CORE1_GPIO3", id = 252 }, - { name = "CORE1_GPIO4", id = 253 }, - { name = "CORE1_GPIO5", id = 254 }, - { name = "CORE1_GPIO6", id = 255 }, + { name = "SDHOST_CARD_INT_N_1", id = 198 }, + { name = "SDHOST_CARD_INT_N_2", id = 199 }, + { name = "SDHOST_CDATA_IN_20", id = 213 }, + { name = "SDHOST_CDATA_IN_21", id = 214 }, + { name = "SDHOST_CDATA_IN_22", id = 215 }, + { name = "SDHOST_CDATA_IN_23", id = 216 }, + { name = "SDHOST_CDATA_IN_24", id = 217 }, + { name = "SDHOST_CDATA_IN_25", id = 218 }, + { name = "SDHOST_CDATA_IN_26", id = 219 }, + { name = "SDHOST_CDATA_IN_27", id = 220 }, + + { name = "PRO_ALONEGPIO0", id = 221 }, + { name = "PRO_ALONEGPIO1", id = 222 }, + { name = "PRO_ALONEGPIO2", id = 223 }, + { name = "PRO_ALONEGPIO3", id = 224 }, + { name = "PRO_ALONEGPIO4", id = 225 }, + { name = "PRO_ALONEGPIO5", id = 226 }, + { name = "PRO_ALONEGPIO6", id = 227 }, + { name = "PRO_ALONEGPIO7", id = 228 }, + + { name = "USB_JTAG_TDO_BRIDGE", id = 251 }, + { name = "CORE1_GPIO3", id = 252 }, + { name = "CORE1_GPIO4", id = 253 }, + { name = "CORE1_GPIO5", id = 254 }, + { name = "CORE1_GPIO6", id = 255 }, { name = "SPIIO4" }, { name = "SPIIO5" }, @@ -600,184 +548,184 @@ input_signals = [ { name = "MTMS" }, ] output_signals = [ - { name = "SPIQ", id = 0 }, - { name = "SPID", id = 1 }, - { name = "SPIHD", id = 2 }, - { name = "SPIWP", id = 3 }, - { name = "SPICLK", id = 4 }, - { name = "SPICS0", id = 5 }, - { name = "SPICS1", id = 6 }, - { name = "SPID4", id = 7 }, - { name = "SPID5", id = 8 }, - { name = "SPID6", id = 9 }, - { name = "SPID7", id = 10 }, - { name = "SPIDQS", id = 11 }, - { name = "U0TXD", id = 12 }, - { name = "U0RTS", id = 13 }, - { name = "U0DTR", id = 14 }, - { name = "U1TXD", id = 15 }, - { name = "U1RTS", id = 16 }, - { name = "U1DTR", id = 17 }, - { name = "U2TXD", id = 18 }, - { name = "U2RTS", id = 19 }, - { name = "U2DTR", id = 20 }, - { name = "I2S1_MCLK", id = 21 }, - { name = "I2S0O_BCK", id = 22 }, - { name = "I2S0_MCLK", id = 23 }, - { name = "I2S0O_WS", id = 24 }, - { name = "I2S0O_SD", id = 25 }, - { name = "I2S0I_BCK", id = 26 }, - { name = "I2S0I_WS", id = 27 }, - { name = "I2S1O_BCK", id = 28 }, - { name = "I2S1O_WS", id = 29 }, - { name = "I2S1O_SD", id = 30 }, - { name = "I2S1I_BCK", id = 31 }, - { name = "I2S1I_WS", id = 32 }, - { name = "CORE1_GPIO7", id = 54 }, - { name = "USB_EXTPHY_OEN", id = 55 }, - { name = "USB_EXTPHY_VPO", id = 57 }, - { name = "USB_EXTPHY_VMO", id = 58 }, - { name = "SPI3_CLK", id = 66 }, - { name = "SPI3_Q", id = 67 }, - { name = "SPI3_D", id = 68 }, - { name = "SPI3_HD", id = 69 }, - { name = "SPI3_WP", id = 70 }, - { name = "SPI3_CS0", id = 71 }, - { name = "SPI3_CS1", id = 72 }, - { name = "LEDC_LS_SIG0", id = 73 }, - { name = "LEDC_LS_SIG1", id = 74 }, - { name = "LEDC_LS_SIG2", id = 75 }, - { name = "LEDC_LS_SIG3", id = 76 }, - { name = "LEDC_LS_SIG4", id = 77 }, - { name = "LEDC_LS_SIG5", id = 78 }, - { name = "LEDC_LS_SIG6", id = 79 }, - { name = "LEDC_LS_SIG7", id = 80 }, - { name = "RMT_SIG_0", id = 81 }, - { name = "RMT_SIG_1", id = 82 }, - { name = "RMT_SIG_2", id = 83 }, - { name = "RMT_SIG_3", id = 84 }, - { name = "I2CEXT0_SCL", id = 89 }, - { name = "I2CEXT0_SDA", id = 90 }, - { name = "I2CEXT1_SCL", id = 91 }, - { name = "I2CEXT1_SDA", id = 92 }, - { name = "GPIO_SD0", id = 93 }, - { name = "GPIO_SD1", id = 94 }, - { name = "GPIO_SD2", id = 95 }, - { name = "GPIO_SD3", id = 96 }, - { name = "GPIO_SD4", id = 97 }, - { name = "GPIO_SD5", id = 98 }, - { name = "GPIO_SD6", id = 99 }, - { name = "GPIO_SD7", id = 100 }, - { name = "FSPICLK", id = 101 }, - { name = "FSPIQ", id = 102 }, - { name = "FSPID", id = 103 }, - { name = "FSPIHD", id = 104 }, - { name = "FSPIWP", id = 105 }, - { name = "FSPIIO4", id = 106 }, - { name = "FSPIIO5", id = 107 }, - { name = "FSPIIO6", id = 108 }, - { name = "FSPIIO7", id = 109 }, - { name = "FSPICS0", id = 110 }, - { name = "FSPICS1", id = 111 }, - { name = "FSPICS2", id = 112 }, - { name = "FSPICS3", id = 113 }, - { name = "FSPICS4", id = 114 }, - { name = "FSPICS5", id = 115 }, - { name = "TWAI_TX", id = 116 }, - { name = "SUBSPICLK", id = 119 }, - { name = "SUBSPIQ", id = 120 }, - { name = "SUBSPID", id = 121 }, - { name = "SUBSPIHD", id = 122 }, - { name = "SUBSPIWP", id = 123 }, - { name = "SUBSPICS0", id = 124 }, - { name = "SUBSPICS1", id = 125 }, - { name = "FSPIDQS", id = 126 }, - { name = "SPI3_CS2", id = 127 }, - { name = "I2S0O_SD1", id = 128 }, - { name = "CORE1_GPIO0", id = 129 }, - { name = "CORE1_GPIO1", id = 130 }, - { name = "CORE1_GPIO2", id = 131 }, - { name = "LCD_CS", id = 132 }, - { name = "LCD_DATA_0", id = 133 }, - { name = "LCD_DATA_1", id = 134 }, - { name = "LCD_DATA_2", id = 135 }, - { name = "LCD_DATA_3", id = 136 }, - { name = "LCD_DATA_4", id = 137 }, - { name = "LCD_DATA_5", id = 138 }, - { name = "LCD_DATA_6", id = 139 }, - { name = "LCD_DATA_7", id = 140 }, - { name = "LCD_DATA_8", id = 141 }, - { name = "LCD_DATA_9", id = 142 }, - { name = "LCD_DATA_10", id = 143 }, - { name = "LCD_DATA_11", id = 144 }, - { name = "LCD_DATA_12", id = 145 }, - { name = "LCD_DATA_13", id = 146 }, - { name = "LCD_DATA_14", id = 147 }, - { name = "LCD_DATA_15", id = 148 }, - { name = "CAM_CLK", id = 149 }, - { name = "LCD_H_ENABLE", id = 150 }, - { name = "LCD_H_SYNC", id = 151 }, - { name = "LCD_V_SYNC", id = 152 }, - { name = "LCD_DC", id = 153 }, - { name = "LCD_PCLK", id = 154 }, - { name = "SUBSPID4", id = 155 }, - { name = "SUBSPID5", id = 156 }, - { name = "SUBSPID6", id = 157 }, - { name = "SUBSPID7", id = 158 }, - { name = "SUBSPIDQS", id = 159 }, - { name = "PWM0_0A", id = 160 }, - { name = "PWM0_0B", id = 161 }, - { name = "PWM0_1A", id = 162 }, - { name = "PWM0_1B", id = 163 }, - { name = "PWM0_2A", id = 164 }, - { name = "PWM0_2B", id = 165 }, - { name = "PWM1_0A", id = 166 }, - { name = "PWM1_0B", id = 167 }, - { name = "PWM1_1A", id = 168 }, - { name = "PWM1_1B", id = 169 }, - { name = "PWM1_2A", id = 170 }, - { name = "PWM1_2B", id = 171 }, - { name = "SDHOST_CCLK_OUT_1", id = 172 }, - { name = "SDHOST_CCLK_OUT_2", id = 173 }, - { name = "SDHOST_RST_N_1", id = 174 }, - { name = "SDHOST_RST_N_2", id = 175 }, + { name = "SPIQ", id = 0 }, + { name = "SPID", id = 1 }, + { name = "SPIHD", id = 2 }, + { name = "SPIWP", id = 3 }, + { name = "SPICLK", id = 4 }, + { name = "SPICS0", id = 5 }, + { name = "SPICS1", id = 6 }, + { name = "SPID4", id = 7 }, + { name = "SPID5", id = 8 }, + { name = "SPID6", id = 9 }, + { name = "SPID7", id = 10 }, + { name = "SPIDQS", id = 11 }, + { name = "U0TXD", id = 12 }, + { name = "U0RTS", id = 13 }, + { name = "U0DTR", id = 14 }, + { name = "U1TXD", id = 15 }, + { name = "U1RTS", id = 16 }, + { name = "U1DTR", id = 17 }, + { name = "U2TXD", id = 18 }, + { name = "U2RTS", id = 19 }, + { name = "U2DTR", id = 20 }, + { name = "I2S1_MCLK", id = 21 }, + { name = "I2S0O_BCK", id = 22 }, + { name = "I2S0_MCLK", id = 23 }, + { name = "I2S0O_WS", id = 24 }, + { name = "I2S0O_SD", id = 25 }, + { name = "I2S0I_BCK", id = 26 }, + { name = "I2S0I_WS", id = 27 }, + { name = "I2S1O_BCK", id = 28 }, + { name = "I2S1O_WS", id = 29 }, + { name = "I2S1O_SD", id = 30 }, + { name = "I2S1I_BCK", id = 31 }, + { name = "I2S1I_WS", id = 32 }, + { name = "CORE1_GPIO7", id = 54 }, + { name = "USB_EXTPHY_OEN", id = 55 }, + { name = "USB_EXTPHY_VPO", id = 57 }, + { name = "USB_EXTPHY_VMO", id = 58 }, + { name = "SPI3_CLK", id = 66 }, + { name = "SPI3_Q", id = 67 }, + { name = "SPI3_D", id = 68 }, + { name = "SPI3_HD", id = 69 }, + { name = "SPI3_WP", id = 70 }, + { name = "SPI3_CS0", id = 71 }, + { name = "SPI3_CS1", id = 72 }, + { name = "LEDC_LS_SIG0", id = 73 }, + { name = "LEDC_LS_SIG1", id = 74 }, + { name = "LEDC_LS_SIG2", id = 75 }, + { name = "LEDC_LS_SIG3", id = 76 }, + { name = "LEDC_LS_SIG4", id = 77 }, + { name = "LEDC_LS_SIG5", id = 78 }, + { name = "LEDC_LS_SIG6", id = 79 }, + { name = "LEDC_LS_SIG7", id = 80 }, + { name = "RMT_SIG_0", id = 81 }, + { name = "RMT_SIG_1", id = 82 }, + { name = "RMT_SIG_2", id = 83 }, + { name = "RMT_SIG_3", id = 84 }, + { name = "I2CEXT0_SCL", id = 89 }, + { name = "I2CEXT0_SDA", id = 90 }, + { name = "I2CEXT1_SCL", id = 91 }, + { name = "I2CEXT1_SDA", id = 92 }, + { name = "GPIO_SD0", id = 93 }, + { name = "GPIO_SD1", id = 94 }, + { name = "GPIO_SD2", id = 95 }, + { name = "GPIO_SD3", id = 96 }, + { name = "GPIO_SD4", id = 97 }, + { name = "GPIO_SD5", id = 98 }, + { name = "GPIO_SD6", id = 99 }, + { name = "GPIO_SD7", id = 100 }, + { name = "FSPICLK", id = 101 }, + { name = "FSPIQ", id = 102 }, + { name = "FSPID", id = 103 }, + { name = "FSPIHD", id = 104 }, + { name = "FSPIWP", id = 105 }, + { name = "FSPIIO4", id = 106 }, + { name = "FSPIIO5", id = 107 }, + { name = "FSPIIO6", id = 108 }, + { name = "FSPIIO7", id = 109 }, + { name = "FSPICS0", id = 110 }, + { name = "FSPICS1", id = 111 }, + { name = "FSPICS2", id = 112 }, + { name = "FSPICS3", id = 113 }, + { name = "FSPICS4", id = 114 }, + { name = "FSPICS5", id = 115 }, + { name = "TWAI_TX", id = 116 }, + { name = "SUBSPICLK", id = 119 }, + { name = "SUBSPIQ", id = 120 }, + { name = "SUBSPID", id = 121 }, + { name = "SUBSPIHD", id = 122 }, + { name = "SUBSPIWP", id = 123 }, + { name = "SUBSPICS0", id = 124 }, + { name = "SUBSPICS1", id = 125 }, + { name = "FSPIDQS", id = 126 }, + { name = "SPI3_CS2", id = 127 }, + { name = "I2S0O_SD1", id = 128 }, + { name = "CORE1_GPIO0", id = 129 }, + { name = "CORE1_GPIO1", id = 130 }, + { name = "CORE1_GPIO2", id = 131 }, + { name = "LCD_CS", id = 132 }, + { name = "LCD_DATA_0", id = 133 }, + { name = "LCD_DATA_1", id = 134 }, + { name = "LCD_DATA_2", id = 135 }, + { name = "LCD_DATA_3", id = 136 }, + { name = "LCD_DATA_4", id = 137 }, + { name = "LCD_DATA_5", id = 138 }, + { name = "LCD_DATA_6", id = 139 }, + { name = "LCD_DATA_7", id = 140 }, + { name = "LCD_DATA_8", id = 141 }, + { name = "LCD_DATA_9", id = 142 }, + { name = "LCD_DATA_10", id = 143 }, + { name = "LCD_DATA_11", id = 144 }, + { name = "LCD_DATA_12", id = 145 }, + { name = "LCD_DATA_13", id = 146 }, + { name = "LCD_DATA_14", id = 147 }, + { name = "LCD_DATA_15", id = 148 }, + { name = "CAM_CLK", id = 149 }, + { name = "LCD_H_ENABLE", id = 150 }, + { name = "LCD_H_SYNC", id = 151 }, + { name = "LCD_V_SYNC", id = 152 }, + { name = "LCD_DC", id = 153 }, + { name = "LCD_PCLK", id = 154 }, + { name = "SUBSPID4", id = 155 }, + { name = "SUBSPID5", id = 156 }, + { name = "SUBSPID6", id = 157 }, + { name = "SUBSPID7", id = 158 }, + { name = "SUBSPIDQS", id = 159 }, + { name = "PWM0_0A", id = 160 }, + { name = "PWM0_0B", id = 161 }, + { name = "PWM0_1A", id = 162 }, + { name = "PWM0_1B", id = 163 }, + { name = "PWM0_2A", id = 164 }, + { name = "PWM0_2B", id = 165 }, + { name = "PWM1_0A", id = 166 }, + { name = "PWM1_0B", id = 167 }, + { name = "PWM1_1A", id = 168 }, + { name = "PWM1_1B", id = 169 }, + { name = "PWM1_2A", id = 170 }, + { name = "PWM1_2B", id = 171 }, + { name = "SDHOST_CCLK_OUT_1", id = 172 }, + { name = "SDHOST_CCLK_OUT_2", id = 173 }, + { name = "SDHOST_RST_N_1", id = 174 }, + { name = "SDHOST_RST_N_2", id = 175 }, { name = "SDHOST_CCMD_OD_PULLUP_EN_N", id = 176 }, - { name = "SDIO_TOHOST_INT", id = 177 }, - { name = "SDHOST_CCMD_OUT_1", id = 178 }, - { name = "SDHOST_CCMD_OUT_2", id = 179 }, - { name = "SDHOST_CDATA_OUT_10", id = 180 }, - { name = "SDHOST_CDATA_OUT_11", id = 181 }, - { name = "SDHOST_CDATA_OUT_12", id = 182 }, - { name = "SDHOST_CDATA_OUT_13", id = 183 }, - { name = "SDHOST_CDATA_OUT_14", id = 184 }, - { name = "SDHOST_CDATA_OUT_15", id = 185 }, - { name = "SDHOST_CDATA_OUT_16", id = 186 }, - { name = "SDHOST_CDATA_OUT_17", id = 187 }, - { name = "SDHOST_CDATA_OUT_20", id = 213 }, - { name = "SDHOST_CDATA_OUT_21", id = 214 }, - { name = "SDHOST_CDATA_OUT_22", id = 215 }, - { name = "SDHOST_CDATA_OUT_23", id = 216 }, - { name = "SDHOST_CDATA_OUT_24", id = 217 }, - { name = "SDHOST_CDATA_OUT_25", id = 218 }, - { name = "SDHOST_CDATA_OUT_26", id = 219 }, - { name = "SDHOST_CDATA_OUT_27", id = 220 }, - - { name = "PRO_ALONEGPIO0", id = 221 }, - { name = "PRO_ALONEGPIO1", id = 222 }, - { name = "PRO_ALONEGPIO2", id = 223 }, - { name = "PRO_ALONEGPIO3", id = 224 }, - { name = "PRO_ALONEGPIO4", id = 225 }, - { name = "PRO_ALONEGPIO5", id = 226 }, - { name = "PRO_ALONEGPIO6", id = 227 }, - { name = "PRO_ALONEGPIO7", id = 228 }, - - { name = "USB_JTAG_TRST", id = 251 }, - { name = "CORE1_GPIO3", id = 252 }, - { name = "CORE1_GPIO4", id = 253 }, - { name = "CORE1_GPIO5", id = 254 }, - { name = "CORE1_GPIO6", id = 255 }, - - { name = "GPIO", id = 256 }, + { name = "SDIO_TOHOST_INT", id = 177 }, + { name = "SDHOST_CCMD_OUT_1", id = 178 }, + { name = "SDHOST_CCMD_OUT_2", id = 179 }, + { name = "SDHOST_CDATA_OUT_10", id = 180 }, + { name = "SDHOST_CDATA_OUT_11", id = 181 }, + { name = "SDHOST_CDATA_OUT_12", id = 182 }, + { name = "SDHOST_CDATA_OUT_13", id = 183 }, + { name = "SDHOST_CDATA_OUT_14", id = 184 }, + { name = "SDHOST_CDATA_OUT_15", id = 185 }, + { name = "SDHOST_CDATA_OUT_16", id = 186 }, + { name = "SDHOST_CDATA_OUT_17", id = 187 }, + { name = "SDHOST_CDATA_OUT_20", id = 213 }, + { name = "SDHOST_CDATA_OUT_21", id = 214 }, + { name = "SDHOST_CDATA_OUT_22", id = 215 }, + { name = "SDHOST_CDATA_OUT_23", id = 216 }, + { name = "SDHOST_CDATA_OUT_24", id = 217 }, + { name = "SDHOST_CDATA_OUT_25", id = 218 }, + { name = "SDHOST_CDATA_OUT_26", id = 219 }, + { name = "SDHOST_CDATA_OUT_27", id = 220 }, + + { name = "PRO_ALONEGPIO0", id = 221 }, + { name = "PRO_ALONEGPIO1", id = 222 }, + { name = "PRO_ALONEGPIO2", id = 223 }, + { name = "PRO_ALONEGPIO3", id = 224 }, + { name = "PRO_ALONEGPIO4", id = 225 }, + { name = "PRO_ALONEGPIO5", id = 226 }, + { name = "PRO_ALONEGPIO6", id = 227 }, + { name = "PRO_ALONEGPIO7", id = 228 }, + + { name = "USB_JTAG_TRST", id = 251 }, + { name = "CORE1_GPIO3", id = 252 }, + { name = "CORE1_GPIO4", id = 253 }, + { name = "CORE1_GPIO5", id = 254 }, + { name = "CORE1_GPIO6", id = 255 }, + + { name = "GPIO", id = 256 }, { name = "SPIIO4" }, { name = "SPIIO5" }, @@ -799,26 +747,8 @@ output_signals = [ [device.dedicated_gpio] support_status = "partial" channels = [ - [ - "PRO_ALONEGPIO0", - "PRO_ALONEGPIO1", - "PRO_ALONEGPIO2", - "PRO_ALONEGPIO3", - "PRO_ALONEGPIO4", - "PRO_ALONEGPIO5", - "PRO_ALONEGPIO6", - "PRO_ALONEGPIO7", - ], - [ - "CORE1_GPIO0", - "CORE1_GPIO1", - "CORE1_GPIO2", - "CORE1_GPIO3", - "CORE1_GPIO4", - "CORE1_GPIO5", - "CORE1_GPIO6", - "CORE1_GPIO7", - ], + ["PRO_ALONEGPIO0", "PRO_ALONEGPIO1", "PRO_ALONEGPIO2", "PRO_ALONEGPIO3", "PRO_ALONEGPIO4", "PRO_ALONEGPIO5", "PRO_ALONEGPIO6", "PRO_ALONEGPIO7"], + ["CORE1_GPIO0", "CORE1_GPIO1", "CORE1_GPIO2", "CORE1_GPIO3", "CORE1_GPIO4", "CORE1_GPIO5", "CORE1_GPIO6", "CORE1_GPIO7" ] ] needs_initialization = true @@ -863,7 +793,7 @@ has_tx_sync = true has_rx_wrap = true has_rx_demodulation = true has_dma = true -clock_sources.supported = ["None", "Apb", "RcFast", "Xtal"] +clock_sources.supported = [ "None", "Apb", "RcFast", "Xtal" ] clock_sources.default = "Apb" [device.rsa] @@ -883,40 +813,15 @@ has_octal = true has_app_interrupts = true has_dma_segmented_transfer = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = [ - "FSPID", - "FSPIQ", - "FSPIWP", - "FSPIHD", - "FSPIIO4", - "FSPIIO5", - "FSPIIO6", - "FSPIIO7", - ], cs = [ - "FSPICS0", - "FSPICS1", - "FSPICS2", - "FSPICS3", - "FSPICS4", - "FSPICS5", - ] }, - { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CLK", sio = [ - "SPI3_D", - "SPI3_Q", - "SPI3_WP", - "SPI3_HD", - ], cs = [ - "SPI3_CS0", - "SPI3_CS1", - "SPI3_CS2", - ] }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", sio = ["FSPID", "FSPIQ", "FSPIWP", "FSPIHD", "FSPIIO4", "FSPIIO5", "FSPIIO6", "FSPIIO7"], cs = ["FSPICS0", "FSPICS1", "FSPICS2", "FSPICS3", "FSPICS4", "FSPICS5"] }, + { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CLK", sio = ["SPI3_D", "SPI3_Q", "SPI3_WP", "SPI3_HD"], cs = ["SPI3_CS0", "SPI3_CS1", "SPI3_CS2"] }, ] [device.spi_slave] support_status = "partial" supports_dma = true instances = [ - { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, + { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CLK", mosi = "SPI3_D", miso = "SPI3_Q", cs = "SPI3_CS0" }, ] @@ -948,7 +853,7 @@ support_status = "not_supported" [device.rng] support_status = "partial" trng_supported = true -apb_cycle_wait_num = 16 # TODO +apb_cycle_wait_num = 16 # TODO [device.sleep] support_status = "partial" @@ -975,6 +880,8 @@ deep_sleep = true ## Miscellaneous [device.io_mux] [device.psram] +octal_spi = true + [device.systimer] [device.temp_sensor] [device.ulp_fsm] @@ -991,4 +898,4 @@ controller = "btdm" [device.phy] combo_module = true -backed_up_digital_register_count = 21 +backed_up_digital_register_count = 21 \ No newline at end of file From cd956468c83c288f64227c4a2098d0c22a9d5b81 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 12:01:08 -0600 Subject: [PATCH 19/37] Update _build_script_utils.rs --- esp-metadata-generated/src/_build_script_utils.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 5a45041ff42..de3826da8e0 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -2021,6 +2021,12 @@ impl Chip { "cargo:rustc-cfg=soc_has_mem2mem6", "cargo:rustc-cfg=soc_has_mem2mem7", "cargo:rustc-cfg=soc_has_mem2mem8", + "cargo:rustc-cfg=soc_has_psram", + "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=soc_has_mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=soc_has_mcpwm_support_etm", + "cargo:rustc-cfg=soc_has_mcpwm_support_event_comparator", + "cargo:rustc-cfg=soc_has_mcpwm_support_sleep_retention", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", From be9a6e47071826ca86b9ad736843b9d91eccd638 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 12:03:13 -0600 Subject: [PATCH 20/37] Fix typo in MCPWM capabilities comment --- esp-metadata/devices/esp32c6.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index cf9e118d962..26533747a4e 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -23,7 +23,7 @@ symbols = [ "rom_crc_be", "rom_md5_bsd", - # MCPWM capabilites + # MCPWM capabilities "soc_has_mcpwm_swsync_can_propagate", "soc_has_mcpwm_capture_clk_from_group", "soc_has_mcpwm_support_etm", @@ -786,4 +786,4 @@ controller = "npl" [device.ieee802154] [device.phy] -combo_module = true \ No newline at end of file +combo_module = true From 6cd9d007a1ceb4b9dee1c620f268d303b10b7427 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 12:04:19 -0600 Subject: [PATCH 21/37] Update temp_sensor support status in esp32c5.toml --- esp-metadata/devices/esp32c5.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp-metadata/devices/esp32c5.toml b/esp-metadata/devices/esp32c5.toml index c59ef033350..c23da1e2e03 100644 --- a/esp-metadata/devices/esp32c5.toml +++ b/esp-metadata/devices/esp32c5.toml @@ -713,11 +713,11 @@ support_status = { status = "not_supported", issue = 5172 } [device.sd_slave] support_status = { status = "not_supported", issue = 5169 } +[device.temp_sensor] +support_status = { status = "not_supported", issue = 5153 } + [device.ulp_riscv] support_status = { status = "not_supported", issue = 5160 } [device.lp_timer] support_status = { status = "not_supported", issue = 5162 } - -[device.temp_sensor] -support_status = { status = "not_supported", issue = 5153 } \ No newline at end of file From b2a39d0aec1bd91c94ef402c6b7650dbba09a5a0 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 12:05:29 -0600 Subject: [PATCH 22/37] Fix typo in MCPWM capabilities comment --- esp-metadata/devices/esp32h2.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index 93626938f1b..25620c8f028 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -17,7 +17,7 @@ symbols = [ "phy", "swd", - # MCPWM capabilites + # MCPWM capabilities "soc_has_mcpwm_swsync_can_propagate", "soc_has_mcpwm_capture_clk_from_group", "soc_has_mcpwm_support_etm", @@ -672,4 +672,4 @@ controller = "npl" [device.ieee802154] -[device.phy] \ No newline at end of file +[device.phy] From d6d474b48854e26802fb898c0aecd4c6ec478ba0 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 12:18:02 -0600 Subject: [PATCH 23/37] Update order of device.temp_sensor --- esp-metadata/devices/esp32c5.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp-metadata/devices/esp32c5.toml b/esp-metadata/devices/esp32c5.toml index c23da1e2e03..65d61ed566a 100644 --- a/esp-metadata/devices/esp32c5.toml +++ b/esp-metadata/devices/esp32c5.toml @@ -713,11 +713,11 @@ support_status = { status = "not_supported", issue = 5172 } [device.sd_slave] support_status = { status = "not_supported", issue = 5169 } -[device.temp_sensor] -support_status = { status = "not_supported", issue = 5153 } - [device.ulp_riscv] support_status = { status = "not_supported", issue = 5160 } [device.lp_timer] support_status = { status = "not_supported", issue = 5162 } + +[device.temp_sensor] +support_status = { status = "not_supported", issue = 5153 } From acf6119b3d1d1f1d98d30405fbd4888a48e7c0ee Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 13:59:48 -0600 Subject: [PATCH 24/37] Fixed typos, updated docs, fixed BlockGuard. --- esp-hal/CHANGELOG.md | 5 +++ esp-hal/Cargo.toml | 35 +++++++---------- esp-hal/MIGRATING-1.0.0.md | 17 +++++++++ esp-hal/src/mcpwm/capture.rs | 2 +- esp-hal/src/mcpwm/mod.rs | 38 ++++++++++++------- esp-hal/src/mcpwm/sync.rs | 11 ++++-- esp-hal/src/mcpwm/timer.rs | 26 ++++++------- .../src/_build_script_utils.rs | 4 +- 8 files changed, 82 insertions(+), 56 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 8f3c4943d2f..a1baedd517b 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -60,6 +60,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Cache configuration options for ESP32-S2 (#5306) - C5: Add PSRAM support (#5317) - C61: Add PSRAM support (#5325) +- MCPWM: Add external sync line and timer sync out support. (#5344) +- MCPWM: Add capture channel and timer support. (#5344) +- MCPWM: Added `esp_hal::mcpwm::timer::Timer::set_config` to apply a config to a timer. (#5344) ### Changed @@ -101,6 +104,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `esp_hal::efuse::chip_revision` has been marked stable (#5287) - `esp_hal::efuse::chip_revision` now returns `ChipRevision` (#5287) - DMA buffers can now be created using empty buffer slices (#5266) +- MCPWM: `esp_hal::mcpwm::timer::Timer::start` is now parameterless. Instead, use `esp_hal::mcpwm::timer::Timer::set_config` to apply a config to a timer. (#5344) +- MCPWM: timers default to the config given by `esp_hal::mcpwm::timer::TimerClockConfig::default`. (#5344) ### Fixed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index daba24ad469..30a6956cf35 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -102,15 +102,18 @@ ufmt-write = { version = "0.1", optional = true } # IMPORTANT: # Each supported device MUST have its PAC included below along with a # corresponding feature. -esp32 = { version = "0.39", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } -esp32c2 = { version = "0.28", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } -esp32c3 = { version = "0.31", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } -esp32c5 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } -esp32c6 = { version = "0.22", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } -esp32c61 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } -esp32h2 = { version = "0.18", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } -esp32s2 = { version = "0.30", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } -esp32s3 = { version = "0.34", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "879efa6" } + +## Once (#415) pull request is accepted update the commit hash to +## point to the latest commit on the main branch of esp-pacs +esp32 = { version = "0.39", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32c2 = { version = "0.28", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32c3 = { version = "0.31", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32c5 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32c6 = { version = "0.22", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32c61 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32h2 = { version = "0.18", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32s2 = { version = "0.30", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32s3 = { version = "0.34", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { version = "0.15.0" } @@ -334,16 +337,4 @@ requires-unstable = [] mixed_attributes_style = "allow" [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(host_os, values("windows"))'] } - -## Temp patch till esp-pacs-mcpwm pull request is accepted. -[patch."https://github.com/esp-rs/esp-pacs"] -esp32 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } -esp32c2 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } -esp32c3 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } -esp32c5 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } -esp32c6 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } -esp32c61 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } -esp32h2 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } -esp32s2 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } -esp32s3 = { git = "https://github.com/Alex3404/esp-pacs-mcpwm", rev = "a0e6861" } \ No newline at end of file +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(host_os, values("windows"))'] } \ No newline at end of file diff --git a/esp-hal/MIGRATING-1.0.0.md b/esp-hal/MIGRATING-1.0.0.md index 5ff29f9fdce..1d5a8601737 100644 --- a/esp-hal/MIGRATING-1.0.0.md +++ b/esp-hal/MIGRATING-1.0.0.md @@ -179,3 +179,20 @@ expensive. -let revision = chip_revision(); +let revision = chip_revision().combined(); ``` + +## MCPWM changes +- The `Timer::start` method is now parameterless and doesn't take in a `TimerClockConfig`. +- `Timer::start` starts with the configured `StopCondition` rather than being restricted to +running till `Timer::stop` is called. +- Instead, use `Timer::set_config` method to set the config for the `mcpwm::Timer`. +- Timers now have a default configuration when you create a MCPWM instance via `McPwm::new`. + +`TimerClockConfig` created by `timer_clock_with_frequency` and `timer_clock_with_prescaler` +will still default to `StopCondition::RunContinuously`. So, any existing code will only need +a simple change. + +```diff +-mcpwm.timer0.start(timer_clock_cfg); ++mcpwm.timer0.set_config(timer_clock_cfg); ++mcpwm.timer0.start(); +``` \ No newline at end of file diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 9e4e68dab44..73bf00ed368 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -13,7 +13,7 @@ //! //! ### Capture events can be triggered in 2 ways: //! 1. During a falling and/or Rising edge of a preconfigured GPIO pin. -//! 2. Software triggered captures though [`CaptureChannel::trigger_capture`]. +//! 2. Software triggered captures through [`CaptureChannel::trigger_capture`]. //! //! ### Configuration //! This module provides the flexibility of configuring any GPIO pin as an input diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index db32ea1e635..7e08abd9140 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -25,7 +25,6 @@ //! - Generate Space Vector PWM (SVPWM) signals for Field Oriented Control (FOC) //! //! ## Configuration -//! //! * PWM Timers 0, 1 and 2 //! * Every PWM timer has a dedicated 8-bit clock prescaler. //! * The 16-bit counter in the PWM timer can work in count-up mode, count-down mode or @@ -44,15 +43,13 @@ //! * Configurable dead-time on rising and falling edges; each set up independently. (Not yet //! implemented) //! * All events can trigger CPU interrupts. (Not yet implemented) -//! * Modulating of PWM output by high-frequency carrier signals, useful when gate drivers are -//! insulated with a transformer. (Not yet implemented) //! * Period, time stamps and important control registers have shadow registers with flexible //! updating methods. //! * Capture Channels 0, 1 and 2 //! * Every capture channel has one signal input. With an optional invert filter //! * Each capture module can be configured to detect rising and (or), falling edges on an //! external signal. -//! * Each capture channel can trigger software capture event recoding the capture counter. The +//! * Each capture channel can trigger software capture event recording the capture counter. The //! edge that is captured is UNSPECIFIED for software captures. //! * Each capture channel can be configured with a 8-bit pre-scaler. Which only triggers //! capture events every Nth edge captured. ( Useful for high frequencies ) @@ -66,14 +63,14 @@ )] #![cfg_attr( not(soc_has_mcpwm_capture_clk_from_group), - doc = " * Capture timer's has it's own independent clock source from the MCPWM peripheral." + doc = " * Capture timer has its own independent clock source from the MCPWM peripheral." )] //! * Fault Detection Module (Not yet implemented) #![cfg_attr( not(soc_has_mcpwm_capture_clk_from_group), doc = "\nCapture clock source is `ADB-CLK (80 MHz)` by default.\n" )] -//! Clock source is `__clock_src__`` by default. +//! Clock source is `__clock_src__` by default. //! //! ## Examples //! @@ -104,7 +101,9 @@ //! // of 20 kHz //! let timer_clock_cfg = clock_cfg //! .timer_clock_with_frequency(99, PwmWorkingMode::Increase, -//! Rate::from_khz(20))?; mcpwm.timer0.start(timer_clock_cfg); +//! Rate::from_khz(20))?; +//! mcpwm.timer0.set_config(timer_clock_cfg); +//! mcpwm.timer0.start(); //! //! // pin will be high 50% of the time //! pwm_pin.set_timestamp(50); @@ -385,6 +384,19 @@ impl PeripheralClockConfig { ) -> Result { timer::TimerClockConfig::with_frequency(self, period, mode, target_freq) } + + /// Get a timer clock configuration with the default values. + /// + /// ### Note: + /// - Prescaler defaults to the minimum value of `0`. + /// - Period defaults to the maximum value of `u16::MAX`. + /// - PWM working mode defaults to `PwmWorkingMode::Increase`. + /// + /// The frequency is calculated with the formula described in + /// [`PeripheralClockConfig::timer_clock_with_prescaler`] with the default prescaler value. + pub fn timer_clock_default(&self) -> timer::TimerClockConfig { + timer::TimerClockConfig::default(self) + } } /// Target frequency could not be set. @@ -494,15 +506,13 @@ impl State { let int_ena = self.int_ena.borrow(cs); let regs = info.regs(); - int_ena.set(regs.int_ena().write(|w| { - unsafe { w.bits(int_ena.take()) }; - + let new_int_ena = regs.int_ena().modify(|_, w| { for event in events { dispatch_event_write!(w, event, UNIT, value); } - w - })); + }); + int_ena.set(new_int_ena); }); } } @@ -660,7 +670,7 @@ impl Instance for crate::peripherals::MCPWM1<'_> { } #[allow(dead_code)] // Field is seemingly unused but we rely on its Drop impl -struct PwmClockGuard(DropGuard); +struct PwmClockGuard(DropGuard<(), fn(())>); impl PwmClockGuard { fn instance() -> clocks::McpwmInstance { @@ -676,7 +686,7 @@ impl PwmClockGuard { pub fn new() -> Self { ClockTree::with(move |clocks| Self::instance::().request_function_clock(clocks)); - Self(DropGuard::new(|| { + Self(DropGuard::new((), |_| { ClockTree::with(move |clocks| Self::instance::().release_function_clock(clocks)); })) } diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index c4008bf824e..413349cdf69 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -9,7 +9,7 @@ //! ## Overview //! The `Sync` is responsible for managing the different ways //! MCPWM can listen to sync events. There are 2 different types of -//! sync sources. One is a [`SyncOut`] that comes from [`super::Timer::get_sync_out`], +//! sync sources. One is a [`SyncOut`] that comes from [`super::Timer::sync_out`], //! or from a [`SyncLine`]. //! //! This module provides the flexibility to map any of the @@ -20,11 +20,14 @@ //! ### Configuring a SyncLine signal //! For configuring a [`SyncLine`] input signal, and then connecting //! it to timer 0's sync in event. This is useful when you need to sync -//! the timers phase from an external signal such as a zero-cross event -//! for 3 phase PWM. +//! the timers phase from an external signal, such as a zero-cross event +//! for 3-phase PWM. //! //! ```rust, no_run -//! use esp_hal::mcpwm::{McPwm, PeripheralClockConfig}; +//! use esp_hal::{ +//! mcpwm::{McPwm, PeripheralClockConfig}, +//! time::Rate, +//! }; //! //! // initialize peripheral //! let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(__mcpwm_freq__))?; diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 6d031f983fb..a37c847b52a 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -52,12 +52,12 @@ pub enum TimerEvent { TimerEqualPeriod, } -impl Into for TimerEvent { - fn into(self) -> Event { - match self { - TimerEvent::TimerEqualPeriod => Event::TimerEqualPeriod, - TimerEvent::TimerEqualZero => Event::TimerEqualZero, +impl From for Event { + fn from(value: TimerEvent) -> Self { + match value { TimerEvent::TimerStop => Event::TimerStop, + TimerEvent::TimerEqualZero => Event::TimerEqualZero, + TimerEvent::TimerEqualPeriod => Event::TimerEqualPeriod, } } } @@ -79,12 +79,7 @@ pub struct Timer<'d, const TIM: u8, PWM: Instance> { impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { pub(super) fn new(guard: PeripheralGuard, peripheral_clock: &PeripheralClockConfig) -> Self { // Default configuration for the timer - let config = TimerClockConfig::with_prescaler( - peripheral_clock, - u16::MAX, - PwmWorkingMode::Increase, - 0, - ); + let config = TimerClockConfig::default(peripheral_clock); let mut timer = Timer { sync_out: SyncOut::new(), @@ -135,7 +130,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// ## Overview /// Internally we set the timers phase and direction /// Then trigger a software sync event. - #[cfg_attr(soc_has_mcpwm_swsync_can_propagate, doc(hidden))] + #[cfg_attr(docsrs, doc(cfg(soc_has_mcpwm_swsync_can_propagate)))] /// **Note** This will cause the timer to fire a sync out event to other timers pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { self.set_sync_phase(phase); @@ -144,7 +139,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } /// Trigger a software sync event - #[cfg_attr(soc_has_mcpwm_swsync_can_propagate, doc(hidden))] + #[cfg_attr(docsrs, doc(cfg(soc_has_mcpwm_swsync_can_propagate)))] /// **Note** This will cause the timer to fire a sync out event to other timers pub fn trigger_sync(&mut self) { // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const @@ -403,6 +398,11 @@ impl TimerClockConfig { }) } + /// Default configuration for the timer with the provided clock configuration + pub(super) fn default(clock: &PeripheralClockConfig) -> Self { + Self::with_prescaler(clock, u16::MAX, PwmWorkingMode::Increase, 0) + } + /// Set the method for updating the PWM period pub fn with_period_updating_method(self, method: PeriodUpdatingMethod) -> Self { Self { diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index de3826da8e0..514860f1b6a 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -4698,10 +4698,10 @@ impl Chip { "phy", "swd", "ulp_riscv_core", - "soc_has_mcpwm_swsync_can_propagate", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", + "soc_has_mcpwm_swsync_can_propagate", "pm_support_ext0_wakeup", "pm_support_ext1_wakeup", "pm_support_touch_sensor_wakeup", @@ -4946,10 +4946,10 @@ impl Chip { "cargo:rustc-cfg=phy", "cargo:rustc-cfg=swd", "cargo:rustc-cfg=ulp_riscv_core", - "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", + "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", "cargo:rustc-cfg=pm_support_ext0_wakeup", "cargo:rustc-cfg=pm_support_ext1_wakeup", "cargo:rustc-cfg=pm_support_touch_sensor_wakeup", From 3d3075307bb16482f25cb9f03e6ba18f89c3bf53 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 14:05:29 -0600 Subject: [PATCH 25/37] Remove unexpected_cfgs lint configuration --- esp-hal/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 30a6956cf35..0b2a7ff3e0e 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -337,4 +337,3 @@ requires-unstable = [] mixed_attributes_style = "allow" [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(host_os, values("windows"))'] } \ No newline at end of file From b8abff4518b832486a565dcdde75ed1bd69483fa Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 14:06:08 -0600 Subject: [PATCH 26/37] Add warning for unexpected_cfgs lint in Cargo.toml --- esp-hal/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 0b2a7ff3e0e..34e37264130 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -337,3 +337,4 @@ requires-unstable = [] mixed_attributes_style = "allow" [lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(host_os, values("windows"))'] } From 2b9cfd943be153fe6802fdbf485d31b735657efb Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 14:09:55 -0600 Subject: [PATCH 27/37] Update MCPWM Timer method descriptions Clarified MCPWM changes regarding Timer methods and configurations. --- esp-hal/MIGRATING-1.0.0.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp-hal/MIGRATING-1.0.0.md b/esp-hal/MIGRATING-1.0.0.md index 1d5a8601737..b9d6640e16c 100644 --- a/esp-hal/MIGRATING-1.0.0.md +++ b/esp-hal/MIGRATING-1.0.0.md @@ -182,9 +182,9 @@ expensive. ## MCPWM changes - The `Timer::start` method is now parameterless and doesn't take in a `TimerClockConfig`. + Instead, use `Timer::set_config` method to set the config for the `mcpwm::Timer`. - `Timer::start` starts with the configured `StopCondition` rather than being restricted to -running till `Timer::stop` is called. -- Instead, use `Timer::set_config` method to set the config for the `mcpwm::Timer`. + running till `Timer::stop` is called. - Timers now have a default configuration when you create a MCPWM instance via `McPwm::new`. `TimerClockConfig` created by `timer_clock_with_frequency` and `timer_clock_with_prescaler` @@ -195,4 +195,4 @@ a simple change. -mcpwm.timer0.start(timer_clock_cfg); +mcpwm.timer0.set_config(timer_clock_cfg); +mcpwm.timer0.start(); -``` \ No newline at end of file +``` From 51ffc327410ed2f22dde7cbc800f0edb06085cc5 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 14:11:11 -0600 Subject: [PATCH 28/37] Updated doc for timer --- esp-hal/src/mcpwm/timer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index a37c847b52a..deb0d1066f3 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -118,7 +118,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// If the timer is already running you might want to call [`Timer::stop`] first. /// /// If your [`PeriodUpdatingMethod`] is set to [`PeriodUpdatingMethod::Immediately`] - /// and if your new period is larger than the current counter value as this will cause weird + /// and if your new period is smaller than the current counter value as this will cause weird /// behavior. pub fn set_config(&mut self, config: TimerClockConfig) { self.config = config; From c8f3da75f6686bc19659435fbba592d3c7dd9d6a Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 15:22:46 -0600 Subject: [PATCH 29/37] Removed PWM::State Keeping the int_ena state in a variable is not needed as modify is much better suited. --- esp-hal/src/mcpwm/capture.rs | 26 ++++----- esp-hal/src/mcpwm/mod.rs | 100 +++++++++++++--------------------- esp-hal/src/mcpwm/operator.rs | 10 ++-- esp-hal/src/mcpwm/sync.rs | 4 +- esp-hal/src/mcpwm/timer.rs | 12 ++-- 5 files changed, 64 insertions(+), 88 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 73bf00ed368..48255714c30 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -200,12 +200,12 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { } fn cfg() -> &'static crate::Reg { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs().cap_timer_cfg() } fn phase() -> &'static crate::Reg { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs().cap_timer_phase() } } @@ -323,7 +323,7 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// Assign the input signal for the capture pub fn with_signal_input<'a>(self, input: impl PeripheralInput<'a>) -> Self { - let (info, _) = PWM::split(); + let info = PWM::info(); let input_signal = info.capture_input_signal::(); if input_signal as usize <= property!("gpio.input_signal_max") { @@ -356,42 +356,42 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// This channel can listen to Falling, and/or Rising edges on any of the GPIO pins. #[instability::unstable] pub fn listen(&mut self) { - let (info, state) = PWM::split(); - state.enable_listen::(info, EnumSet::only(Event::Capture), true); + let info = PWM::info(); + info.enable_listen::(EnumSet::only(Event::Capture), true); } /// Stops listening to events on this channel #[instability::unstable] pub fn unlisten(&mut self) { - let (info, state) = PWM::split(); - state.enable_listen::(info, EnumSet::only(Event::Capture), false); + let info = PWM::info(); + info.enable_listen::(EnumSet::only(Event::Capture), false); } /// If the interrupt was set for this channel #[instability::unstable] pub fn is_interrupt_set(&self) -> bool { - let (info, state) = PWM::split(); - state.interrupt_set::(info, Event::Capture) + let info = PWM::info(); + info.interrupt_set::(Event::Capture) } /// Clear the interrupt #[instability::unstable] pub fn clear_interrupt(&self) { - let (info, state) = PWM::split(); - state.clear_interrupt::(info, Event::Capture); + let info = PWM::info(); + info.clear_interrupt::(Event::Capture); } /// Gets the last captured event #[instability::unstable] pub fn events(&self) -> CaptureEvent { - let (info, _) = PWM::split(); + let info = PWM::info(); let time = info.regs().cap_ch(CHAN as usize).read().value().bits(); let edge = info.regs().cap_status().read().cap_edge(CHAN).variant(); CaptureEvent { time, edge } } fn cfg() -> &'static crate::Reg { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs().cap_ch_cfg(CHAN as usize) } } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index 7e08abd9140..d829f6d984b 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -110,9 +110,8 @@ //! # {after_snippet} //! ``` -use core::{cell::Cell, marker::PhantomData}; +use core::marker::PhantomData; -use critical_section::Mutex; use enumset::{EnumSet, EnumSetType}; #[cfg(soc_has_mcpwm0)] @@ -235,7 +234,7 @@ pub struct McPwm<'d, PWM: Instance> { impl<'d, PWM: Instance> McPwm<'d, PWM> { /// Create a new instance generics pub fn new(_peripheral: PWM, peripheral_clock: PeripheralClockConfig) -> Self { - let (info, _) = PWM::split(); + let info = PWM::info(); let guard = PeripheralGuard::new(info.peripheral()); // set prescaler for timer (0-2) @@ -270,7 +269,7 @@ impl<'d, PWM: Instance> McPwm<'d, PWM> { /// handlers. #[instability::unstable] pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { - let (info, _) = PWM::split(); + let info = PWM::info(); let interrupt = info.interrupt(); for core in crate::system::Cpu::other() { @@ -437,16 +436,6 @@ pub struct Info { operator_b_output: [OutputSignal; 3], } -/// Peripheral state for an MCPWM instance. -#[doc(hidden)] -#[derive(Debug)] -#[non_exhaustive] -pub struct State { - int_ena: Mutex>, -} - -unsafe impl Sync for State {} - /// Dispatches event to register bit getter for interrupt status checks macro_rules! dispatch_event_bit { ($int_register:expr, $event:expr, $unit:expr) => { @@ -483,40 +472,6 @@ macro_rules! dispatch_event_write { }; } -impl State { - /// Return if the interrupt for an event is set - pub fn interrupt_set(&self, info: &Info, event: Event) -> bool { - let regs = info.regs(); - let int_st = regs.int_st().read(); - dispatch_event_bit!(int_st, event, UNIT) - } - - /// Clear the interrupt for an event on a specific UNIT # - pub fn clear_interrupt(&self, info: &Info, event: Event) { - let regs = info.regs(); - regs.int_clr().write(|w| { - dispatch_event_write!(w, event, UNIT, true); - w - }); - } - - /// Enables listening for an event on a specific UNIT # - pub fn enable_listen(&self, info: &Info, events: EnumSet, value: bool) { - critical_section::with(|cs| { - let int_ena = self.int_ena.borrow(cs); - let regs = info.regs(); - - let new_int_ena = regs.int_ena().modify(|_, w| { - for event in events { - dispatch_event_write!(w, event, UNIT, value); - } - w - }); - int_ena.set(new_int_ena); - }); - } -} - /// Event types for MCPWM #[derive(Debug, EnumSetType)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -577,6 +532,35 @@ impl Info { pub fn capture_input_signal(&self) -> InputSignal { self.capture_input[CHAN as usize] } + + /// Return if the interrupt for an event is set + pub fn interrupt_set(&self, event: Event) -> bool { + let regs = self.regs(); + let int_st = regs.int_st().read(); + dispatch_event_bit!(int_st, event, UNIT) + } + + /// Clear the interrupt for an event on a specific UNIT # + pub fn clear_interrupt(&self, event: Event) { + let regs = self.regs(); + regs.int_clr().write(|w| { + dispatch_event_write!(w, event, UNIT, true); + w + }); + } + + /// Enables listening for an event on a specific UNIT # + pub fn enable_listen(&self, events: EnumSet, value: bool) { + let regs = self.regs(); + critical_section::with(|_| { + regs.int_ena().modify(|r, w| { + for event in events { + dispatch_event_write!(w, event, UNIT, value); + } + w + }); + }); + } } impl PartialEq for Info { @@ -591,13 +575,13 @@ unsafe impl Sync for Info {} pub trait Instance: crate::private::Sealed { #[doc(hidden)] /// Returns the peripheral data and state. - fn split() -> (&'static Info, &'static State); + fn info() -> &'static Info; } #[cfg(soc_has_mcpwm0)] impl Instance for crate::peripherals::MCPWM0<'_> { /// Returns peripheral data for MCPWM 0 - fn split() -> (&'static Info, &'static State) { + fn info() -> &'static Info { static INFO: Info = Info { register_block: crate::peripherals::MCPWM0::regs(), _peripheral: crate::system::Peripheral::Mcpwm0, @@ -624,17 +608,13 @@ impl Instance for crate::peripherals::MCPWM0<'_> { ], }; - static STATE: State = State { - int_ena: Mutex::new(Cell::new(0)), - }; - - (&INFO, &STATE) + &INFO } } #[cfg(soc_has_mcpwm1)] impl Instance for crate::peripherals::MCPWM1<'_> { - fn split() -> (&'static Info, &'static State) { + fn info() -> &'static Info { static INFO: Info = Info { register_block: crate::peripherals::MCPWM1::regs(), _peripheral: crate::system::Peripheral::Mcpwm1, @@ -661,11 +641,7 @@ impl Instance for crate::peripherals::MCPWM1<'_> { ], }; - static STATE: State = State { - int_ena: Mutex::new(Cell::new(0)), - }; - - (&INFO, &STATE) + &INFO } } @@ -674,7 +650,7 @@ struct PwmClockGuard(DropGuard<(), fn(())>); impl PwmClockGuard { fn instance() -> clocks::McpwmInstance { - let (info, _) = PWM::split(); + let info = PWM::info(); match info.peripheral() { Peripheral::Mcpwm0 => clocks::McpwmInstance::Mcpwm0, #[cfg(soc_has_mcpwm1)] diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 83ccc217df6..41e167a80f3 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -245,7 +245,7 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { /// Unsafe access to the OPERATORx_TIMERSEL register /// Caller must ensure they only write to the bits corresponding to their operator unsafe fn timesel() -> &'static pac::mcpwm0::OPERATOR_TIMERSEL { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs().operator_timersel() } } @@ -291,7 +291,7 @@ pub struct PwmPin<'d, PWM: Instance, const OP: u8, const IS_A: bool> { impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A> { fn new(pin: impl PeripheralOutput<'d>, config: PwmPinConfig) -> Self { let pin = pin.into(); - let (info, _) = PWM::split(); + let info = PWM::info(); let guard = PeripheralGuard::new(info.peripheral()); let mut pin = PwmPin { @@ -392,7 +392,7 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A pub fn period(&self) -> u16 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self - let (info, _) = PWM::split(); + let info = PWM::info(); let tim_select = info.regs().operator_timersel().read(); let tim = match OP { @@ -416,7 +416,7 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A } unsafe fn ch() -> &'static pac::mcpwm0::CH { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs().ch(OP as usize) } } @@ -574,7 +574,7 @@ impl<'d, PWM: Instance, const OP: u8> LinkedPins<'d, PWM, OP> { } unsafe fn ch() -> &'static pac::mcpwm0::CH { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs().ch(OP as usize) } } diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index 413349cdf69..f62f2ed6b83 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -98,7 +98,7 @@ impl<'d, const SYNC: u8, PWM: Instance> SyncLine<'d, SYNC, PWM> { /// Set the input signal for the sync line pub fn set_signal(&mut self, source: impl PeripheralInput<'d>) { // configure GPIO matrix → SYNC - let (info, _) = PWM::split(); + let info = PWM::info(); let signal = info.sync_input_signal::(); if signal as usize <= property!("gpio.input_signal_max") { @@ -114,7 +114,7 @@ impl<'d, const SYNC: u8, PWM: Instance> SyncLine<'d, SYNC, PWM> { /// If invert is true sync events are triggered on falling edges. /// If invert is false sync events are triggered on rising edges. pub fn set_invert(&mut self, invert: bool) { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs() .timer_synci_cfg() .modify(|_, w| w.external_synci_invert(SYNC).variant(invert)); diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index deb0d1066f3..4d4987b14db 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -179,7 +179,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { #[instability::unstable] pub fn interrupts(&self) -> EnumSet { let mut res = EnumSet::new(); - let (info, _) = PWM::split(); + let info = PWM::info(); let ints = info.regs().int_st().read(); if ints.timer_stop(TIM).bit() { @@ -197,7 +197,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { #[instability::unstable] pub fn clear_interrupts(&mut self, events: EnumSet) { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs().int_clr().write(|w| { for event in events { match event { @@ -260,7 +260,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } fn set_sync_in_select(&mut self, sync_sel: SyncInSelect) { - let (info, _) = PWM::split(); + let info = PWM::info(); // SAFETY: Only TIMER_SYNCI_CFG and TIMERx_SYNC accessed info.regs() @@ -271,13 +271,13 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } fn enable_listen(&mut self, events: EnumSet, value: bool) { - let (info, state) = PWM::split(); + let info = PWM::info(); let mut int_events = EnumSet::new(); for timer_event in events { int_events.insert(timer_event.into()); } - state.enable_listen::(info, int_events, value); + info.enable_listen::(int_events, value); } fn cfg0(&mut self) -> &pac::mcpwm0::timer::CFG0 { @@ -298,7 +298,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { // Marked unsafe as the caller must ensure that only one timer // is accessing the registers for a given TIM const unsafe fn tmr() -> &'static pac::mcpwm0::TIMER { - let (info, _) = PWM::split(); + let info = PWM::info(); info.regs().timer(TIM as usize) } } From 2a5c92dca5701ac6a84b80487437fae932c69d78 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:07:51 -0600 Subject: [PATCH 30/37] Update cargo.toml, and docs --- esp-hal/CHANGELOG.md | 2 +- esp-hal/Cargo.toml | 18 +++++++++--------- esp-hal/src/mcpwm/capture.rs | 4 ++-- esp-hal/src/mcpwm/mod.rs | 4 +++- esp-hal/src/mcpwm/timer.rs | 18 ++++++++++++------ 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index a1baedd517b..5c9d8bcf059 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -105,7 +105,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `esp_hal::efuse::chip_revision` now returns `ChipRevision` (#5287) - DMA buffers can now be created using empty buffer slices (#5266) - MCPWM: `esp_hal::mcpwm::timer::Timer::start` is now parameterless. Instead, use `esp_hal::mcpwm::timer::Timer::set_config` to apply a config to a timer. (#5344) -- MCPWM: timers default to the config given by `esp_hal::mcpwm::timer::TimerClockConfig::default`. (#5344) +- MCPWM: timers default to the config given by `PeripheralClockConfig::timer_clock_default()`. (#5344) ### Fixed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 34e37264130..39550c7bb6c 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -105,15 +105,15 @@ ufmt-write = { version = "0.1", optional = true } ## Once (#415) pull request is accepted update the commit hash to ## point to the latest commit on the main branch of esp-pacs -esp32 = { version = "0.39", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } -esp32c2 = { version = "0.28", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } -esp32c3 = { version = "0.31", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } -esp32c5 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } -esp32c6 = { version = "0.22", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } -esp32c61 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } -esp32h2 = { version = "0.18", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } -esp32s2 = { version = "0.30", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } -esp32s3 = { version = "0.34", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "refs/pull/415/head" } +esp32 = { version = "0.39", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32c2 = { version = "0.28", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32c3 = { version = "0.31", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32c5 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32c6 = { version = "0.22", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32c61 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32h2 = { version = "0.18", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32s2 = { version = "0.30", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32s3 = { version = "0.34", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { version = "0.15.0" } diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 48255714c30..7970c36e284 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -126,7 +126,7 @@ impl Default for CaptureTimerConfig { /// When this timer receives a sync event the counter of the timer is reset /// to the phase value set in [`CaptureTimerConfig`]. /// -/// **Note:** This timer always counts up towards a the positive direction. +/// **Note:** This timer always counts up. pub struct CaptureTimer<'d, PWM: Instance> { phantom: PhantomData<&'d PWM>, _guard: PeripheralGuard, @@ -142,7 +142,7 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { } } - /// Start the capture timer to being counting and capturing events + /// Start the capture timer pub fn start(&mut self) { self.set_enable(true); } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index d829f6d984b..f66d0dc9af7 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -31,7 +31,7 @@ //! count-up-down mode. //! * A hardware sync or software sync can trigger a reload on the PWM timer with a phase //! register. -//! * Timers run until a perconfigured [`timer::StopCondition`], this enum also specifies +//! * Timers run until a preconfigured [`timer::StopCondition`], this enum also specifies //! running continuously. //! * Timers can generate [`timer::TimerEvent`] during specific conditions. //! * Timers [`sync::SyncOut`] can be configured to fire at specific conditions configured by @@ -199,6 +199,7 @@ pub mod mcpwm1 { #[non_exhaustive] pub struct McPwm<'d, PWM: Instance> { _phantom: PhantomData<&'d PWM>, + _instance: PWM, /// Timer0 pub timer0: Timer<'d, 0, PWM>, @@ -247,6 +248,7 @@ impl<'d, PWM: Instance> McPwm<'d, PWM> { Self { _phantom: PhantomData, + _instance: _peripheral, timer0: Timer::new(guard.clone(), &peripheral_clock), timer1: Timer::new(guard.clone(), &peripheral_clock), timer2: Timer::new(guard.clone(), &peripheral_clock), diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 4d4987b14db..4faefc44527 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -130,8 +130,11 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// ## Overview /// Internally we set the timers phase and direction /// Then trigger a software sync event. - #[cfg_attr(docsrs, doc(cfg(soc_has_mcpwm_swsync_can_propagate)))] - /// **Note** This will cause the timer to fire a sync out event to other timers + #[cfg_attr( + docsrs, + doc(cfg(soc_has_mcpwm_swsync_can_propagate)), + doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." + )] pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { self.set_sync_phase(phase); self.set_sync_counter_direction(direction); @@ -139,8 +142,11 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { } /// Trigger a software sync event - #[cfg_attr(docsrs, doc(cfg(soc_has_mcpwm_swsync_can_propagate)))] - /// **Note** This will cause the timer to fire a sync out event to other timers + #[cfg_attr( + docsrs, + doc(cfg(soc_has_mcpwm_swsync_can_propagate)), + doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." + )] pub fn trigger_sync(&mut self) { // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const let tmr = unsafe { Self::tmr() }; @@ -154,7 +160,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { (reg.value().bits(), reg.direction().bit_is_set().into()) } - /// Sets the capture timers sync source. Refer to how sync events are + /// Sets the timers sync source. Refer to how sync events are /// handled in the [`Timer`] documentation. pub fn set_sync_in(&mut self, sync_source: &impl SyncSource) { let sync_in_sel = sync_source.get_kind().into(); @@ -412,7 +418,7 @@ impl TimerClockConfig { } /// Sets the stop timer conditions - pub fn with_stop_conditions(self, condition: StopCondition) -> Self { + pub fn with_stop_condition(self, condition: StopCondition) -> Self { Self { stop_condition: condition, ..self From 6a538074dae2f88ab63f7b880b78c29dc6daa64d Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:08:15 -0600 Subject: [PATCH 31/37] Added device.mcpwm configurations to esp-metadata Added the specific supported configs for mcpwm, as well as added for_each_mcpwm macro for the Instance, and public api --- esp-hal/src/mcpwm/mod.rs | 198 +++++++----------- esp-hal/src/mcpwm/timer.rs | 8 +- .../src/_build_script_utils.rs | 83 +++++--- .../src/_generated_esp32.rs | 40 ++++ .../src/_generated_esp32c5.rs | 39 ++++ .../src/_generated_esp32c6.rs | 40 ++++ .../src/_generated_esp32h2.rs | 40 ++++ .../src/_generated_esp32s3.rs | 40 ++++ esp-metadata/devices/esp32.toml | 8 +- esp-metadata/devices/esp32c5.toml | 13 +- esp-metadata/devices/esp32c6.toml | 17 +- esp-metadata/devices/esp32h2.toml | 17 +- esp-metadata/devices/esp32s3.toml | 11 +- esp-metadata/src/cfg.rs | 17 +- esp-metadata/src/cfg/mcpwm.rs | 57 +++++ esp-metadata/src/lib.rs | 3 + 16 files changed, 445 insertions(+), 186 deletions(-) create mode 100644 esp-metadata/src/cfg/mcpwm.rs diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index f66d0dc9af7..50a0a6145b7 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -58,16 +58,16 @@ //! * A hardware sync or software sync can trigger a reload on the capture timer with the set //! phase. #![cfg_attr( - soc_has_mcpwm_capture_clk_from_group, + mcpwm_capture_clk_from_group, doc = " * Capture timer's clock source is the same as the PWM timers clock source" )] #![cfg_attr( - not(soc_has_mcpwm_capture_clk_from_group), + not(mcpwm_capture_clk_from_group), doc = " * Capture timer has its own independent clock source from the MCPWM peripheral." )] //! * Fault Detection Module (Not yet implemented) #![cfg_attr( - not(soc_has_mcpwm_capture_clk_from_group), + not(mcpwm_capture_clk_from_group), doc = "\nCapture clock source is `ADB-CLK (80 MHz)` by default.\n" )] //! Clock source is `__clock_src__` by default. @@ -113,6 +113,7 @@ use core::marker::PhantomData; use enumset::{EnumSet, EnumSetType}; +use paste::paste; #[cfg(soc_has_mcpwm0)] use crate::mcpwm::{ @@ -140,60 +141,38 @@ pub mod sync; /// MCPWM timers pub mod timer; -/// Provides nice types for public API -#[cfg(soc_has_mcpwm0)] -pub mod mcpwm0 { - use crate::{mcpwm::*, peripherals::MCPWM0 as MCPWMPeripheral}; - - /// MCPWM Driver for MCPWM0 - pub type McPwm<'d> = super::McPwm<'d, MCPWMPeripheral<'d>>; - /// Capture channel creator for MCPWM0 - pub type CaptureChannelCreator<'d, const NUM: u8> = - capture::CaptureChannelCreator<'d, NUM, MCPWMPeripheral<'d>>; - /// Capture Channel for MCPWM0 - pub type CaptureChannel<'d, const NUM: u8> = - capture::CaptureChannel<'d, NUM, MCPWMPeripheral<'d>>; - /// Capture timer for MCPWM0 - pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPeripheral<'d>>; - /// Timer for MCPWM0 - pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPeripheral<'d>>; - /// Operator for MCPWM0 - pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPeripheral<'d>>; - /// Pwm Pin for MCPWM0 - pub type PwmPin<'d, const NUM: u8, const IS_A: bool> = - operator::PwmPin<'d, MCPWMPeripheral<'d>, NUM, IS_A>; - /// Linked Pins for MCPWM0 - pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPeripheral<'d>, NUM>; - /// Sync source for MCPWM0 - pub type SyncSource<'d> = dyn sync::SyncSource>; -} - -/// Provides nice types for public API -#[cfg(soc_has_mcpwm1)] -pub mod mcpwm1 { - use crate::{mcpwm::*, peripherals::MCPWM1 as MCPWMPeripheral}; - /// MCPWM Driver for MCPWM1 - pub type McPwm<'d> = super::McPwm<'d, MCPWMPeripheral<'d>>; - /// Capture channel creator for MCPWM1 - pub type CaptureChannelCreator<'d, const NUM: u8> = - capture::CaptureChannelCreator<'d, NUM, MCPWMPeripheral<'d>>; - /// Capture Channel for MCPWM1 - pub type CaptureChannel<'d, const NUM: u8> = - capture::CaptureChannel<'d, NUM, MCPWMPeripheral<'d>>; - /// Capture timer for MCPWM1 - pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPeripheral<'d>>; - /// Timer for MCPWM1 - pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPeripheral<'d>>; - /// Operator for MCPWM1 - pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPeripheral<'d>>; - /// Pwm Pin for MCPWM1 - pub type PwmPin<'d, const NUM: u8, const IS_A: bool> = - operator::PwmPin<'d, MCPWMPeripheral<'d>, NUM, IS_A>; - /// Linked Pins for MCPWM1 - pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPeripheral<'d>, NUM>; - /// Sync source for MCPWM1 - pub type SyncSource<'d> = dyn sync::SyncSource>; -} +for_each_mcpwm!( + ($id:literal, $inst:ident, $sys:ident) => { + paste! { + /// Provides nice types for public API + pub mod [<$inst:lower>] { + use crate::{mcpwm::*, peripherals::[<$inst>] as MCPWMPeripheral}; + + /// MCPWM Driver for MCPWM<$id> + pub type McPwm<'d> = super::McPwm<'d, MCPWMPeripheral<'d>>; + /// Capture channel creator for MCPWM<$id> + pub type CaptureChannelCreator<'d, const NUM: u8> = + capture::CaptureChannelCreator<'d, NUM, MCPWMPeripheral<'d>>; + /// Capture Channel for MCPWM<$id> + pub type CaptureChannel<'d, const NUM: u8> = + capture::CaptureChannel<'d, NUM, MCPWMPeripheral<'d>>; + /// Capture timer for MCPWM<$id> + pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPeripheral<'d>>; + /// Timer for MCPWM<$id> + pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPeripheral<'d>>; + /// Operator for MCPWM<$id> + pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPeripheral<'d>>; + /// Pwm Pin for MCPWM<$id> + pub type PwmPin<'d, const NUM: u8, const IS_A: bool> = + operator::PwmPin<'d, MCPWMPeripheral<'d>, NUM, IS_A>; + /// Linked Pins for MCPWM<$id> + pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPeripheral<'d>, NUM>; + /// Sync source for MCPWM<$id> + pub type SyncSource<'d> = dyn sync::SyncSource> + 'd; + } + } + }; +); /// The MCPWM peripheral #[non_exhaustive] @@ -555,7 +534,7 @@ impl Info { pub fn enable_listen(&self, events: EnumSet, value: bool) { let regs = self.regs(); critical_section::with(|_| { - regs.int_ena().modify(|r, w| { + regs.int_ena().modify(|_, w| { for event in events { dispatch_event_write!(w, event, UNIT, value); } @@ -580,72 +559,45 @@ pub trait Instance: crate::private::Sealed { fn info() -> &'static Info; } -#[cfg(soc_has_mcpwm0)] -impl Instance for crate::peripherals::MCPWM0<'_> { - /// Returns peripheral data for MCPWM 0 - fn info() -> &'static Info { - static INFO: Info = Info { - register_block: crate::peripherals::MCPWM0::regs(), - _peripheral: crate::system::Peripheral::Mcpwm0, - _interrupt: crate::peripherals::Interrupt::MCPWM0, - sync_input: [ - InputSignal::PWM0_SYNC0, - InputSignal::PWM0_SYNC1, - InputSignal::PWM0_SYNC2, - ], - capture_input: [ - InputSignal::PWM0_CAP0, - InputSignal::PWM0_CAP1, - InputSignal::PWM0_CAP2, - ], - operator_a_output: [ - OutputSignal::PWM0_0A, - OutputSignal::PWM0_1A, - OutputSignal::PWM0_2A, - ], - operator_b_output: [ - OutputSignal::PWM0_0B, - OutputSignal::PWM0_1B, - OutputSignal::PWM0_2B, - ], - }; - - &INFO - } -} - -#[cfg(soc_has_mcpwm1)] -impl Instance for crate::peripherals::MCPWM1<'_> { - fn info() -> &'static Info { - static INFO: Info = Info { - register_block: crate::peripherals::MCPWM1::regs(), - _peripheral: crate::system::Peripheral::Mcpwm1, - _interrupt: crate::peripherals::Interrupt::MCPWM1, - sync_input: [ - InputSignal::PWM1_SYNC0, - InputSignal::PWM1_SYNC1, - InputSignal::PWM1_SYNC2, - ], - capture_input: [ - InputSignal::PWM1_CAP0, - InputSignal::PWM1_CAP1, - InputSignal::PWM1_CAP2, - ], - operator_a_output: [ - OutputSignal::PWM1_0A, - OutputSignal::PWM1_1A, - OutputSignal::PWM1_2A, - ], - operator_b_output: [ - OutputSignal::PWM1_0B, - OutputSignal::PWM1_1B, - OutputSignal::PWM1_2B, - ], - }; - - &INFO +// Create an `Instance` impl for each MCPWM peripheral +for_each_mcpwm!( + ($id:literal, $inst:ident, $sys:ident) => { + paste::paste! { + impl Instance for crate::peripherals::$inst<'_> { + /// Returns peripheral data for MCPWM $id + fn info() -> &'static Info { + static INFO: Info = Info { + register_block: crate::peripherals::MCPWM0::regs(), + _peripheral: crate::system::Peripheral::Mcpwm0, + _interrupt: crate::peripherals::Interrupt::MCPWM0, + sync_input: [ + InputSignal::[], + InputSignal::[], + InputSignal::[], + ], + capture_input: [ + InputSignal::[], + InputSignal::[], + InputSignal::[], + ], + operator_a_output: [ + OutputSignal::[], + OutputSignal::[], + OutputSignal::[], + ], + operator_b_output: [ + OutputSignal::[], + OutputSignal::[], + OutputSignal::[], + ], + }; + + &INFO + } + } } -} + }; +); #[allow(dead_code)] // Field is seemingly unused but we rely on its Drop impl struct PwmClockGuard(DropGuard<(), fn(())>); diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 4faefc44527..773fe93984e 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -13,11 +13,11 @@ //! ### Software Sync Events //! The `timer` module supports the software triggering of syncs from Timers. #![cfg_attr( - soc_has_mcpwm_swsync_can_propagate, + mcpwm_swsync_can_propagate, doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." )] #![cfg_attr( - not(soc_has_mcpwm_swsync_can_propagate), + not(mcpwm_swsync_can_propagate), doc = "**Note:** Software triggered sync events do not propagate to other timers on this chip." )] @@ -132,7 +132,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// Then trigger a software sync event. #[cfg_attr( docsrs, - doc(cfg(soc_has_mcpwm_swsync_can_propagate)), + doc(cfg(mcpwm_swsync_can_propagate)), doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." )] pub fn set_counter(&mut self, phase: u16, direction: CounterDirection) { @@ -144,7 +144,7 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// Trigger a software sync event #[cfg_attr( docsrs, - doc(cfg(soc_has_mcpwm_swsync_can_propagate)), + doc(cfg(mcpwm_swsync_can_propagate)), doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." )] pub fn trigger_sync(&mut self) { diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 514860f1b6a..552d20ca961 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -305,6 +305,8 @@ impl Chip { "dac_dac2", "i2c_master_i2c0", "i2c_master_i2c1", + "mcpwm_mcpwm0", + "mcpwm_mcpwm1", "spi_master_spi2", "spi_master_spi3", "spi_slave_spi2", @@ -502,6 +504,8 @@ impl Chip { "cargo:rustc-cfg=dac_dac2", "cargo:rustc-cfg=i2c_master_i2c0", "cargo:rustc-cfg=i2c_master_i2c1", + "cargo:rustc-cfg=mcpwm_mcpwm0", + "cargo:rustc-cfg=mcpwm_mcpwm1", "cargo:rustc-cfg=spi_master_spi2", "cargo:rustc-cfg=spi_master_spi3", "cargo:rustc-cfg=spi_slave_spi2", @@ -1773,11 +1777,6 @@ impl Chip { "soc_has_mem2mem7", "soc_has_mem2mem8", "soc_has_psram", - "soc_has_mcpwm_swsync_can_propagate", - "soc_has_mcpwm_capture_clk_from_group", - "soc_has_mcpwm_support_etm", - "soc_has_mcpwm_support_event_comparator", - "soc_has_mcpwm_support_sleep_retention", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", @@ -1867,6 +1866,11 @@ impl Chip { "interrupt_controller=\"clic\"", "lp_i2c_master_fifo_size=\"16\"", "lp_uart_ram_size=\"32\"", + "mcpwm_swsync_can_propagate", + "mcpwm_capture_clk_from_group", + "mcpwm_support_etm", + "mcpwm_support_sleep_retention", + "mcpwm_support_event_comparator", "parl_io_version=\"2\"", "phy_combo_module", "rmt_ram_start=\"1610638336\"", @@ -2022,11 +2026,6 @@ impl Chip { "cargo:rustc-cfg=soc_has_mem2mem7", "cargo:rustc-cfg=soc_has_mem2mem8", "cargo:rustc-cfg=soc_has_psram", - "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", - "cargo:rustc-cfg=soc_has_mcpwm_capture_clk_from_group", - "cargo:rustc-cfg=soc_has_mcpwm_support_etm", - "cargo:rustc-cfg=soc_has_mcpwm_support_event_comparator", - "cargo:rustc-cfg=soc_has_mcpwm_support_sleep_retention", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", @@ -2116,6 +2115,11 @@ impl Chip { "cargo:rustc-cfg=interrupt_controller=\"clic\"", "cargo:rustc-cfg=lp_i2c_master_fifo_size=\"16\"", "cargo:rustc-cfg=lp_uart_ram_size=\"32\"", + "cargo:rustc-cfg=mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=mcpwm_support_etm", + "cargo:rustc-cfg=mcpwm_support_sleep_retention", + "cargo:rustc-cfg=mcpwm_support_event_comparator", "cargo:rustc-cfg=parl_io_version=\"2\"", "cargo:rustc-cfg=phy_combo_module", "cargo:rustc-cfg=rmt_ram_start=\"1610638336\"", @@ -2389,10 +2393,6 @@ impl Chip { "rom_crc_le", "rom_crc_be", "rom_md5_bsd", - "soc_has_mcpwm_swsync_can_propagate", - "soc_has_mcpwm_capture_clk_from_group", - "soc_has_mcpwm_support_etm", - "soc_has_mcpwm_support_sleep_retention", "pm_support_wifi_wakeup", "pm_support_beacon_wakeup", "pm_support_bt_wakeup", @@ -2442,6 +2442,7 @@ impl Chip { "wifi_driver_supported", "adc_adc1", "i2c_master_i2c0", + "mcpwm_mcpwm0", "spi_master_spi2", "spi_slave_spi2", "timergroup_timg0", @@ -2492,6 +2493,10 @@ impl Chip { "interrupt_controller=\"plic\"", "lp_i2c_master_fifo_size=\"16\"", "lp_uart_ram_size=\"32\"", + "mcpwm_swsync_can_propagate", + "mcpwm_capture_clk_from_group", + "mcpwm_support_etm", + "mcpwm_support_sleep_retention", "parl_io_version=\"1\"", "phy_combo_module", "rmt_ram_start=\"1610638336\"", @@ -2667,10 +2672,6 @@ impl Chip { "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", - "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", - "cargo:rustc-cfg=soc_has_mcpwm_capture_clk_from_group", - "cargo:rustc-cfg=soc_has_mcpwm_support_etm", - "cargo:rustc-cfg=soc_has_mcpwm_support_sleep_retention", "cargo:rustc-cfg=pm_support_wifi_wakeup", "cargo:rustc-cfg=pm_support_beacon_wakeup", "cargo:rustc-cfg=pm_support_bt_wakeup", @@ -2720,6 +2721,7 @@ impl Chip { "cargo:rustc-cfg=wifi_driver_supported", "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=i2c_master_i2c0", + "cargo:rustc-cfg=mcpwm_mcpwm0", "cargo:rustc-cfg=spi_master_spi2", "cargo:rustc-cfg=spi_slave_spi2", "cargo:rustc-cfg=timergroup_timg0", @@ -2770,6 +2772,10 @@ impl Chip { "cargo:rustc-cfg=interrupt_controller=\"plic\"", "cargo:rustc-cfg=lp_i2c_master_fifo_size=\"16\"", "cargo:rustc-cfg=lp_uart_ram_size=\"32\"", + "cargo:rustc-cfg=mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=mcpwm_support_etm", + "cargo:rustc-cfg=mcpwm_support_sleep_retention", "cargo:rustc-cfg=parl_io_version=\"1\"", "cargo:rustc-cfg=phy_combo_module", "cargo:rustc-cfg=rmt_ram_start=\"1610638336\"", @@ -3499,10 +3505,6 @@ impl Chip { "soc_has_mem2mem8", "phy", "swd", - "soc_has_mcpwm_swsync_can_propagate", - "soc_has_mcpwm_capture_clk_from_group", - "soc_has_mcpwm_support_etm", - "soc_has_mcpwm_support_sleep_retention", "rom_crc_le", "rom_crc_be", "rom_md5_bsd", @@ -3545,6 +3547,7 @@ impl Chip { "adc_adc1", "i2c_master_i2c0", "i2c_master_i2c1", + "mcpwm_mcpwm0", "spi_master_spi2", "spi_slave_spi2", "timergroup_timg0", @@ -3597,6 +3600,10 @@ impl Chip { "i2c_master_fifo_size=\"32\"", "interrupts_status_registers=\"2\"", "interrupt_controller=\"plic\"", + "mcpwm_swsync_can_propagate", + "mcpwm_capture_clk_from_group", + "mcpwm_support_etm", + "mcpwm_support_sleep_retention", "parl_io_version=\"2\"", "rmt_ram_start=\"1610642432\"", "rmt_channel_ram_size=\"48\"", @@ -3742,10 +3749,6 @@ impl Chip { "cargo:rustc-cfg=soc_has_mem2mem8", "cargo:rustc-cfg=phy", "cargo:rustc-cfg=swd", - "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", - "cargo:rustc-cfg=soc_has_mcpwm_capture_clk_from_group", - "cargo:rustc-cfg=soc_has_mcpwm_support_etm", - "cargo:rustc-cfg=soc_has_mcpwm_support_sleep_retention", "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", @@ -3788,6 +3791,7 @@ impl Chip { "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=i2c_master_i2c0", "cargo:rustc-cfg=i2c_master_i2c1", + "cargo:rustc-cfg=mcpwm_mcpwm0", "cargo:rustc-cfg=spi_master_spi2", "cargo:rustc-cfg=spi_slave_spi2", "cargo:rustc-cfg=timergroup_timg0", @@ -3840,6 +3844,10 @@ impl Chip { "cargo:rustc-cfg=i2c_master_fifo_size=\"32\"", "cargo:rustc-cfg=interrupts_status_registers=\"2\"", "cargo:rustc-cfg=interrupt_controller=\"plic\"", + "cargo:rustc-cfg=mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=mcpwm_capture_clk_from_group", + "cargo:rustc-cfg=mcpwm_support_etm", + "cargo:rustc-cfg=mcpwm_support_sleep_retention", "cargo:rustc-cfg=parl_io_version=\"2\"", "cargo:rustc-cfg=rmt_ram_start=\"1610642432\"", "cargo:rustc-cfg=rmt_channel_ram_size=\"48\"", @@ -4701,7 +4709,7 @@ impl Chip { "rom_crc_le", "rom_crc_be", "rom_md5_bsd", - "soc_has_mcpwm_swsync_can_propagate", + "mcpwm_swsync_can_propagate", "pm_support_ext0_wakeup", "pm_support_ext1_wakeup", "pm_support_touch_sensor_wakeup", @@ -4754,6 +4762,8 @@ impl Chip { "adc_adc2", "i2c_master_i2c0", "i2c_master_i2c1", + "mcpwm_mcpwm0", + "mcpwm_mcpwm1", "spi_master_spi2", "spi_master_spi3", "spi_slave_spi2", @@ -4801,6 +4811,7 @@ impl Chip { "i2c_master_fifo_size=\"32\"", "interrupts_status_registers=\"4\"", "interrupt_controller=\"xtensa\"", + "mcpwm_swsync_can_propagate", "phy_combo_module", "phy_backed_up_digital_register_count=\"21\"", "phy_backed_up_digital_register_count_is_set", @@ -4949,7 +4960,7 @@ impl Chip { "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", - "cargo:rustc-cfg=soc_has_mcpwm_swsync_can_propagate", + "cargo:rustc-cfg=mcpwm_swsync_can_propagate", "cargo:rustc-cfg=pm_support_ext0_wakeup", "cargo:rustc-cfg=pm_support_ext1_wakeup", "cargo:rustc-cfg=pm_support_touch_sensor_wakeup", @@ -5002,6 +5013,8 @@ impl Chip { "cargo:rustc-cfg=adc_adc2", "cargo:rustc-cfg=i2c_master_i2c0", "cargo:rustc-cfg=i2c_master_i2c1", + "cargo:rustc-cfg=mcpwm_mcpwm0", + "cargo:rustc-cfg=mcpwm_mcpwm1", "cargo:rustc-cfg=spi_master_spi2", "cargo:rustc-cfg=spi_master_spi3", "cargo:rustc-cfg=spi_slave_spi2", @@ -5049,6 +5062,7 @@ impl Chip { "cargo:rustc-cfg=i2c_master_fifo_size=\"32\"", "cargo:rustc-cfg=interrupts_status_registers=\"4\"", "cargo:rustc-cfg=interrupt_controller=\"xtensa\"", + "cargo:rustc-cfg=mcpwm_swsync_can_propagate", "cargo:rustc-cfg=phy_combo_module", "cargo:rustc-cfg=phy_backed_up_digital_register_count=\"21\"", "cargo:rustc-cfg=phy_backed_up_digital_register_count_is_set", @@ -5490,6 +5504,8 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(dac_dac2)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_i2c0)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_i2c1)"); + println!("cargo:rustc-check-cfg=cfg(mcpwm_mcpwm0)"); + println!("cargo:rustc-check-cfg=cfg(mcpwm_mcpwm1)"); println!("cargo:rustc-check-cfg=cfg(spi_master_spi2)"); println!("cargo:rustc-check-cfg=cfg(spi_master_spi3)"); println!("cargo:rustc-check-cfg=cfg(spi_slave_spi2)"); @@ -5683,11 +5699,6 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem6)"); println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem7)"); println!("cargo:rustc-check-cfg=cfg(soc_has_mem2mem8)"); - println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_swsync_can_propagate)"); - println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_capture_clk_from_group)"); - println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_support_etm)"); - println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_support_event_comparator)"); - println!("cargo:rustc-check-cfg=cfg(soc_has_mcpwm_support_sleep_retention)"); println!("cargo:rustc-check-cfg=cfg(ieee802154_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(lp_i2c_master_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(parl_io_driver_supported)"); @@ -5700,6 +5711,11 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(ecc_has_curve_p384)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_can_estimate_nack_reason)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_has_reliable_fsm_reset)"); + println!("cargo:rustc-check-cfg=cfg(mcpwm_swsync_can_propagate)"); + println!("cargo:rustc-check-cfg=cfg(mcpwm_capture_clk_from_group)"); + println!("cargo:rustc-check-cfg=cfg(mcpwm_support_etm)"); + println!("cargo:rustc-check-cfg=cfg(mcpwm_support_sleep_retention)"); + println!("cargo:rustc-check-cfg=cfg(mcpwm_support_event_comparator)"); println!("cargo:rustc-check-cfg=cfg(rmt_has_tx_loop_auto_stop)"); println!("cargo:rustc-check-cfg=cfg(rmt_supports_pll80mhz_clock)"); println!("cargo:rustc-check-cfg=cfg(soc_cpu_has_branch_predictor)"); @@ -5781,6 +5797,7 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(soc_has_wcl)"); println!("cargo:rustc-check-cfg=cfg(soc_has_dma_ch3)"); println!("cargo:rustc-check-cfg=cfg(soc_has_dma_ch4)"); + println!("cargo:rustc-check-cfg=cfg(mcpwm_swsync_can_propagate)"); println!("cargo:rustc-check-cfg=cfg(camera_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(psram_octal_spi)"); println!("cargo:rustc-check-cfg=cfg(rmt_has_dma)"); diff --git a/esp-metadata-generated/src/_generated_esp32.rs b/esp-metadata-generated/src/_generated_esp32.rs index 409de03f410..019ab9ad134 100644 --- a/esp-metadata-generated/src/_generated_esp32.rs +++ b/esp-metadata-generated/src/_generated_esp32.rs @@ -178,6 +178,21 @@ macro_rules! property { ("interrupts.status_registers", str) => { stringify!(3) }; + ("mcpwm.swsync_can_propagate") => { + false + }; + ("mcpwm.capture_clk_from_group") => { + false + }; + ("mcpwm.support_etm") => { + false + }; + ("mcpwm.support_sleep_retention") => { + false + }; + ("mcpwm.support_event_comparator") => { + false + }; ("phy.combo_module") => { true }; @@ -3107,6 +3122,31 @@ macro_rules! for_each_uart { U2RTS))); }; } +/// This macro can be used to generate code for each peripheral instance of the MCPWM driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($id:literal, $instance:ident, $sys:ident)` +/// +/// Macro fragments: +/// +/// - `$id`: the index of the MCPWM instance +/// - `$instance`: the name of the MCPWM instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// +/// Example data: `(0, MCPWM0, Mcpwm0)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_mcpwm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_mcpwm { $(($pattern) => $code;)* ($other : tt) => {} + } _for_each_inner_mcpwm!((0, MCPWM0, Mcpwm0)); _for_each_inner_mcpwm!((1, MCPWM1, + Mcpwm1)); _for_each_inner_mcpwm!((all(0, MCPWM0, Mcpwm0), (1, MCPWM1, Mcpwm1))); + }; +} /// This macro can be used to generate code for each peripheral instance of the SPI master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32c5.rs b/esp-metadata-generated/src/_generated_esp32c5.rs index b66b7c5e49c..c08bac9a16d 100644 --- a/esp-metadata-generated/src/_generated_esp32c5.rs +++ b/esp-metadata-generated/src/_generated_esp32c5.rs @@ -229,6 +229,21 @@ macro_rules! property { ("lp_uart.ram_size", str) => { stringify!(32) }; + ("mcpwm.swsync_can_propagate") => { + true + }; + ("mcpwm.capture_clk_from_group") => { + true + }; + ("mcpwm.support_etm") => { + true + }; + ("mcpwm.support_sleep_retention") => { + true + }; + ("mcpwm.support_event_comparator") => { + true + }; ("parl_io.version") => { 2 }; @@ -3377,6 +3392,30 @@ macro_rules! for_each_uart { UART1, Uart1, U1RXD, U1TXD, U1CTS, U1RTS))); }; } +/// This macro can be used to generate code for each peripheral instance of the MCPWM driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($id:literal, $instance:ident, $sys:ident)` +/// +/// Macro fragments: +/// +/// - `$id`: the index of the MCPWM instance +/// - `$instance`: the name of the MCPWM instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// +/// Example data: `(0, MCPWM0, Mcpwm0)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_mcpwm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_mcpwm { $(($pattern) => $code;)* ($other : tt) => {} + } _for_each_inner_mcpwm!((all)); + }; +} /// This macro can be used to generate code for each peripheral instance of the SPI master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32c6.rs b/esp-metadata-generated/src/_generated_esp32c6.rs index f3579164e18..5d415ffdf77 100644 --- a/esp-metadata-generated/src/_generated_esp32c6.rs +++ b/esp-metadata-generated/src/_generated_esp32c6.rs @@ -229,6 +229,21 @@ macro_rules! property { ("lp_uart.ram_size", str) => { stringify!(32) }; + ("mcpwm.swsync_can_propagate") => { + true + }; + ("mcpwm.capture_clk_from_group") => { + true + }; + ("mcpwm.support_etm") => { + true + }; + ("mcpwm.support_sleep_retention") => { + true + }; + ("mcpwm.support_event_comparator") => { + false + }; ("parl_io.version") => { 1 }; @@ -4148,6 +4163,31 @@ macro_rules! for_each_uart { UART1, Uart1, U1RXD, U1TXD, U1CTS, U1RTS))); }; } +/// This macro can be used to generate code for each peripheral instance of the MCPWM driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($id:literal, $instance:ident, $sys:ident)` +/// +/// Macro fragments: +/// +/// - `$id`: the index of the MCPWM instance +/// - `$instance`: the name of the MCPWM instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// +/// Example data: `(0, MCPWM0, Mcpwm0)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_mcpwm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_mcpwm { $(($pattern) => $code;)* ($other : tt) => {} + } _for_each_inner_mcpwm!((0, MCPWM0, Mcpwm0)); _for_each_inner_mcpwm!((all(0, + MCPWM0, Mcpwm0))); + }; +} /// This macro can be used to generate code for each peripheral instance of the SPI master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32h2.rs b/esp-metadata-generated/src/_generated_esp32h2.rs index 474bafd4a4f..fbf3a43ec46 100644 --- a/esp-metadata-generated/src/_generated_esp32h2.rs +++ b/esp-metadata-generated/src/_generated_esp32h2.rs @@ -217,6 +217,21 @@ macro_rules! property { ("interrupts.disabled_interrupt") => { 31 }; + ("mcpwm.swsync_can_propagate") => { + true + }; + ("mcpwm.capture_clk_from_group") => { + true + }; + ("mcpwm.support_etm") => { + true + }; + ("mcpwm.support_sleep_retention") => { + true + }; + ("mcpwm.support_event_comparator") => { + false + }; ("parl_io.version") => { 2 }; @@ -3224,6 +3239,31 @@ macro_rules! for_each_uart { UART1, Uart1, U1RXD, U1TXD, U1CTS, U1RTS))); }; } +/// This macro can be used to generate code for each peripheral instance of the MCPWM driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($id:literal, $instance:ident, $sys:ident)` +/// +/// Macro fragments: +/// +/// - `$id`: the index of the MCPWM instance +/// - `$instance`: the name of the MCPWM instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// +/// Example data: `(0, MCPWM0, Mcpwm0)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_mcpwm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_mcpwm { $(($pattern) => $code;)* ($other : tt) => {} + } _for_each_inner_mcpwm!((0, MCPWM0, Mcpwm0)); _for_each_inner_mcpwm!((all(0, + MCPWM0, Mcpwm0))); + }; +} /// This macro can be used to generate code for each peripheral instance of the SPI master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32s3.rs b/esp-metadata-generated/src/_generated_esp32s3.rs index 6be1d36c5da..4fb92882087 100644 --- a/esp-metadata-generated/src/_generated_esp32s3.rs +++ b/esp-metadata-generated/src/_generated_esp32s3.rs @@ -199,6 +199,21 @@ macro_rules! property { ("interrupts.status_registers", str) => { stringify!(4) }; + ("mcpwm.swsync_can_propagate") => { + true + }; + ("mcpwm.capture_clk_from_group") => { + false + }; + ("mcpwm.support_etm") => { + false + }; + ("mcpwm.support_sleep_retention") => { + false + }; + ("mcpwm.support_event_comparator") => { + false + }; ("phy.combo_module") => { true }; @@ -3379,6 +3394,31 @@ macro_rules! for_each_uart { U2RTS))); }; } +/// This macro can be used to generate code for each peripheral instance of the MCPWM driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($id:literal, $instance:ident, $sys:ident)` +/// +/// Macro fragments: +/// +/// - `$id`: the index of the MCPWM instance +/// - `$instance`: the name of the MCPWM instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// +/// Example data: `(0, MCPWM0, Mcpwm0)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_mcpwm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_mcpwm { $(($pattern) => $code;)* ($other : tt) => {} + } _for_each_inner_mcpwm!((0, MCPWM0, Mcpwm0)); _for_each_inner_mcpwm!((1, MCPWM1, + Mcpwm1)); _for_each_inner_mcpwm!((all(0, MCPWM0, Mcpwm0), (1, MCPWM1, Mcpwm1))); + }; +} /// This macro can be used to generate code for each peripheral instance of the SPI master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata/devices/esp32.toml b/esp-metadata/devices/esp32.toml index 4f669b652ba..faf044e0a4e 100644 --- a/esp-metadata/devices/esp32.toml +++ b/esp-metadata/devices/esp32.toml @@ -874,12 +874,18 @@ support_status = "partial" light_sleep = true deep_sleep = true +[device.mcpwm] +support_status = "partial" +instances = [ + { name = "mcpwm0", sys_instance = "Mcpwm0" }, + { name = "mcpwm1", sys_instance = "Mcpwm1" }, +] + # Other drivers which are partially supported but have no other configuration: ## Interfaces [device.i2s] [device.ledc] -[device.mcpwm] [device.pcnt] [device.sd_host] [device.sd_slave] diff --git a/esp-metadata/devices/esp32c5.toml b/esp-metadata/devices/esp32c5.toml index 65d61ed566a..287cf4136d3 100644 --- a/esp-metadata/devices/esp32c5.toml +++ b/esp-metadata/devices/esp32c5.toml @@ -16,13 +16,6 @@ symbols = [ # Additional peripherals defined by us (the developers): # "lp_core", - # MCPWM capabilities - "soc_has_mcpwm_swsync_can_propagate", - "soc_has_mcpwm_capture_clk_from_group", - "soc_has_mcpwm_support_etm", - "soc_has_mcpwm_support_event_comparator", - "soc_has_mcpwm_support_sleep_retention", - # ROM capabilities "rom_crc_le", "rom_crc_be", @@ -690,6 +683,12 @@ support_status = { status = "not_supported", issue = 5161 } [device.mcpwm] support_status = { status = "not_supported", issue = 5154 } +# Although mcpwm is not supported these features are worth noting for future implementation +swsync_can_propagate = true +capture_clk_from_group = true +support_etm = true +support_event_comparator = true +support_sleep_retention = true [device.sleep] support_status = { status = "not_supported", issue = 5165 } diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 26533747a4e..77af093728e 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -23,12 +23,6 @@ symbols = [ "rom_crc_be", "rom_md5_bsd", - # MCPWM capabilities - "soc_has_mcpwm_swsync_can_propagate", - "soc_has_mcpwm_capture_clk_from_group", - "soc_has_mcpwm_support_etm", - "soc_has_mcpwm_support_sleep_retention", - # Wakeup SOC based on ESP-IDF: "pm_support_wifi_wakeup", "pm_support_beacon_wakeup", @@ -750,6 +744,16 @@ deep_sleep = true support_status = "partial" version = 1 +[device.mcpwm] +support_status = "partial" +swsync_can_propagate = true +capture_clk_from_group = true +support_etm = true +support_sleep_retention = true +instances = [ + { name = "mcpwm0", sys_instance = "Mcpwm0" }, +] + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -758,7 +762,6 @@ version = 1 ## Interfaces [device.i2s] [device.ledc] -[device.mcpwm] [device.pcnt] [device.sd_slave] diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index 25620c8f028..ec9a4fae429 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -17,12 +17,6 @@ symbols = [ "phy", "swd", - # MCPWM capabilities - "soc_has_mcpwm_swsync_can_propagate", - "soc_has_mcpwm_capture_clk_from_group", - "soc_has_mcpwm_support_etm", - "soc_has_mcpwm_support_sleep_retention", - # ROM capabilities "rom_crc_le", "rom_crc_be", @@ -645,6 +639,16 @@ support_status = "partial" light_sleep = true deep_sleep = true +[device.mcpwm] +support_status = "partial" +swsync_can_propagate = true +capture_clk_from_group = true +support_etm = true +support_sleep_retention = true +instances = [ + { name = "mcpwm0", sys_instance = "Mcpwm0" }, +] + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -653,7 +657,6 @@ deep_sleep = true ## Interfaces [device.i2s] [device.ledc] -[device.mcpwm] [device.pcnt] [device.twai] [device.usb_serial_jtag] diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index 1dbc0a05b68..e00add79597 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -24,7 +24,7 @@ symbols = [ "rom_md5_bsd", # MCPWM capabilities - "soc_has_mcpwm_swsync_can_propagate", + "mcpwm_swsync_can_propagate", # Wakeup SOC based on ESP-IDF: "pm_support_ext0_wakeup", @@ -860,6 +860,14 @@ support_status = "partial" light_sleep = true deep_sleep = true +[device.mcpwm] +support_status = "partial" +swsync_can_propagate = true +instances = [ + { name = "mcpwm0", sys_instance = "Mcpwm0" }, + { name = "mcpwm1", sys_instance = "Mcpwm1" }, +] + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -870,7 +878,6 @@ deep_sleep = true [device.camera] [device.rgb_display] [device.ledc] -[device.mcpwm] [device.pcnt] [device.sd_host] [device.twai] diff --git a/esp-metadata/src/cfg.rs b/esp-metadata/src/cfg.rs index ab4338ba2c1..6e9025e796e 100644 --- a/esp-metadata/src/cfg.rs +++ b/esp-metadata/src/cfg.rs @@ -3,6 +3,7 @@ pub(crate) mod ecc; pub(crate) mod gpio; pub(crate) mod i2c_master; pub(crate) mod interrupt; +pub(crate) mod mcpwm; pub(crate) mod rmt; pub(crate) mod rsa; pub(crate) mod sha; @@ -17,6 +18,7 @@ pub(crate) use ecc::*; pub(crate) use gpio::*; pub(crate) use i2c_master::*; pub(crate) use interrupt::*; +pub(crate) use mcpwm::*; pub(crate) use rmt::*; pub(crate) use sha::*; pub(crate) use soc::*; @@ -491,10 +493,21 @@ driver_configs![ ram_size: u32, } }, - McpwmProperties { + McpwmProperties { driver: mcpwm, name: "MCPWM", - properties: {} + properties: { + #[serde(default)] + swsync_can_propagate: bool, + #[serde(default)] + capture_clk_from_group: bool, + #[serde(default)] + support_etm: bool, + #[serde(default)] + support_sleep_retention: bool, + #[serde(default)] + support_event_comparator: bool, + } }, ParlIoProperties { driver: parl_io, diff --git a/esp-metadata/src/cfg/mcpwm.rs b/esp-metadata/src/cfg/mcpwm.rs new file mode 100644 index 00000000000..adf314a01d3 --- /dev/null +++ b/esp-metadata/src/cfg/mcpwm.rs @@ -0,0 +1,57 @@ +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; + +use crate::{cfg::McpwmProperties, generate_for_each_macro}; + +/// Instance configuration, used in [device.mcpwm.instances] +#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)] +pub(crate) struct McpwmInstanceConfig { + /// The name of the instance in the `esp_hal::system::Peripheral` enum + pub sys_instance: String, +} + +/// Generates `for_each_mcpwm!` which can be used to implement the MCPWM +/// Instance trait for the relevant peripherals. The macro generates code +/// for each [device.mcpwm.instances[X]] instance. +pub(crate) fn generate_mcpwm_peripherals(mcpwm: &McpwmProperties) -> TokenStream { + let mcpwm_instance_cfgs = mcpwm + .instances + .iter() + .enumerate() + .map(|(index, instance)| { + let instance_config = &instance.instance_config; + + let id = crate::number(index); + + let instance = format_ident!("{}", instance.name.to_uppercase()); + let sys = format_ident!("{}", instance_config.sys_instance); + + // The order and meaning of these tokens must match their use in the + // `for_each_mcpwm!` call. + quote! { + #id, #instance, #sys + } + }) + .collect::>(); + + let for_each = generate_for_each_macro("mcpwm", &[("all", &mcpwm_instance_cfgs)]); + quote! { + /// This macro can be used to generate code for each peripheral instance of the MCPWM driver. + /// + /// For an explanation on the general syntax, as well as usage of individual/repeated + /// matchers, refer to [the crate-level documentation][crate#for_each-macros]. + /// + /// This macro has one option for its "Individual matcher" case: + /// + /// Syntax: `($id:literal, $instance:ident, $sys:ident)` + /// + /// Macro fragments: + /// + /// - `$id`: the index of the MCPWM instance + /// - `$instance`: the name of the MCPWM instance + /// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. + /// + /// Example data: `(0, MCPWM0, Mcpwm0)` + #for_each + } +} diff --git a/esp-metadata/src/lib.rs b/esp-metadata/src/lib.rs index f9d8d369834..87dfaf58cf2 100644 --- a/esp-metadata/src/lib.rs +++ b/esp-metadata/src/lib.rs @@ -618,6 +618,9 @@ impl Config { if let Some(peri) = self.device.peri_config.uart.as_ref() { tokens.extend(cfg::generate_uart_peripherals(peri)); } + if let Some(peri) = self.device.peri_config.mcpwm.as_ref() { + tokens.extend(cfg::generate_mcpwm_peripherals(peri)); + } if let Some(peri) = self.device.peri_config.spi_master.as_ref() { tokens.extend(cfg::generate_spi_master_peripherals(peri)); }; From df1c237b04fb816d15af863008ff22e0d5014d1c Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:12:30 -0600 Subject: [PATCH 32/37] Whoops forgot to remove for esp32s3 chip Removed mcpwm_swsync_can_propagate since the device.mcpwm generates the configs --- esp-metadata-generated/src/_build_script_utils.rs | 3 --- esp-metadata/devices/esp32s3.toml | 3 --- 2 files changed, 6 deletions(-) diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 552d20ca961..aed846af424 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -4709,7 +4709,6 @@ impl Chip { "rom_crc_le", "rom_crc_be", "rom_md5_bsd", - "mcpwm_swsync_can_propagate", "pm_support_ext0_wakeup", "pm_support_ext1_wakeup", "pm_support_touch_sensor_wakeup", @@ -4960,7 +4959,6 @@ impl Chip { "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", - "cargo:rustc-cfg=mcpwm_swsync_can_propagate", "cargo:rustc-cfg=pm_support_ext0_wakeup", "cargo:rustc-cfg=pm_support_ext1_wakeup", "cargo:rustc-cfg=pm_support_touch_sensor_wakeup", @@ -5797,7 +5795,6 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(soc_has_wcl)"); println!("cargo:rustc-check-cfg=cfg(soc_has_dma_ch3)"); println!("cargo:rustc-check-cfg=cfg(soc_has_dma_ch4)"); - println!("cargo:rustc-check-cfg=cfg(mcpwm_swsync_can_propagate)"); println!("cargo:rustc-check-cfg=cfg(camera_driver_supported)"); println!("cargo:rustc-check-cfg=cfg(psram_octal_spi)"); println!("cargo:rustc-check-cfg=cfg(rmt_has_dma)"); diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index e00add79597..1c0a36e0062 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -23,9 +23,6 @@ symbols = [ "rom_crc_be", "rom_md5_bsd", - # MCPWM capabilities - "mcpwm_swsync_can_propagate", - # Wakeup SOC based on ESP-IDF: "pm_support_ext0_wakeup", "pm_support_ext1_wakeup", From 99c99742b30395b0f392ed16ae2be0cc0d9149c2 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:16:25 -0600 Subject: [PATCH 33/37] Fixed typos and referencing wrong peripheral --- esp-hal/src/mcpwm/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index 50a0a6145b7..f3bf35cbc76 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -486,7 +486,7 @@ impl Info { unsafe { &*self.register_block } } - /// Returns the periperal + /// Returns the peripheral pub fn peripheral(&self) -> crate::system::Peripheral { self._peripheral } @@ -567,9 +567,9 @@ for_each_mcpwm!( /// Returns peripheral data for MCPWM $id fn info() -> &'static Info { static INFO: Info = Info { - register_block: crate::peripherals::MCPWM0::regs(), - _peripheral: crate::system::Peripheral::Mcpwm0, - _interrupt: crate::peripherals::Interrupt::MCPWM0, + register_block: crate::peripherals::$inst::regs(), + _peripheral: crate::system::Peripheral::$sys, + _interrupt: crate::peripherals::Interrupt::$inst, sync_input: [ InputSignal::[], InputSignal::[], From a852e89aa06975e1d735d902fdaffadcbb15c02a Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:09:06 -0600 Subject: [PATCH 34/37] Additional Checks for Illegal HW States Added an additional check to make sure the sync range provided by the timer config is valid. As well as updated some of the formatting of comments. Renamed functions to better follow the developer guidelines. --- esp-hal/CHANGELOG.md | 4 +- esp-hal/MIGRATING-1.0.0.md | 4 +- esp-hal/src/mcpwm/capture.rs | 10 +- esp-hal/src/mcpwm/mod.rs | 2 +- esp-hal/src/mcpwm/timer.rs | 171 ++++++++++++++++++++++++----------- 5 files changed, 126 insertions(+), 65 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 5c9d8bcf059..779f5a79522 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -62,7 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - C61: Add PSRAM support (#5325) - MCPWM: Add external sync line and timer sync out support. (#5344) - MCPWM: Add capture channel and timer support. (#5344) -- MCPWM: Added `esp_hal::mcpwm::timer::Timer::set_config` to apply a config to a timer. (#5344) +- MCPWM: Added `esp_hal::mcpwm::timer::Timer::apply_config` to apply a config to a timer. (#5344) ### Changed @@ -104,7 +104,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `esp_hal::efuse::chip_revision` has been marked stable (#5287) - `esp_hal::efuse::chip_revision` now returns `ChipRevision` (#5287) - DMA buffers can now be created using empty buffer slices (#5266) -- MCPWM: `esp_hal::mcpwm::timer::Timer::start` is now parameterless. Instead, use `esp_hal::mcpwm::timer::Timer::set_config` to apply a config to a timer. (#5344) +- MCPWM: `esp_hal::mcpwm::timer::Timer::start` is now parameterless. Instead, use `esp_hal::mcpwm::timer::Timer::apply_config` to apply a config to a timer. (#5344) - MCPWM: timers default to the config given by `PeripheralClockConfig::timer_clock_default()`. (#5344) ### Fixed diff --git a/esp-hal/MIGRATING-1.0.0.md b/esp-hal/MIGRATING-1.0.0.md index b9d6640e16c..cf8b84ae099 100644 --- a/esp-hal/MIGRATING-1.0.0.md +++ b/esp-hal/MIGRATING-1.0.0.md @@ -182,7 +182,7 @@ expensive. ## MCPWM changes - The `Timer::start` method is now parameterless and doesn't take in a `TimerClockConfig`. - Instead, use `Timer::set_config` method to set the config for the `mcpwm::Timer`. + Instead, use `Timer::apply_config` method to set the config for the `mcpwm::Timer`. - `Timer::start` starts with the configured `StopCondition` rather than being restricted to running till `Timer::stop` is called. - Timers now have a default configuration when you create a MCPWM instance via `McPwm::new`. @@ -193,6 +193,6 @@ a simple change. ```diff -mcpwm.timer0.start(timer_clock_cfg); -+mcpwm.timer0.set_config(timer_clock_cfg); ++mcpwm.timer0.apply_config(timer_clock_cfg); +mcpwm.timer0.start(); ``` diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 7970c36e284..9f81bf95169 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -11,14 +11,10 @@ //! capture timer during specific software or hardware triggered //! 'capture' events. //! -//! ### Capture events can be triggered in 2 ways: -//! 1. During a falling and/or Rising edge of a preconfigured GPIO pin. -//! 2. Software triggered captures through [`CaptureChannel::trigger_capture`]. -//! -//! ### Configuration +//! ## Configuration //! This module provides the flexibility of configuring any GPIO pin as an input //! for capturing the rising and/or falling edge of a signal. This module allows -//! for the ability to trigger software captures. +//! for the ability to trigger software captures to record the current timer's value. //! //! ## Example //! @@ -161,7 +157,7 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { } /// Configure the capture timer with the provided config - pub fn set_config(&mut self, config: CaptureTimerConfig) { + pub fn apply_config(&mut self, config: CaptureTimerConfig) { self.set_sync_phase(config.sync_phase); } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index f3bf35cbc76..cc80170fc38 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -102,7 +102,7 @@ //! let timer_clock_cfg = clock_cfg //! .timer_clock_with_frequency(99, PwmWorkingMode::Increase, //! Rate::from_khz(20))?; -//! mcpwm.timer0.set_config(timer_clock_cfg); +//! mcpwm.timer0.apply_config(timer_clock_cfg)?; //! mcpwm.timer0.start(); //! //! // pin will be high 50% of the time diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index 773fe93984e..d8208adc98f 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -1,24 +1,24 @@ -#![cfg_attr(docsrs, procmacros::doc_replace)] - //! # MCPWM Timer Module //! //! ## Overview //! The `timer` module provides an interface to configure and use timers for //! generating `PWM` signals used in motor control and other applications. //! -//! The `timer` module allows the configuration of setting the sync in source -//! for the timer, and the ability to get their sync out to given to other timers -//! as their sync in. +//! * Timers can be configured with different clock frequencies, periods, and prescalers using the +//! [`TimerClockConfig`] struct. //! -//! ### Software Sync Events -//! The `timer` module supports the software triggering of syncs from Timers. +//! ## Sync Events +//! * Timers can be configured to generate sync events when the timer counter equals zero, equals +//! the period, or when a sync in is received. +//! * Timers can be configured to listen to sync events from different sources such as other timers +//! or external sync inputs. More information in [`crate::mcpwm::sync`]. #![cfg_attr( mcpwm_swsync_can_propagate, - doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." + doc = "\n * **Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." )] #![cfg_attr( not(mcpwm_swsync_can_propagate), - doc = "**Note:** Software triggered sync events do not propagate to other timers on this chip." + doc = "\n * **Note:** Software triggered sync events do not propagate to other timers on this chip." )] use core::marker::PhantomData; @@ -52,16 +52,6 @@ pub enum TimerEvent { TimerEqualPeriod, } -impl From for Event { - fn from(value: TimerEvent) -> Self { - match value { - TimerEvent::TimerStop => Event::TimerStop, - TimerEvent::TimerEqualZero => Event::TimerEqualZero, - TimerEvent::TimerEqualPeriod => Event::TimerEqualPeriod, - } - } -} - /// A MCPWM timer /// /// Every timer of a particular [`MCPWM`](super::McPwm) peripheral can be used @@ -93,11 +83,20 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { timer } - /// Start the given timer with the provided configuration + /// Start the timer with the current configuration. + /// Refer to the documentation of [`StopCondition`] and + /// [`TimerClockConfig`] for more details on the + /// configuration of the timer. pub fn start(&mut self) { // set timer to run with a stop condition let stop_condition = self.config.stop_condition as u8; let mode = self.config.mode as u8; + + // Update sync counter direction and phase according to the configuration + // Since `Timer::set_counter` can change the phase and counter direction. + self.set_sync_counter_direction(self.config.sync_direction); + self.set_sync_phase(self.config.sync_phase); + self.cfg1().write(|w| unsafe { w.start().bits(stop_condition); w.mod_().bits(mode) @@ -120,9 +119,37 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { /// If your [`PeriodUpdatingMethod`] is set to [`PeriodUpdatingMethod::Immediately`] /// and if your new period is smaller than the current counter value as this will cause weird /// behavior. - pub fn set_config(&mut self, config: TimerClockConfig) { + /// + /// ### Config Constraints + /// The valid range for phase depends on the timer configuration: + /// - When the timer is in [`PwmWorkingMode::UpDown`] mode: + /// - The valid range for phase is `[0, period]` when the sync direction is + /// [`CounterDirection::Increasing`]. + /// - The valid range for phase is `[1, period+1]` when the sync direction is + /// [`CounterDirection::Decreasing`]. + /// - The valid range for phase is `[0, period+1]` when the timer is in another + /// [`PwmWorkingMode`]. + pub fn apply_config(&mut self, config: TimerClockConfig) -> Result<(), ConfigError> { + // Check for valid phase range + if config.sync_phase > config.period.saturating_add(1) { + return Err(ConfigError::InvalidPhaseRange); + } + + if config.mode == PwmWorkingMode::UpDown { + match config.sync_direction { + CounterDirection::Increasing if config.sync_phase > config.period => { + return Err(ConfigError::InvalidPhaseRange); + } + CounterDirection::Decreasing if config.sync_phase == 0 => { + return Err(ConfigError::InvalidPhaseRange); + } + _ => {} + } + } + self.config = config; self.configure(); + Ok(()) } /// Set the timer counter to the provided value @@ -322,11 +349,33 @@ pub enum SyncOutSelect { SyncWhenEqualPeriod = 2, } +/// Sync error for an invalid sync configuration +#[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum ConfigError { + /// Error is thrown when the provided phase is out of range for the timer configuration + InvalidPhaseRange, +} + +impl core::error::Error for ConfigError {} + +impl core::fmt::Display for ConfigError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + ConfigError::InvalidPhaseRange => write!( + f, + "Provided phase is out of range for the current timer configuration" + ), + } + } +} + /// Clock configuration of a MCPWM timer /// /// Use [`PeripheralClockConfig::timer_clock_with_prescaler`](super::PeripheralClockConfig::timer_clock_with_prescaler) or /// [`PeripheralClockConfig::timer_clock_with_frequency`](super::PeripheralClockConfig::timer_clock_with_frequency) to it. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TimerClockConfig { frequency: Rate, @@ -361,9 +410,9 @@ impl TimerClockConfig { period_updating_method: PeriodUpdatingMethod::Immediately, stop_condition: StopCondition::RunContinuously, mode, - sync_out: SyncOutSelect::SyncIn, sync_phase: 0, sync_direction: CounterDirection::Increasing, + sync_out: SyncOutSelect::SyncIn, } } @@ -398,49 +447,50 @@ impl TimerClockConfig { period_updating_method: PeriodUpdatingMethod::Immediately, stop_condition: StopCondition::RunContinuously, mode, - sync_out: SyncOutSelect::SyncIn, sync_phase: 0, sync_direction: CounterDirection::Increasing, + sync_out: SyncOutSelect::SyncIn, }) } - /// Default configuration for the timer with the provided clock configuration - pub(super) fn default(clock: &PeripheralClockConfig) -> Self { - Self::with_prescaler(clock, u16::MAX, PwmWorkingMode::Increase, 0) + /// Set the sync out selection for the timer. Refer to how sync events are + /// handled in the [`Timer`] documentation. + pub fn with_sync_out(self, sync_out: SyncOutSelect) -> Self { + Self { sync_out, ..self } } - /// Set the method for updating the PWM period - pub fn with_period_updating_method(self, method: PeriodUpdatingMethod) -> Self { + /// Set the sync phase for the timer. Refer to how sync events are + /// handled in the [`Timer`] documentation. + pub fn with_phase(self, phase: u16) -> Self { Self { - period_updating_method: method, + sync_phase: phase, ..self } } - /// Sets the stop timer conditions - pub fn with_stop_condition(self, condition: StopCondition) -> Self { + /// Set the sync counter direction for the timer. Refer to how sync events are + /// handled in the [`Timer`] documentation. + pub fn with_direction(self, direction: CounterDirection) -> Self { Self { - stop_condition: condition, + sync_direction: direction, ..self } } - /// Set sync out selection - pub fn with_sync_out_selection(self, sync_out: SyncOutSelect) -> Self { - Self { sync_out, ..self } - } - - /// Sets the counter direction when the timer receives a sync event in up-down mode - pub fn with_sync_direction(self, direction: CounterDirection) -> Self { + /// Set the method for updating the PWM period + pub fn with_period_updating_method(self, method: PeriodUpdatingMethod) -> Self { Self { - sync_direction: direction, + period_updating_method: method, ..self } } - /// Sets the sync phase for the timer - pub fn with_sync_phase(self, sync_phase: u16) -> Self { - Self { sync_phase, ..self } + /// Sets the stop timer conditions + pub fn with_stop_condition(self, condition: StopCondition) -> Self { + Self { + stop_condition: condition, + ..self + } } /// Get the timer clock frequency. @@ -450,6 +500,11 @@ impl TimerClockConfig { pub fn frequency(&self) -> Rate { self.frequency } + + /// Default configuration for the timer with the provided clock configuration + pub(super) fn default(clock: &PeripheralClockConfig) -> Self { + Self::with_prescaler(clock, u16::MAX, PwmWorkingMode::Increase, 0) + } } /// Method for updating the PWM period @@ -475,11 +530,11 @@ pub enum PeriodUpdatingMethod { pub enum StopCondition { /// Defines to start the timer now and run till [`Timer::stop`] is called. RunContinuously = 2, - /// Defines to start the timer now and run till the - /// next time the timers counts equal zeros + /// Defines to start the timer now and run till + /// the counter equals zero StopAtZero = 3, - /// Defines to start the timer now and run till the - /// next time the timers counts equals period + /// Defines to start the timer now and run till + /// the counter equals period StopAtPeriod = 4, } @@ -505,6 +560,15 @@ pub enum PwmWorkingMode { UpDown = 3, } +impl From for CounterDirection { + fn from(bit: bool) -> Self { + match bit { + false => CounterDirection::Increasing, + true => CounterDirection::Decreasing, + } + } +} + /// The direction the timer counter is changing #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(u8)] @@ -515,11 +579,12 @@ pub enum CounterDirection { Decreasing = 1, } -impl From for CounterDirection { - fn from(bit: bool) -> Self { - match bit { - false => CounterDirection::Increasing, - true => CounterDirection::Decreasing, +impl From for Event { + fn from(value: TimerEvent) -> Self { + match value { + TimerEvent::TimerStop => Event::TimerStop, + TimerEvent::TimerEqualZero => Event::TimerEqualZero, + TimerEvent::TimerEqualPeriod => Event::TimerEqualPeriod, } } } From 5a5290291442b43c31b4cfd85a3970f359bebb7d Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:20:22 -0600 Subject: [PATCH 35/37] Cleaned up capture Why was I making a capture channel creator seems a bit redundent. --- esp-hal/src/mcpwm/capture.rs | 54 ++------ esp-hal/src/mcpwm/mod.rs | 18 ++- esp-hal/src/mcpwm/sync.rs | 4 +- hil-test/src/bin/misc_drivers.rs | 217 +++++++++++++++++++++++++++++++ 4 files changed, 241 insertions(+), 52 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index 9f81bf95169..d183ef05f33 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -42,18 +42,15 @@ //! let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(__mcpwm_freq__))?; //! let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg); //! -//! // capture rising edges -//! let capture_cfg = CaptureChannelConfig::default().with_capture_mode(CaptureMode::RisingEdge); -//! //! // initialize capture timer //! let cap_timer_cfg = CaptureTimerConfig::default(); //! mcpwm.capture_timer.set_config(cap_timer_cfg); //! mcpwm.capture_timer.start(); //! -//! // create capture channel with given config and `pin` -//! let mut capture = mcpwm.capture0.configure(capture_cfg).with_signal_input(pin); +//! // create capture channel with a `pin` and rising edge capture mode +//! let mut capture = mcpwm.capture0.with_signal_input(pin); //! capture.set_enable(true); -//! capture.listen(); +//! capture.listen(CaptureMode::RisingEdge); //! //! critical_section::with(|cs| CAP0.borrow_ref_mut(cs).replace(capture)); //! @@ -233,7 +230,6 @@ impl CaptureEvent { // Hash cannot be implemented for CaptureMode pub struct CaptureChannelConfig { invert: bool, - capture_mode: CaptureMode, prescaler: u8, } @@ -242,13 +238,7 @@ impl CaptureChannelConfig { pub fn with_invert(self, invert: bool) -> Self { Self { invert, ..self } } - /// Sets the capture mode for the config - pub fn with_capture_mode(self, capture_mode: CaptureMode) -> Self { - Self { - capture_mode, - ..self - } - } + /// Sets the prescaler for the config pub fn with_prescaler(self, prescaler: u8) -> Self { Self { prescaler, ..self } @@ -259,32 +249,11 @@ impl Default for CaptureChannelConfig { fn default() -> Self { Self { invert: false, - capture_mode: CaptureMode::None, prescaler: 0, } } } -/// Capture channel creator -pub struct CaptureChannelCreator<'d, const CHAN: u8, PWM: Instance> { - phantom: PhantomData<&'d PWM>, - _guard: PeripheralGuard, -} - -impl<'d, const CHAN: u8, PWM: Instance> CaptureChannelCreator<'d, CHAN, PWM> { - pub(super) fn new(guard: PeripheralGuard) -> Self { - Self { - phantom: PhantomData, - _guard: guard, - } - } - - /// Configure a new capture channel from a config - pub fn configure(self, config: CaptureChannelConfig) -> CaptureChannel<'d, CHAN, PWM> { - CaptureChannel::new(self._guard, config) - } -} - /// A MCPWM Capture Channel /// /// The MCPWM Capture Channel has the following functions: @@ -311,7 +280,6 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { pub(super) fn configure(&mut self, config: CaptureChannelConfig) { Self::cfg().modify(|_, w| { - w.mode().variant(config.capture_mode); w.in_invert().variant(config.invert); unsafe { w.prescale().bits(config.prescaler) } }); @@ -350,17 +318,23 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// Sets the capture channel to listen to captures on specific edge events /// This channel can listen to Falling, and/or Rising edges on any of the GPIO pins. + /// Using [`CaptureMode::None`] is the same as calling [`CaptureChannel::unlisten`] and will + /// stop listening to any events on this channel. #[instability::unstable] - pub fn listen(&mut self) { + pub fn listen(&mut self, capture_mode: CaptureMode) { + Self::cfg().modify(|_, w| w.mode().variant(capture_mode)); + let info = PWM::info(); - info.enable_listen::(EnumSet::only(Event::Capture), true); + info.enable_listen::( + EnumSet::only(Event::Capture), + capture_mode != CaptureMode::None, + ); } /// Stops listening to events on this channel #[instability::unstable] pub fn unlisten(&mut self) { - let info = PWM::info(); - info.enable_listen::(EnumSet::only(Event::Capture), false); + self.listen(CaptureMode::None); } /// If the interrupt was set for this channel diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index cc80170fc38..eade38314b3 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -117,7 +117,7 @@ use paste::paste; #[cfg(soc_has_mcpwm0)] use crate::mcpwm::{ - capture::{CaptureChannelCreator, CaptureTimer}, + capture::{CaptureChannel, CaptureTimer}, operator::Operator, sync::SyncLine, timer::Timer, @@ -125,6 +125,7 @@ use crate::mcpwm::{ use crate::{ gpio::{InputSignal, OutputSignal}, interrupt::{self, InterruptHandler}, + mcpwm::capture::CaptureChannelConfig, pac, private::DropGuard, soc::clocks::{self, ClockTree}, @@ -150,9 +151,6 @@ for_each_mcpwm!( /// MCPWM Driver for MCPWM<$id> pub type McPwm<'d> = super::McPwm<'d, MCPWMPeripheral<'d>>; - /// Capture channel creator for MCPWM<$id> - pub type CaptureChannelCreator<'d, const NUM: u8> = - capture::CaptureChannelCreator<'d, NUM, MCPWMPeripheral<'d>>; /// Capture Channel for MCPWM<$id> pub type CaptureChannel<'d, const NUM: u8> = capture::CaptureChannel<'d, NUM, MCPWMPeripheral<'d>>; @@ -197,11 +195,11 @@ pub struct McPwm<'d, PWM: Instance> { pub operator2: Operator<'d, 2, PWM>, /// Capture0 - pub capture0: CaptureChannelCreator<'d, 0, PWM>, + pub capture0: CaptureChannel<'d, 0, PWM>, /// Capture1 - pub capture1: CaptureChannelCreator<'d, 1, PWM>, + pub capture1: CaptureChannel<'d, 1, PWM>, /// Capture2 - pub capture2: CaptureChannelCreator<'d, 2, PWM>, + pub capture2: CaptureChannel<'d, 2, PWM>, /// Sync0 pub sync0: SyncLine<'d, 0, PWM>, @@ -235,9 +233,9 @@ impl<'d, PWM: Instance> McPwm<'d, PWM> { operator1: Operator::new(guard.clone()), operator2: Operator::new(guard.clone()), capture_timer: CaptureTimer::new(guard.clone()), - capture0: CaptureChannelCreator::new(guard.clone()), - capture1: CaptureChannelCreator::new(guard.clone()), - capture2: CaptureChannelCreator::new(guard), + capture0: CaptureChannel::new(guard.clone(), CaptureChannelConfig::default()), + capture1: CaptureChannel::new(guard.clone(), CaptureChannelConfig::default()), + capture2: CaptureChannel::new(guard, CaptureChannelConfig::default()), sync0: SyncLine::new(), sync1: SyncLine::new(), sync2: SyncLine::new(), diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index f62f2ed6b83..a5e1d9aded0 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -181,13 +181,13 @@ impl From for SyncInSelect { 0 => SyncInSelect::SyncLine0, 1 => SyncInSelect::SyncLine1, 2 => SyncInSelect::SyncLine2, - _ => panic!("Invalid sync line"), + _ => unreachable!(), }, SyncKind::TimerSyncOut(timer) => match timer { 0 => SyncInSelect::Timer0SyncOut, 1 => SyncInSelect::Timer1SyncOut, 2 => SyncInSelect::Timer2SyncOut, - _ => panic!("Invalid timer for sync out"), + _ => unreachable!(), }, } } diff --git a/hil-test/src/bin/misc_drivers.rs b/hil-test/src/bin/misc_drivers.rs index 0666efdaddc..d29566c784f 100644 --- a/hil-test/src/bin/misc_drivers.rs +++ b/hil-test/src/bin/misc_drivers.rs @@ -773,3 +773,220 @@ mod twai { } } } + +#[cfg(mcpwm_driver_supported)] +#[embedded_test::tests(default_timeout = 3)] +mod mcpwm { + use esp_hal::{ + self, + delay::Delay, + gpio::{AnyPin, Level, Output, OutputConfig, Pin}, + mcpwm::{ + McPwm, + PeripheralClockConfig, + capture::{CaptureEdge, CaptureMode, CaptureTimerConfig}, + mcpwm0, + timer::{CounterDirection, PwmWorkingMode, SyncOutSelect}, + }, + time::Rate, + }; + + struct Context<'d> { + mcpwm: mcpwm0::McPwm<'static>, + input: AnyPin<'d>, + output: AnyPin<'d>, + delay: Delay, + clock_cfg: PeripheralClockConfig, + } + #[init] + fn init() -> Context<'static> { + let peripherals = esp_hal::init(esp_hal::Config::default()); + + let (din, dout) = hil_test::common_test_pins!(peripherals); + + let din = din.degrade(); + let dout = dout.degrade(); + + let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(1)); + assert!(clock_cfg.is_ok(), "Failed to set MCPWM clock frequency"); + let clock_cfg = clock_cfg.unwrap(); + + Context { + mcpwm: McPwm::new(peripherals.MCPWM0, clock_cfg), + input: din, + output: dout, + delay: Delay::new(), + clock_cfg, + } + } + + #[test] + fn test_capture_any_edge(mut ctx: Context<'static>) { + // Setup capture 0 to to capture either falling or rising edges + let mut output = Output::new(ctx.output, Level::Low, OutputConfig::default()); + + ctx.mcpwm.capture_timer.start(); + let mut capture = ctx.mcpwm.capture0.with_signal_input(ctx.input); + capture.set_enable(true); + capture.listen(CaptureMode::AnyEdge); + + output.set_high(); + ctx.delay.delay_micros(1); + assert_eq!(CaptureEdge::Rising, capture.events().edge()); + + output.set_low(); + ctx.delay.delay_micros(1); + assert_eq!(CaptureEdge::Falling, capture.events().edge()); + + output.set_high(); + ctx.delay.delay_micros(1); + assert_eq!(CaptureEdge::Rising, capture.events().edge()); + + output.set_low(); + ctx.delay.delay_micros(1); + assert_eq!(CaptureEdge::Falling, capture.events().edge()); + } + + #[test] + fn test_timer_set_counter(ctx: Context<'static>) { + // create timer but don't start it + let mut timer = ctx.mcpwm.timer0; + + timer.set_counter(0, CounterDirection::Increasing); + ctx.delay.delay_micros(1); + assert_eq!((0, CounterDirection::Increasing), timer.status()); + + timer.set_counter(1234, CounterDirection::Increasing); + ctx.delay.delay_micros(1); + assert_eq!((1234, CounterDirection::Increasing), timer.status()); + + timer.set_counter(5553, CounterDirection::Increasing); + ctx.delay.delay_micros(1); + assert_eq!((5553, CounterDirection::Increasing), timer.status()); + } + + #[test] + fn test_timer_sync_phase_from_sync_line(mut ctx: Context<'static>) { + // setup sync line to be controlled by output pin + let mut output = Output::new(ctx.output, Level::Low, OutputConfig::default()); + ctx.mcpwm.sync0.set_signal(ctx.input); + + let timer_cfg = ctx + .clock_cfg + .timer_clock_with_prescaler(u16::MAX, PwmWorkingMode::Increase, 0) + .with_phase(25000); + + // create timer but don't start it + let mut timer = ctx.mcpwm.timer0; + timer.set_sync_in(&ctx.mcpwm.sync0); + timer.set_counter(0, CounterDirection::Increasing); + assert!(timer.apply_config(timer_cfg).is_ok()); + + // before sync + assert_eq!(0, timer.status().0); + + // sync the timer + output.set_high(); + ctx.delay.delay_micros(1); + output.set_low(); + ctx.delay.delay_micros(1); + assert_eq!(25000, timer.status().0); + + // apply new sync phase + let timer_cfg = timer_cfg.with_phase(12345); + assert!(timer.apply_config(timer_cfg).is_ok()); + + // sync the timer + output.set_high(); + ctx.delay.delay_micros(1); + output.set_low(); + ctx.delay.delay_micros(1); + assert_eq!(12345, timer.status().0); + } + + #[test] + fn test_cap_timer_sync_phase_from_sync_line(mut ctx: Context<'static>) { + // setup sync line to be controlled by output pin + let mut output = Output::new(ctx.output, Level::Low, OutputConfig::default()); + ctx.mcpwm.sync0.set_signal(ctx.input); + + let mut cap_timer = ctx.mcpwm.capture_timer; + cap_timer.set_sync_in(&ctx.mcpwm.sync0); + + let mut capture = ctx.mcpwm.capture0; + capture.set_enable(true); + + // before sync initial phase == 0 + capture.trigger_capture(); + ctx.delay.delay_micros(1); + assert_eq!(0, capture.events().time()); + + cap_timer.apply_config(CaptureTimerConfig::default().with_sync_phase(1234)); + + // sync the timer + output.set_high(); + ctx.delay.delay_micros(1); + output.set_low(); + ctx.delay.delay_micros(1); + + // Compare capture phase + capture.trigger_capture(); + ctx.delay.delay_micros(1); + assert_eq!(1234, capture.events().time()); + + // apply a new sync phase + cap_timer.apply_config(CaptureTimerConfig::default().with_sync_phase(5324)); + + // sync the timer + output.set_high(); + ctx.delay.delay_micros(1); + output.set_low(); + ctx.delay.delay_micros(1); + + // Compare capture phase + capture.trigger_capture(); + ctx.delay.delay_micros(1); + assert_eq!(5324, capture.events().time()); + } + + #[test] + fn test_timer_sync_out_propagating_sync(mut ctx: Context<'static>) { + // setup sync line to be controlled by output pin + ctx.mcpwm.sync0.set_signal(ctx.input); + + // Small prescaler to ensure sync will fire often ~ 5uS + let timer0_cfg = ctx + .clock_cfg + .timer_clock_with_prescaler(5, PwmWorkingMode::Increase, 0) + .with_sync_out(SyncOutSelect::SyncWhenEqualPeriod); + + // Create timer0 with sync out and start it + let mut timer0 = ctx.mcpwm.timer0; + assert!(timer0.apply_config(timer0_cfg).is_ok()); + timer0.start(); + + let timer1_cfg = ctx + .clock_cfg + .timer_clock_with_prescaler(u16::MAX, PwmWorkingMode::Increase, 0) + .with_phase(25000); + + // timer 1 listens to sync out of timer 0 + let mut timer1 = ctx.mcpwm.timer1; + assert!(timer1.apply_config(timer1_cfg).is_ok()); + + // before sync + assert_eq!(0, timer0.status().0); + + // timer 1 should be synced from timer 0 + timer1.set_sync_in(&timer0.sync_out); + ctx.delay.delay_millis(1); + assert_eq!(25000, timer1.status().0); + + let timer1_cfg = timer1_cfg.with_phase(12345); + assert!(timer1.apply_config(timer1_cfg).is_ok()); + + // timer 1 should be synced from timer 0 with new phase + ctx.delay.delay_millis(1); + assert_eq!(12345, timer1.status().0); + } +} From 9eb5b0431a533550561f86870d57275641c75989 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Mon, 1 Jun 2026 10:56:45 -0600 Subject: [PATCH 36/37] Removed generics --- esp-hal/src/mcpwm/capture.rs | 125 ++++++++++++----------- esp-hal/src/mcpwm/mod.rs | 187 +++++++++++++++------------------- esp-hal/src/mcpwm/operator.rs | 153 ++++++++++++++++------------ esp-hal/src/mcpwm/sync.rs | 145 +++++++------------------- esp-hal/src/mcpwm/timer.rs | 138 +++++++++++++------------ 5 files changed, 351 insertions(+), 397 deletions(-) diff --git a/esp-hal/src/mcpwm/capture.rs b/esp-hal/src/mcpwm/capture.rs index d183ef05f33..3586373cd2a 100644 --- a/esp-hal/src/mcpwm/capture.rs +++ b/esp-hal/src/mcpwm/capture.rs @@ -70,6 +70,7 @@ //! }); //! } //! ``` + use core::marker::PhantomData; use enumset::EnumSet; @@ -81,11 +82,7 @@ pub use crate::pac::mcpwm0::{ }; use crate::{ gpio::interconnect::PeripheralInput, - mcpwm::{ - Instance, - PwmClockGuard, - sync::{SyncInSelect, SyncSource}, - }, + mcpwm::{Info, PwmClockGuard, sync::SyncKind}, pac, }; @@ -120,18 +117,20 @@ impl Default for CaptureTimerConfig { /// to the phase value set in [`CaptureTimerConfig`]. /// /// **Note:** This timer always counts up. -pub struct CaptureTimer<'d, PWM: Instance> { - phantom: PhantomData<&'d PWM>, +pub struct CaptureTimer<'d> { + mcpwm_info: &'static Info, + _phantom: PhantomData<&'d ()>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } -impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { - pub(super) fn new(guard: PeripheralGuard) -> Self { +impl<'d> CaptureTimer<'d> { + pub(super) fn new(guard: PeripheralGuard, mcpwm_info: &'static Info) -> Self { Self { - phantom: PhantomData, + mcpwm_info, + _phantom: PhantomData, _guard: guard, - _pwm_clock_guard: PwmClockGuard::new::(), + _pwm_clock_guard: PwmClockGuard::new(mcpwm_info), } } @@ -161,44 +160,35 @@ impl<'d, PWM: Instance> CaptureTimer<'d, PWM> { /// Triggers a software sync event on the capture timer. /// Refer to how sync events are handled in the [`CaptureTimer`] documentation. pub fn trigger_sync(&mut self) { - Self::cfg().modify(|_r, w| w.cap_sync_sw().set_bit()); + self.cfg().modify(|_r, w| w.cap_sync_sw().set_bit()); } /// Sets the capture timers sync source. Refer to how sync events are /// handled in the [`CaptureTimer`] documentation. - pub fn set_sync_in(&mut self, sync_source: &impl SyncSource) { - let sync_in = sync_source.get_kind().into(); - self.set_sync_in_select(sync_in); - } - - /// Clears the sync in - pub fn clear_sync_in(&mut self) { - self.set_sync_in_select(SyncInSelect::None); + pub fn set_sync_in(&mut self, sync_sel: SyncKind) { + // SAFETY: Only CAP_TIMER_CFG accessed; unique per PWM instance + self.cfg().modify(|_r, w| { + w.cap_synci_en().bit(sync_sel != SyncKind::None); + unsafe { w.cap_synci_sel().bits(sync_sel as u8) } + }); } fn set_enable(&mut self, enable: bool) { - Self::cfg().modify(|_r, w| w.cap_timer_en().bit(enable)); + self.cfg().modify(|_r, w| w.cap_timer_en().bit(enable)); } fn set_sync_phase(&mut self, sync_phase: u32) { - Self::phase().write(|w| unsafe { w.cap_phase().bits(sync_phase) }); - } - - fn set_sync_in_select(&mut self, sync_sel: SyncInSelect) { - // SAFETY: Only CAP_TIMER_CFG accessed; unique per PWM instance - Self::cfg().modify(|_r, w| { - w.cap_synci_en().bit(sync_sel != SyncInSelect::None); - unsafe { w.cap_synci_sel().bits(sync_sel as u8) } - }); + self.phase() + .write(|w| unsafe { w.cap_phase().bits(sync_phase) }); } - fn cfg() -> &'static crate::Reg { - let info = PWM::info(); + fn cfg(&mut self) -> &'d crate::Reg { + let info = self.mcpwm_info; info.regs().cap_timer_cfg() } - fn phase() -> &'static crate::Reg { - let info = PWM::info(); + fn phase(&mut self) -> &'d crate::Reg { + let info = self.mcpwm_info; info.regs().cap_timer_phase() } } @@ -261,25 +251,34 @@ impl Default for CaptureChannelConfig { /// * Setting the capture input GPIO pin /// * Whether to trigger capture events on rising and/or falling edges /// * Read the last capture edge, and the last capture time -pub struct CaptureChannel<'d, const CHAN: u8, PWM: Instance> { - phantom: PhantomData<&'d PWM>, +pub struct CaptureChannel<'d> { + mcpwm_info: &'static Info, + number: u8, + _phantom: PhantomData<&'d ()>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } -impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { - pub(super) fn new(guard: PeripheralGuard, config: CaptureChannelConfig) -> Self { +impl<'d> CaptureChannel<'d> { + pub(super) fn new( + guard: PeripheralGuard, + mcpwm_info: &'static Info, + number: u8, + config: CaptureChannelConfig, + ) -> Self { let mut channel = Self { - phantom: PhantomData, + mcpwm_info, + number, + _phantom: PhantomData, _guard: guard, - _pwm_clock_guard: PwmClockGuard::new::(), + _pwm_clock_guard: PwmClockGuard::new(mcpwm_info), }; channel.configure(config); channel } pub(super) fn configure(&mut self, config: CaptureChannelConfig) { - Self::cfg().modify(|_, w| { + self.cfg().modify(|_, w| { w.in_invert().variant(config.invert); unsafe { w.prescale().bits(config.prescaler) } }); @@ -287,8 +286,8 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// Assign the input signal for the capture pub fn with_signal_input<'a>(self, input: impl PeripheralInput<'a>) -> Self { - let info = PWM::info(); - let input_signal = info.capture_input_signal::(); + let info = self.mcpwm_info; + let input_signal = info.capture_input_signal(self.number); if input_signal as usize <= property!("gpio.input_signal_max") { let source = input.into(); @@ -303,7 +302,7 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// Enable or disables this capture channel pub fn set_enable(&mut self, enable: bool) { - Self::cfg().modify(|_, w| w.en().variant(enable)); + self.cfg().modify(|_, w| w.en().variant(enable)); } /// Set the config @@ -313,7 +312,7 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// Triggers a software capture on the current capture channel pub fn trigger_capture(&mut self) { - Self::cfg().modify(|_, w| w.sw().set_bit()); + self.cfg().modify(|_, w| w.sw().set_bit()); } /// Sets the capture channel to listen to captures on specific edge events @@ -322,10 +321,11 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// stop listening to any events on this channel. #[instability::unstable] pub fn listen(&mut self, capture_mode: CaptureMode) { - Self::cfg().modify(|_, w| w.mode().variant(capture_mode)); + self.cfg().modify(|_, w| w.mode().variant(capture_mode)); - let info = PWM::info(); - info.enable_listen::( + let info = self.mcpwm_info; + info.enable_listen( + self.number, EnumSet::only(Event::Capture), capture_mode != CaptureMode::None, ); @@ -340,28 +340,37 @@ impl<'d, const CHAN: u8, PWM: Instance> CaptureChannel<'d, CHAN, PWM> { /// If the interrupt was set for this channel #[instability::unstable] pub fn is_interrupt_set(&self) -> bool { - let info = PWM::info(); - info.interrupt_set::(Event::Capture) + let info = self.mcpwm_info; + info.interrupt_set(self.number, Event::Capture) } /// Clear the interrupt #[instability::unstable] pub fn clear_interrupt(&self) { - let info = PWM::info(); - info.clear_interrupt::(Event::Capture); + let info = self.mcpwm_info; + info.clear_interrupt(self.number, Event::Capture); } /// Gets the last captured event #[instability::unstable] pub fn events(&self) -> CaptureEvent { - let info = PWM::info(); - let time = info.regs().cap_ch(CHAN as usize).read().value().bits(); - let edge = info.regs().cap_status().read().cap_edge(CHAN).variant(); + let info = self.mcpwm_info; + let time = info + .regs() + .cap_ch(self.number as usize) + .read() + .value() + .bits(); + let edge = info + .regs() + .cap_status() + .read() + .cap_edge(self.number) + .variant(); CaptureEvent { time, edge } } - fn cfg() -> &'static crate::Reg { - let info = PWM::info(); - info.regs().cap_ch_cfg(CHAN as usize) + fn cfg(&mut self) -> &'d crate::Reg { + self.mcpwm_info.regs().cap_ch_cfg(self.number as usize) } } diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index eade38314b3..ab9f3ed711d 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -110,10 +110,7 @@ //! # {after_snippet} //! ``` -use core::marker::PhantomData; - use enumset::{EnumSet, EnumSetType}; -use paste::paste; #[cfg(soc_has_mcpwm0)] use crate::mcpwm::{ @@ -142,77 +139,62 @@ pub mod sync; /// MCPWM timers pub mod timer; -for_each_mcpwm!( - ($id:literal, $inst:ident, $sys:ident) => { - paste! { - /// Provides nice types for public API - pub mod [<$inst:lower>] { - use crate::{mcpwm::*, peripherals::[<$inst>] as MCPWMPeripheral}; - - /// MCPWM Driver for MCPWM<$id> - pub type McPwm<'d> = super::McPwm<'d, MCPWMPeripheral<'d>>; - /// Capture Channel for MCPWM<$id> - pub type CaptureChannel<'d, const NUM: u8> = - capture::CaptureChannel<'d, NUM, MCPWMPeripheral<'d>>; - /// Capture timer for MCPWM<$id> - pub type CaptureTimer<'d> = capture::CaptureTimer<'d, MCPWMPeripheral<'d>>; - /// Timer for MCPWM<$id> - pub type Timer<'d, const NUM: u8> = timer::Timer<'d, NUM, MCPWMPeripheral<'d>>; - /// Operator for MCPWM<$id> - pub type Operator<'d, const NUM: u8> = operator::Operator<'d, NUM, MCPWMPeripheral<'d>>; - /// Pwm Pin for MCPWM<$id> - pub type PwmPin<'d, const NUM: u8, const IS_A: bool> = - operator::PwmPin<'d, MCPWMPeripheral<'d>, NUM, IS_A>; - /// Linked Pins for MCPWM<$id> - pub type LinkedPins<'d, const NUM: u8> = operator::LinkedPins<'d, MCPWMPeripheral<'d>, NUM>; - /// Sync source for MCPWM<$id> - pub type SyncSource<'d> = dyn sync::SyncSource> + 'd; - } - } - }; -); +crate::any_peripheral! { + /// Any MCPWM peripheral. + pub peripheral AnyMcPwm<'d> { + #[cfg(soc_has_mcpwm0)] + Mcpwm0(crate::peripherals::MCPWM0<'d>), + #[cfg(soc_has_mcpwm1)] + Mcpwm1(crate::peripherals::MCPWM1<'d>), + } +} + +impl Instance for AnyMcPwm<'_> { + fn info(&self) -> &'static Info { + any::delegate!(self, mcpwm => { mcpwm.info() }) + } +} /// The MCPWM peripheral #[non_exhaustive] -pub struct McPwm<'d, PWM: Instance> { - _phantom: PhantomData<&'d PWM>, - _instance: PWM, +pub struct McPwm<'d> { + mcpwm: AnyMcPwm<'d>, /// Timer0 - pub timer0: Timer<'d, 0, PWM>, + pub timer0: Timer<'d>, /// Timer1 - pub timer1: Timer<'d, 1, PWM>, + pub timer1: Timer<'d>, /// Timer2 - pub timer2: Timer<'d, 2, PWM>, + pub timer2: Timer<'d>, /// Capture Timer - pub capture_timer: CaptureTimer<'d, PWM>, + pub capture_timer: CaptureTimer<'d>, /// Operator0 - pub operator0: Operator<'d, 0, PWM>, + pub operator0: Operator<'d>, /// Operator1 - pub operator1: Operator<'d, 1, PWM>, + pub operator1: Operator<'d>, /// Operator2 - pub operator2: Operator<'d, 2, PWM>, + pub operator2: Operator<'d>, /// Capture0 - pub capture0: CaptureChannel<'d, 0, PWM>, + pub capture0: CaptureChannel<'d>, /// Capture1 - pub capture1: CaptureChannel<'d, 1, PWM>, + pub capture1: CaptureChannel<'d>, /// Capture2 - pub capture2: CaptureChannel<'d, 2, PWM>, - - /// Sync0 - pub sync0: SyncLine<'d, 0, PWM>, - /// Sync1 - pub sync1: SyncLine<'d, 1, PWM>, - /// Sync2 - pub sync2: SyncLine<'d, 2, PWM>, + pub capture2: CaptureChannel<'d>, + + /// Sync line 0 + pub sync0: SyncLine, + /// Sync line 1 + pub sync1: SyncLine, + /// Sync line 2 + pub sync2: SyncLine, } -impl<'d, PWM: Instance> McPwm<'d, PWM> { +impl<'d> McPwm<'d> { /// Create a new instance generics - pub fn new(_peripheral: PWM, peripheral_clock: PeripheralClockConfig) -> Self { - let info = PWM::info(); + pub fn new(mcpwm: AnyMcPwm<'d>, peripheral_clock: PeripheralClockConfig) -> Self { + let info = mcpwm.info(); let guard = PeripheralGuard::new(info.peripheral()); // set prescaler for timer (0-2) @@ -223,22 +205,22 @@ impl<'d, PWM: Instance> McPwm<'d, PWM> { // enable clock info.regs().clk().write(|w| w.en().set_bit()); + let info = mcpwm.info(); Self { - _phantom: PhantomData, - _instance: _peripheral, - timer0: Timer::new(guard.clone(), &peripheral_clock), - timer1: Timer::new(guard.clone(), &peripheral_clock), - timer2: Timer::new(guard.clone(), &peripheral_clock), - operator0: Operator::new(guard.clone()), - operator1: Operator::new(guard.clone()), - operator2: Operator::new(guard.clone()), - capture_timer: CaptureTimer::new(guard.clone()), - capture0: CaptureChannel::new(guard.clone(), CaptureChannelConfig::default()), - capture1: CaptureChannel::new(guard.clone(), CaptureChannelConfig::default()), - capture2: CaptureChannel::new(guard, CaptureChannelConfig::default()), - sync0: SyncLine::new(), - sync1: SyncLine::new(), - sync2: SyncLine::new(), + mcpwm, + timer0: Timer::new(guard.clone(), info, 0, &peripheral_clock), + timer1: Timer::new(guard.clone(), info, 1, &peripheral_clock), + timer2: Timer::new(guard.clone(), info, 2, &peripheral_clock), + operator0: Operator::new(guard.clone(), 0, info), + operator1: Operator::new(guard.clone(), 1, info), + operator2: Operator::new(guard.clone(), 2, info), + capture_timer: CaptureTimer::new(guard.clone(), info), + capture0: CaptureChannel::new(guard.clone(), info, 0, CaptureChannelConfig::default()), + capture1: CaptureChannel::new(guard.clone(), info, 1, CaptureChannelConfig::default()), + capture2: CaptureChannel::new(guard, info, 2, CaptureChannelConfig::default()), + sync0: SyncLine::new(0, info), + sync1: SyncLine::new(1, info), + sync2: SyncLine::new(2, info), } } @@ -248,7 +230,7 @@ impl<'d, PWM: Instance> McPwm<'d, PWM> { /// handlers. #[instability::unstable] pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { - let info = PWM::info(); + let info = self.mcpwm.info(); let interrupt = info.interrupt(); for core in crate::system::Cpu::other() { @@ -478,6 +460,13 @@ pub enum Event { Capture, } +/// A peripheral singleton compatible with the MCPWM driver. +pub trait Instance: crate::private::Sealed + any::Degrade { + /// Returns the peripheral data describing this instance. + #[doc(hidden)] + fn info(&self) -> &'static Info; +} + impl Info { /// Returns the register block for this PWM instance. pub fn regs(&self) -> &RegisterBlock { @@ -495,46 +484,46 @@ impl Info { } /// Returns the output signal for operators - pub fn operator_output_signal(&self) -> OutputSignal { - match IS_A { - true => self.operator_a_output[OP as usize], - false => self.operator_b_output[OP as usize], + pub fn operator_output_signal(&self, operator: u8, is_a: bool) -> OutputSignal { + match is_a { + true => self.operator_a_output[operator as usize], + false => self.operator_b_output[operator as usize], } } /// Returns the sync input signal - pub fn sync_input_signal(&self) -> InputSignal { - self.sync_input[SYNC as usize] + pub fn sync_input_signal(&self, sync: u8) -> InputSignal { + self.sync_input[sync as usize] } /// Returns the capture input signal - pub fn capture_input_signal(&self) -> InputSignal { - self.capture_input[CHAN as usize] + pub fn capture_input_signal(&self, chan: u8) -> InputSignal { + self.capture_input[chan as usize] } /// Return if the interrupt for an event is set - pub fn interrupt_set(&self, event: Event) -> bool { + pub fn interrupt_set(&self, unit: u8, event: Event) -> bool { let regs = self.regs(); let int_st = regs.int_st().read(); - dispatch_event_bit!(int_st, event, UNIT) + dispatch_event_bit!(int_st, event, unit) } /// Clear the interrupt for an event on a specific UNIT # - pub fn clear_interrupt(&self, event: Event) { + pub fn clear_interrupt(&self, unit: u8, event: Event) { let regs = self.regs(); regs.int_clr().write(|w| { - dispatch_event_write!(w, event, UNIT, true); + dispatch_event_write!(w, event, unit, true); w }); } /// Enables listening for an event on a specific UNIT # - pub fn enable_listen(&self, events: EnumSet, value: bool) { + pub fn enable_listen(&self, unit: u8, events: EnumSet, value: bool) { let regs = self.regs(); critical_section::with(|_| { regs.int_ena().modify(|_, w| { for event in events { - dispatch_event_write!(w, event, UNIT, value); + dispatch_event_write!(w, event, unit, value); } w }); @@ -550,20 +539,13 @@ impl PartialEq for Info { unsafe impl Sync for Info {} -/// Represents a MCPWM peripheral -pub trait Instance: crate::private::Sealed { - #[doc(hidden)] - /// Returns the peripheral data and state. - fn info() -> &'static Info; -} - // Create an `Instance` impl for each MCPWM peripheral for_each_mcpwm!( ($id:literal, $inst:ident, $sys:ident) => { paste::paste! { impl Instance for crate::peripherals::$inst<'_> { /// Returns peripheral data for MCPWM $id - fn info() -> &'static Info { + fn info(&self) -> &'static Info { static INFO: Info = Info { register_block: crate::peripherals::$inst::regs(), _peripheral: crate::system::Peripheral::$sys, @@ -598,12 +580,11 @@ for_each_mcpwm!( ); #[allow(dead_code)] // Field is seemingly unused but we rely on its Drop impl -struct PwmClockGuard(DropGuard<(), fn(())>); +struct PwmClockGuard(DropGuard); impl PwmClockGuard { - fn instance() -> clocks::McpwmInstance { - let info = PWM::info(); - match info.peripheral() { + fn instance(mcpwm_info: &'static Info) -> clocks::McpwmInstance { + match mcpwm_info.peripheral() { Peripheral::Mcpwm0 => clocks::McpwmInstance::Mcpwm0, #[cfg(soc_has_mcpwm1)] Peripheral::Mcpwm1 => clocks::McpwmInstance::Mcpwm1, @@ -611,18 +592,18 @@ impl PwmClockGuard { } } - pub fn new() -> Self { - ClockTree::with(move |clocks| Self::instance::().request_function_clock(clocks)); + pub fn new(mcpwm_info: &'static Info) -> Self { + ClockTree::with(move |clocks| Self::instance(mcpwm_info).request_function_clock(clocks)); - Self(DropGuard::new((), |_| { - ClockTree::with(move |clocks| Self::instance::().release_function_clock(clocks)); + Self(DropGuard::new(Self::instance(mcpwm_info), move |mcpwm| { + ClockTree::with(move |clocks| mcpwm.release_function_clock(clocks)); })) } } -impl<'d, PWM: Instance + 'd> crate::private::Sealed for McPwm<'d, PWM> {} +impl<'d> crate::private::Sealed for McPwm<'d> {} #[instability::unstable] -impl<'d, PWM: Instance + 'd> crate::interrupt::InterruptConfigurable for McPwm<'d, PWM> { +impl<'d> crate::interrupt::InterruptConfigurable for McPwm<'d> { fn set_interrupt_handler(&mut self, handler: InterruptHandler) { self.set_interrupt_handler(handler); } diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 41e167a80f3..46542cf737b 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -14,7 +14,7 @@ use core::marker::PhantomData; use super::PeripheralGuard; use crate::{ gpio::interconnect::{OutputSignal, PeripheralOutput}, - mcpwm::{Instance, PwmClockGuard, timer::Timer}, + mcpwm::{AnyMcPwm, Info, Instance, PwmClockGuard, timer::Timer}, pac, }; @@ -168,22 +168,23 @@ impl DeadTimeCfg { /// implemented) /// * 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<'d, const OP: u8, PWM> -where - PWM: Instance, -{ - _phantom: PhantomData<&'d PWM>, +pub struct Operator<'d> { + mcpwm_info: &'static Info, + number: u8, + _phantom: PhantomData<&'d ()>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, } -impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { - pub(super) fn new(guard: PeripheralGuard) -> Self { +impl<'d> Operator<'d> { + pub(super) fn new(guard: PeripheralGuard, number: u8, mcpwm_info: &'static Info) -> Self { // NOTE: Writing 3 to timersel does not disable timer reference (hardware limitation) - Operator { + Self { + mcpwm_info, + number, _phantom: PhantomData, _guard: guard, - _pwm_clock_guard: PwmClockGuard::new::(), + _pwm_clock_guard: PwmClockGuard::new(mcpwm_info), } } @@ -191,11 +192,12 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { /// /// ### Note: /// By default TIMER0 is used - pub fn set_timer(&mut self, _timer: &Timer<'d, TIM, PWM>) { + pub fn set_timer(&mut self, timer: &Timer<'d>) { // SAFETY: // We only write to our OPERATORx_TIMERSEL register - let timer_select = unsafe { Self::timesel() }; - timer_select.modify(|_, w| unsafe { w.operator_timersel(OP).bits(TIM) }); + let timer_select = unsafe { self.timesel() }; + timer_select + .modify(|_, w| unsafe { w.operator_timersel(self.number).bits(timer.number()) }); } /// Use the A output with the given pin and configuration @@ -203,8 +205,8 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { self, pin: impl PeripheralOutput<'d>, config: PwmPinConfig, - ) -> PwmPin<'d, PWM, OP, true> { - PwmPin::new(pin, config) + ) -> PwmPin<'d, true> { + PwmPin::new(pin, self.mcpwm_info, self.number, config) } /// Use the B output with the given pin and configuration @@ -212,8 +214,8 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { self, pin: impl PeripheralOutput<'d>, config: PwmPinConfig, - ) -> PwmPin<'d, PWM, OP, false> { - PwmPin::new(pin, config) + ) -> PwmPin<'d, false> { + PwmPin::new(pin, self.mcpwm_info, self.number, config) } /// Use both the A and the B output with the given pins and configurations @@ -223,8 +225,11 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { config_a: PwmPinConfig, pin_b: impl PeripheralOutput<'d>, config_b: PwmPinConfig, - ) -> (PwmPin<'d, PWM, OP, true>, PwmPin<'d, PWM, OP, false>) { - (PwmPin::new(pin_a, config_a), PwmPin::new(pin_b, config_b)) + ) -> (PwmPin<'d, true>, PwmPin<'d, false>) { + ( + PwmPin::new(pin_a, self.mcpwm_info, self.number, config_a), + PwmPin::new(pin_b, self.mcpwm_info, self.number, config_b), + ) } /// Link two pins using the deadtime generator @@ -238,14 +243,22 @@ impl<'d, const OP: u8, PWM: Instance> Operator<'d, OP, PWM> { pin_b: impl PeripheralOutput<'d>, config_b: PwmPinConfig, config_dt: DeadTimeCfg, - ) -> LinkedPins<'d, PWM, OP> { - LinkedPins::new(pin_a, config_a, pin_b, config_b, config_dt) + ) -> LinkedPins<'d> { + LinkedPins::new( + pin_a, + config_a, + pin_b, + config_b, + config_dt, + self.mcpwm_info, + self.number, + ) } /// Unsafe access to the OPERATORx_TIMERSEL register /// Caller must ensure they only write to the bits corresponding to their operator - unsafe fn timesel() -> &'static pac::mcpwm0::OPERATOR_TIMERSEL { - let info = PWM::info(); + unsafe fn timesel(&self) -> &'static pac::mcpwm0::OPERATOR_TIMERSEL { + let info = self.mcpwm_info; info.regs().operator_timersel() } } @@ -282,27 +295,34 @@ impl PwmPinConfig { } /// A pin driven by an MCPWM operator -pub struct PwmPin<'d, PWM: Instance, const OP: u8, const IS_A: bool> { +pub struct PwmPin<'d, const IS_A: bool> { + mcpwm_info: &'static Info, + operator: u8, pin: OutputSignal<'d>, - phantom: PhantomData, _guard: PeripheralGuard, } -impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A> { - fn new(pin: impl PeripheralOutput<'d>, config: PwmPinConfig) -> Self { +impl<'d, const IS_A: bool> PwmPin<'d, IS_A> { + fn new( + pin: impl PeripheralOutput<'d>, + mcpwm_info: &'static Info, + operator: u8, + config: PwmPinConfig, + ) -> Self { let pin = pin.into(); - let info = PWM::info(); + let info = mcpwm_info; let guard = PeripheralGuard::new(info.peripheral()); let mut pin = PwmPin { pin, - phantom: PhantomData, + mcpwm_info, + operator, _guard: guard, }; pin.set_actions(config.actions); pin.set_update_method(config.update_method); - let signal = info.operator_output_signal::(); + let signal = info.operator_output_signal(operator, IS_A); signal.connect_to(&pin.pin); pin.pin.set_output_enable(true); @@ -313,7 +333,7 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A pub fn set_actions(&mut self, value: PwmActions) { // SAFETY: // We only write to our GENx_x register - let ch = unsafe { Self::ch() }; + let ch = unsafe { self.ch() }; let bits = value.0; // SAFETY: @@ -325,7 +345,7 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) { // SAFETY: // We only write to our GENx_x_UPMETHOD register - let ch = unsafe { Self::ch() }; + let ch = unsafe { self.ch() }; let bits = update_method.0; #[cfg(esp32s3)] @@ -348,7 +368,7 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A pub fn set_timestamp(&mut self, value: u16) { // SAFETY: // We only write to our GENx_TSTMP_x register - let ch = unsafe { Self::ch() }; + let ch = unsafe { self.ch() }; #[cfg(esp32s3)] if IS_A { @@ -371,7 +391,7 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A pub fn timestamp(&self) -> u16 { // SAFETY: // We only read to our GENx_TSTMP_x register - let ch = unsafe { Self::ch() }; + let ch = unsafe { self.ch() }; #[cfg(esp32s3)] if IS_A { @@ -392,10 +412,10 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A pub fn period(&self) -> u16 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self - let info = PWM::info(); + let info = self.mcpwm_info; let tim_select = info.regs().operator_timersel().read(); - let tim = match OP { + let tim = match self.operator { 0 => tim_select.operator0_timersel().bits(), 1 => tim_select.operator1_timersel().bits(), 2 => tim_select.operator2_timersel().bits(), @@ -415,23 +435,21 @@ impl<'d, PWM: Instance, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A .bits() } - unsafe fn ch() -> &'static pac::mcpwm0::CH { - let info = PWM::info(); - info.regs().ch(OP as usize) + unsafe fn ch(&self) -> &'d pac::mcpwm0::CH { + // Unsafe since caller needs to ensure there isn't multiple references to the same + // operator + let info = self.mcpwm_info; + info.regs().ch(self.operator as usize) } } /// Implement no error type for the PwmPin because the method are infallible -impl embedded_hal::pwm::ErrorType - for PwmPin<'_, PWM, OP, IS_A> -{ +impl embedded_hal::pwm::ErrorType for PwmPin<'_, IS_A> { type Error = core::convert::Infallible; } /// Implement the trait SetDutyCycle for PwmPin -impl embedded_hal::pwm::SetDutyCycle - for PwmPin<'_, PWM, OP, IS_A> -{ +impl embedded_hal::pwm::SetDutyCycle for PwmPin<'_, IS_A> { /// Get the max duty of the PwmPin fn max_duty_cycle(&self) -> u16 { self.period() @@ -490,30 +508,39 @@ impl embedded_hal::pwm::SetDutyCy /// // pin_b: ------_________-----------_________----- /// # {after_snippet} /// ``` -pub struct LinkedPins<'d, PWM: Instance, const OP: u8> { - pin_a: PwmPin<'d, PWM, OP, true>, - pin_b: PwmPin<'d, PWM, OP, false>, +pub struct LinkedPins<'d> { + mcpwm_info: &'static Info, + operator: u8, + pin_a: PwmPin<'d, true>, + pin_b: PwmPin<'d, false>, } -impl<'d, PWM: Instance, const OP: u8> LinkedPins<'d, PWM, OP> { +impl<'d> LinkedPins<'d> { fn new( pin_a: impl PeripheralOutput<'d>, config_a: PwmPinConfig, pin_b: impl PeripheralOutput<'d>, config_b: PwmPinConfig, config_dt: DeadTimeCfg, + mcpwm_info: &'static Info, + operator: u8, ) -> Self { // setup deadtime config before enabling the pins #[cfg(esp32s3)] - let dt_cfg = unsafe { Self::ch() }.db_cfg(); + let dt_cfg = unsafe { mcpwm_info.regs().ch(operator as usize) }.db_cfg(); #[cfg(not(esp32s3))] - let dt_cfg = unsafe { Self::ch() }.dt_cfg(); + let dt_cfg = unsafe { mcpwm_info.regs().ch(operator as usize) }.dt_cfg(); dt_cfg.write(|w| unsafe { w.bits(config_dt.cfg_reg) }); - let pin_a = PwmPin::new(pin_a, config_a); - let pin_b = PwmPin::new(pin_b, config_b); + let pin_a = PwmPin::new(pin_a, mcpwm_info, operator, config_a); + let pin_b = PwmPin::new(pin_b, mcpwm_info, operator, config_b); - LinkedPins { pin_a, pin_b } + LinkedPins { + pin_a, + pin_b, + mcpwm_info, + operator, + } } /// Configure what actions should be taken on timing events @@ -550,32 +577,32 @@ impl<'d, PWM: Instance, const OP: u8> LinkedPins<'d, PWM, OP> { /// Configure the deadtime generator pub fn set_deadtime_cfg(&mut self, config: DeadTimeCfg) { #[cfg(esp32s3)] - let dt_cfg = unsafe { Self::ch() }.db_cfg(); + let dt_cfg = unsafe { self.ch() }.db_cfg(); #[cfg(not(esp32s3))] - let dt_cfg = unsafe { Self::ch() }.dt_cfg(); + let dt_cfg = unsafe { self.ch() }.dt_cfg(); dt_cfg.write(|w| unsafe { w.bits(config.cfg_reg) }); } /// Set the deadtime generator rising edge delay pub fn set_rising_edge_deadtime(&mut self, dead_time: u16) { #[cfg(esp32s3)] - let dt_red = unsafe { Self::ch() }.db_red_cfg(); + let dt_red = unsafe { self.ch() }.db_red_cfg(); #[cfg(not(esp32s3))] - let dt_red = unsafe { Self::ch() }.dt_red_cfg(); + let dt_red = unsafe { self.ch() }.dt_red_cfg(); dt_red.write(|w| unsafe { w.red().bits(dead_time) }); } /// Set the deadtime generator falling edge delay pub fn set_falling_edge_deadtime(&mut self, dead_time: u16) { #[cfg(esp32s3)] - let dt_fed = unsafe { Self::ch() }.db_fed_cfg(); + let dt_fed = unsafe { self.ch() }.db_fed_cfg(); #[cfg(not(esp32s3))] - let dt_fed = unsafe { Self::ch() }.dt_fed_cfg(); + let dt_fed = unsafe { self.ch() }.dt_fed_cfg(); dt_fed.write(|w| unsafe { w.fed().bits(dead_time) }); } - unsafe fn ch() -> &'static pac::mcpwm0::CH { - let info = PWM::info(); - info.regs().ch(OP as usize) + unsafe fn ch(&self) -> &'d pac::mcpwm0::CH { + let info = self.mcpwm_info; + info.regs().ch(self.operator as usize) } } diff --git a/esp-hal/src/mcpwm/sync.rs b/esp-hal/src/mcpwm/sync.rs index a5e1d9aded0..2ca6e48cc82 100644 --- a/esp-hal/src/mcpwm/sync.rs +++ b/esp-hal/src/mcpwm/sync.rs @@ -56,50 +56,25 @@ //! // set timer2's sync in //! mcpwm.timer2.set_sync_in(&mcpwm.timer1.sync_out); //! ``` -use core::marker::PhantomData; -use crate::{gpio::interconnect::PeripheralInput, mcpwm::Instance}; +use crate::{gpio::interconnect::PeripheralInput, mcpwm::Info}; -#[allow(private_bounds)] -/// Public trait to represent a sync source for a PWM -pub trait SyncSource: InternalSyncSource {} - -/// Sync out created by timers -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct SyncOut<'d, const TIM: u8, PWM: Instance> { - _phantom: PhantomData<&'d PWM>, +/// Sync line for MCPWM +pub struct SyncLine { + number: u8, + mcpwm_info: &'static Info, } -impl<'d, const TIM: u8, PWM: Instance> SyncSource for SyncOut<'d, TIM, PWM> {} -impl<'d, const TIM: u8, PWM: Instance> SyncOut<'d, TIM, PWM> { - pub(super) fn new() -> Self { - Self { - _phantom: PhantomData, - } - } -} - -/// There are only a limited number sync lines for the MCPWM unit -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct SyncLine<'d, const SYNC: u8, PWM: Instance> { - _phantom: PhantomData<&'d PWM>, -} - -impl<'d, const SYNC: u8, PWM: Instance> SyncSource for SyncLine<'d, SYNC, PWM> {} -impl<'d, const SYNC: u8, PWM: Instance> SyncLine<'d, SYNC, PWM> { - pub(super) fn new() -> Self { - Self { - _phantom: PhantomData, - } +impl SyncLine { + pub(crate) fn new(number: u8, mcpwm_info: &'static Info) -> Self { + Self { number, mcpwm_info } } /// Set the input signal for the sync line - pub fn set_signal(&mut self, source: impl PeripheralInput<'d>) { + pub fn set_signal<'d>(&self, source: impl PeripheralInput<'d>) { // configure GPIO matrix → SYNC - let info = PWM::info(); - let signal = info.sync_input_signal::(); + let info = self.mcpwm_info; + let signal = info.sync_input_signal(self.number); if signal as usize <= property!("gpio.input_signal_max") { let source = source.into(); @@ -113,82 +88,40 @@ impl<'d, const SYNC: u8, PWM: Instance> SyncLine<'d, SYNC, PWM> { /// Inverts the input signal from the supplied input source /// If invert is true sync events are triggered on falling edges. /// If invert is false sync events are triggered on rising edges. - pub fn set_invert(&mut self, invert: bool) { - let info = PWM::info(); - info.regs() + pub fn set_invert(&self, invert: bool) { + self.mcpwm_info + .regs() .timer_synci_cfg() - .modify(|_, w| w.external_synci_invert(SYNC).variant(invert)); + .modify(|_, w| w.external_synci_invert(self.number).variant(invert)); } -} - -/// Represents the different types of sync sources -/// Either from sync lines or from timers sync out. -/// -/// Shall only be created from this file -#[derive(Clone, Copy)] -pub(crate) enum SyncKind { - SyncLine(u8), - TimerSyncOut(u8), -} -/// Internal trait to represent which pwm unit and -/// sync out it came from. Broadly represents sync lines, -/// and timer sync out. -pub(crate) trait InternalSyncSource: crate::private::Sealed { - fn get_kind(&self) -> SyncKind; -} - -impl<'d, const TIM: u8, PWM: Instance> crate::private::Sealed for SyncOut<'d, TIM, PWM> {} -impl<'d, const TIM: u8, PWM: Instance> InternalSyncSource for SyncOut<'d, TIM, PWM> { - fn get_kind(&self) -> SyncKind { - SyncKind::TimerSyncOut(TIM) - } -} - -impl<'d, const SYNC: u8, PWM: Instance> crate::private::Sealed for SyncLine<'d, SYNC, PWM> {} -impl<'d, const SYNC: u8, PWM: Instance> InternalSyncSource for SyncLine<'d, SYNC, PWM> { - fn get_kind(&self) -> SyncKind { - SyncKind::SyncLine(SYNC) + /// Get the kind of sync line this is + pub fn kind(&self) -> SyncKind { + match self.number { + 0 => SyncKind::SyncLine0, + 1 => SyncKind::SyncLine1, + 2 => SyncKind::SyncLine2, + _ => unreachable!(), + } } } -/// Values for any of the sync selection registers -/// This is the internal value used by capture timer, and timers +/// Values for any of the sync selection fields in the timer configuration #[repr(u8)] #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub(crate) enum SyncInSelect { - /// Select no sync input for the capture timer - None = 0, - /// Select the timers sync source for a timer's sync out, - Timer0SyncOut = 1, - Timer1SyncOut = 2, - Timer2SyncOut = 3, - /// Select the timers sync source from a sync line - SyncLine0 = 4, - SyncLine1 = 5, - SyncLine2 = 6, -} - -/// Provides a simple way of translating the internal SyncKind to -/// the value for sync selection used in SYNCI_SEL register fields -impl From for SyncInSelect { - fn from(value: SyncKind) -> Self { - match value { - // SAFETY: Const generics ensure TIM and SYNC are valid (0-2) - // Runtime values for line, and timer are only created - // from generic constants - SyncKind::SyncLine(line) => match line { - 0 => SyncInSelect::SyncLine0, - 1 => SyncInSelect::SyncLine1, - 2 => SyncInSelect::SyncLine2, - _ => unreachable!(), - }, - SyncKind::TimerSyncOut(timer) => match timer { - 0 => SyncInSelect::Timer0SyncOut, - 1 => SyncInSelect::Timer1SyncOut, - 2 => SyncInSelect::Timer2SyncOut, - _ => unreachable!(), - }, - } - } +pub enum SyncKind { + /// Select no sync input for the timer + None = 0, + /// Sync out from timer0 + Timer0Sync = 1, + /// Sync out from timer1 + Timer1Sync = 2, + /// Sync out from timer2 + Timer2Sync = 3, + /// Sync line 0 + SyncLine0 = 4, + /// Sync line 1 + SyncLine1 = 5, + /// Sync line 2 + SyncLine2 = 6, } diff --git a/esp-hal/src/mcpwm/timer.rs b/esp-hal/src/mcpwm/timer.rs index d8208adc98f..5b7d6a43208 100644 --- a/esp-hal/src/mcpwm/timer.rs +++ b/esp-hal/src/mcpwm/timer.rs @@ -27,14 +27,7 @@ use enumset::{EnumSet, EnumSetType}; use super::PeripheralGuard; use crate::{ - mcpwm::{ - Event, - FrequencyError, - Instance, - PeripheralClockConfig, - PwmClockGuard, - sync::{SyncInSelect, SyncOut, SyncSource}, - }, + mcpwm::{Event, FrequencyError, Info, PeripheralClockConfig, PwmClockGuard, sync::SyncKind}, pac, time::Rate, }; @@ -57,25 +50,32 @@ pub enum TimerEvent { /// Every timer of a particular [`MCPWM`](super::McPwm) peripheral can be used /// as a timing reference for every /// [`Operator`](super::operator::Operator) of that peripheral -pub struct Timer<'d, const TIM: u8, PWM: Instance> { +pub struct Timer<'d> { /// Sync out for the timer that can be connected to other timers sync in or operators sync in - pub sync_out: SyncOut<'d, TIM, PWM>, - _phantom: PhantomData<&'d PWM>, + number: u8, + mcpwm_info: &'static Info, + _phantom: PhantomData<&'d ()>, _guard: PeripheralGuard, _pwm_clock_guard: PwmClockGuard, config: TimerClockConfig, } -impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { - pub(super) fn new(guard: PeripheralGuard, peripheral_clock: &PeripheralClockConfig) -> Self { +impl<'d> Timer<'d> { + pub(super) fn new( + guard: PeripheralGuard, + mcpwm_info: &'static Info, + number: u8, + peripheral_clock: &PeripheralClockConfig, + ) -> Self { // Default configuration for the timer let config = TimerClockConfig::default(peripheral_clock); let mut timer = Timer { - sync_out: SyncOut::new(), + number, + mcpwm_info, _phantom: PhantomData, _guard: guard, - _pwm_clock_guard: PwmClockGuard::new::(), + _pwm_clock_guard: PwmClockGuard::new(mcpwm_info), config, }; timer.configure(); @@ -175,28 +175,42 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { doc = "**Note:** Software triggered sync events from timers will propagate to their respective sync outputs on this chip." )] pub fn trigger_sync(&mut self) { - // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const - let tmr = unsafe { Self::tmr() }; - tmr.sync().modify(|r, w| w.sw().bit(!r.sw().bit())); + self.sync().modify(|r, w| w.sw().bit(!r.sw().bit())); } /// Read the counter value and counter direction of the timer pub fn status(&self) -> (u16, CounterDirection) { // SAFETY: Only read TIMERx_STATUS; unique per TIM const - let reg = unsafe { Self::tmr() }.status().read(); + let reg = unsafe { self.tmr() }.status().read(); (reg.value().bits(), reg.direction().bit_is_set().into()) } /// Sets the timers sync source. Refer to how sync events are /// handled in the [`Timer`] documentation. - pub fn set_sync_in(&mut self, sync_source: &impl SyncSource) { - let sync_in_sel = sync_source.get_kind().into(); - self.set_sync_in_select(sync_in_sel); + pub fn set_sync_in(&mut self, sync_sel: SyncKind) { + let info = self.mcpwm_info; + + // SAFETY: Only TIMER_SYNCI_CFG and TIMERx_SYNC accessed + info.regs() + .timer_synci_cfg() + .modify(|_r, w| unsafe { w.timer_syncisel(self.number).bits(sync_sel as u8) }); + self.sync() + .modify(|_r, w| w.synci_en().bit(sync_sel != SyncKind::None)); } /// Clears the sync in for the timer and disables sync input pub fn clear_sync_in(&mut self) { - self.set_sync_in_select(SyncInSelect::None); + self.set_sync_in(SyncKind::None); + } + + /// Get the sync out selection for the timer + pub fn get_sync_out(&self) -> SyncKind { + match self.number { + 0 => SyncKind::Timer0Sync, + 1 => SyncKind::Timer1Sync, + 2 => SyncKind::Timer2Sync, + _ => unreachable!(), + } } #[instability::unstable] @@ -212,16 +226,16 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { #[instability::unstable] pub fn interrupts(&self) -> EnumSet { let mut res = EnumSet::new(); - let info = PWM::info(); + let info = self.mcpwm_info; let ints = info.regs().int_st().read(); - if ints.timer_stop(TIM).bit() { + if ints.timer_stop(self.number).bit() { res.insert(TimerEvent::TimerStop); } - if ints.timer_tep(TIM).bit() { + if ints.timer_tep(self.number).bit() { res.insert(TimerEvent::TimerEqualPeriod); } - if ints.timer_tez(TIM).bit() { + if ints.timer_tez(self.number).bit() { res.insert(TimerEvent::TimerEqualZero); } @@ -230,13 +244,13 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { #[instability::unstable] pub fn clear_interrupts(&mut self, events: EnumSet) { - let info = PWM::info(); + let info = self.mcpwm_info; info.regs().int_clr().write(|w| { for event in events { match event { - TimerEvent::TimerStop => w.timer_stop(TIM).bit(true), - TimerEvent::TimerEqualPeriod => w.timer_tep(TIM).bit(true), - TimerEvent::TimerEqualZero => w.timer_tez(TIM).bit(true), + TimerEvent::TimerStop => w.timer_stop(self.number).bit(true), + TimerEvent::TimerEqualPeriod => w.timer_tep(self.number).bit(true), + TimerEvent::TimerEqualZero => w.timer_tez(self.number).bit(true), }; } w @@ -251,6 +265,12 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { .modify(|_r, w| unsafe { w.period().bits(new_period) }); } + /// Get the timer number + #[doc(hidden)] + pub fn number(&self) -> u8 { + self.number + } + fn configure(&mut self) { // write prescaler and period let (prescaler, period, period_updating_method) = ( @@ -272,67 +292,50 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { fn set_sync_phase(&mut self, sync_phase: u16) { // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const - let tmr = unsafe { Self::tmr() }; - tmr.sync() + self.sync() .modify(|_r, w| unsafe { w.phase().bits(sync_phase) }); } fn set_sync_counter_direction(&mut self, direction: CounterDirection) { - // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const - let tmr = unsafe { Self::tmr() }; - tmr.sync() + self.sync() .modify(|_r, w| w.phase_direction().bit(direction as u8 != 0)); } fn set_sync_out_selection(&mut self, sync_out: SyncOutSelect) { - // SAFETY: Only TIMERx_SYNC accessed; unique per TIM const - let timer = unsafe { Self::tmr() }; - timer - .sync() - .modify(|_r, w| unsafe { w.synco_sel().bits(sync_out as u8) }); - } - - fn set_sync_in_select(&mut self, sync_sel: SyncInSelect) { - let info = PWM::info(); - - // SAFETY: Only TIMER_SYNCI_CFG and TIMERx_SYNC accessed - info.regs() - .timer_synci_cfg() - .modify(|_r, w| unsafe { w.timer_syncisel(TIM).bits(sync_sel as u8) }); self.sync() - .modify(|_r, w| w.synci_en().bit(sync_sel != SyncInSelect::None)); + .modify(|_r, w| unsafe { w.synco_sel().bits(sync_out as u8) }); } fn enable_listen(&mut self, events: EnumSet, value: bool) { - let info = PWM::info(); + let info = self.mcpwm_info; let mut int_events = EnumSet::new(); for timer_event in events { int_events.insert(timer_event.into()); } - info.enable_listen::(int_events, value); + info.enable_listen(self.number, int_events, value); } fn cfg0(&mut self) -> &pac::mcpwm0::timer::CFG0 { // SAFETY: Unique register access per TIM - unsafe { Self::tmr() }.cfg0() + unsafe { self.tmr().cfg0() } } fn cfg1(&mut self) -> &pac::mcpwm0::timer::CFG1 { // SAFETY: Unique register access per TIM - unsafe { Self::tmr() }.cfg1() + unsafe { self.tmr().cfg1() } } fn sync(&mut self) -> &pac::mcpwm0::timer::SYNC { // SAFETY: Unique register access per TIM - unsafe { Self::tmr() }.sync() + unsafe { self.tmr().sync() } } // Marked unsafe as the caller must ensure that only one timer // is accessing the registers for a given TIM const - unsafe fn tmr() -> &'static pac::mcpwm0::TIMER { - let info = PWM::info(); - info.regs().timer(TIM as usize) + unsafe fn tmr(&self) -> &'d pac::mcpwm0::TIMER { + let info = self.mcpwm_info; + info.regs().timer(self.number as usize) } } @@ -342,9 +345,9 @@ impl<'d, const TIM: u8, PWM: Instance> Timer<'d, TIM, PWM> { #[repr(u8)] pub enum SyncOutSelect { /// Sync out is triggered when a timer receives a sync in - SyncIn = 0, + SyncIn = 0, /// Sync out is triggered when the timer equals zero - SyncWhenEqualZero = 1, + SyncWhenEqualZero = 1, /// Sync out is triggered when the timer equals the period SyncWhenEqualPeriod = 2, } @@ -513,11 +516,11 @@ impl TimerClockConfig { #[repr(u8)] pub enum PeriodUpdatingMethod { /// The period is updated immediately. - Immediately = 0, + Immediately = 0, /// The period is updated when the timer equals zero. - TimerEqualsZero = 1, + TimerEqualsZero = 1, /// The period is updated on a synchronization event. - Sync = 2, + Sync = 2, /// The period is updated either when the timer equals zero or on a /// synchronization event. TimerEqualsZeroOrSync = 3, @@ -532,10 +535,10 @@ pub enum StopCondition { RunContinuously = 2, /// Defines to start the timer now and run till /// the counter equals zero - StopAtZero = 3, + StopAtZero = 3, /// Defines to start the timer now and run till /// the counter equals period - StopAtPeriod = 4, + StopAtPeriod = 4, } /// PWM working mode @@ -557,7 +560,7 @@ pub enum PwmWorkingMode { /// starts increasing from zero until the period value is reached. Then, /// the timer decreases back to zero. This pattern is then repeated. The /// PWM period is the result of the value of the period field × 2. - UpDown = 3, + UpDown = 3, } impl From for CounterDirection { @@ -572,6 +575,7 @@ impl From for CounterDirection { /// The direction the timer counter is changing #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(u8)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum CounterDirection { /// The timer counter is increasing Increasing = 0, From 670834fb4edabe741d9e1c1795826a889c5f9529 Mon Sep 17 00:00:00 2001 From: Alex Dehart <105888845+Alex3404@users.noreply.github.com> Date: Fri, 10 Jul 2026 16:27:22 -0600 Subject: [PATCH 37/37] Update --- esp-hal/Cargo.toml | 19 ++++----- .../src/_build_script_utils.rs | 6 +-- .../src/_generated_esp32.rs | 29 ++++++-------- .../src/_generated_esp32h2.rs | 12 ++++++ .../src/_generated_esp32p4.rs | 39 +++++++++++++++++++ esp-metadata/devices/esp32/soc.toml | 2 + esp-metadata/devices/esp32c6/soc.toml | 1 - esp-metadata/devices/esp32h2/soc.toml | 21 +++++----- esp-metadata/devices/esp32s3/soc.toml | 19 +++++---- 9 files changed, 97 insertions(+), 51 deletions(-) diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 2ac6870af82..a55eea75bc0 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -112,15 +112,16 @@ ufmt-write = { version = "0.1", optional = true } ## Once (#415) pull request is accepted update the commit hash to ## point to the latest commit on the main branch of esp-pacs -esp32 = { version = "0.39", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } -esp32c2 = { version = "0.28", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } -esp32c3 = { version = "0.31", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } -esp32c5 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } -esp32c6 = { version = "0.22", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } -esp32c61 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } -esp32h2 = { version = "0.18", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } -esp32s2 = { version = "0.30", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } -esp32s3 = { version = "0.34", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "64db7c2018e25b0f5084f62a1c77b77015be237a" } +esp32 = { version = "0.39", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32c2 = { version = "0.28", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32c3 = { version = "0.31", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32c5 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32c6 = { version = "0.22", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32c61 = { version = "0.1", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32h2 = { version = "0.18", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32p4 = { version = "0.2", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32s2 = { version = "0.30", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } +esp32s3 = { version = "0.34", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "f7ffe16ade04b525d69704907b5a65eb0b0a2324" } [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { version = "0.15.0" } diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 4a86919226a..9e72e5308d1 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -363,7 +363,7 @@ impl Chip { "interrupts_status_registers=\"3\"", "interrupt_controller=\"xtensa\"", "ledc_version=\"1\"", - "ledc_channel_count=\"8\"", + "ledc_channel_count=\"6\"", "phy_combo_module", "psram_extmem_origin=\"1065353216\"", "rmt_ram_start=\"1073047552\"", @@ -590,7 +590,7 @@ impl Chip { "cargo:rustc-cfg=interrupts_status_registers=\"3\"", "cargo:rustc-cfg=interrupt_controller=\"xtensa\"", "cargo:rustc-cfg=ledc_version=\"1\"", - "cargo:rustc-cfg=ledc_channel_count=\"8\"", + "cargo:rustc-cfg=ledc_channel_count=\"6\"", "cargo:rustc-cfg=phy_combo_module", "cargo:rustc-cfg=psram_extmem_origin=\"1065353216\"", "cargo:rustc-cfg=rmt_ram_start=\"1073047552\"", @@ -7268,7 +7268,7 @@ pub fn emit_check_cfg_directives() { values(\"xtensa\",\"riscv_basic\",\"clic\",\"plic\"))" ); println!("cargo:rustc-check-cfg=cfg(ledc_version, values(\"1\",\"2\",\"3\"))"); - println!("cargo:rustc-check-cfg=cfg(ledc_channel_count, values(\"8\",\"6\"))"); + println!("cargo:rustc-check-cfg=cfg(ledc_channel_count, values(\"6\",\"8\"))"); println!( "cargo:rustc-check-cfg=cfg(psram_extmem_origin, \ values(\"1065353216\",\"1107296256\",\"1207959552\",\"1062207488\",\"1006632960\"))" diff --git a/esp-metadata-generated/src/_generated_esp32.rs b/esp-metadata-generated/src/_generated_esp32.rs index 1cb86aae962..8ae039c5a9d 100644 --- a/esp-metadata-generated/src/_generated_esp32.rs +++ b/esp-metadata-generated/src/_generated_esp32.rs @@ -238,6 +238,18 @@ macro_rules! property { ("interrupts.status_registers", str) => { stringify!(3) }; + ("ledc.version") => { + 1 + }; + ("ledc.version", str) => { + stringify!(1) + }; + ("ledc.channel_count") => { + 6 + }; + ("ledc.channel_count", str) => { + stringify!(6) + }; ("mcpwm.swsync_can_propagate") => { false }; @@ -704,23 +716,6 @@ macro_rules! for_each_sha_algorithm { }; } #[macro_export] -#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] -macro_rules! for_each_wakeup_source { - ($($pattern:tt => $code:tt;)*) => { - macro_rules! _for_each_inner_wakeup_source { $(($pattern) => $code;)* ($other : - tt) => {} } _for_each_inner_wakeup_source!((Ext0, 0)); - _for_each_inner_wakeup_source!((Ext1, 1)); _for_each_inner_wakeup_source!((Gpio, - 2)); _for_each_inner_wakeup_source!((Timer, 3)); - _for_each_inner_wakeup_source!((Sdio, 4)); _for_each_inner_wakeup_source!((Wifi, - 5)); _for_each_inner_wakeup_source!((Uart0, 6)); - _for_each_inner_wakeup_source!((Uart1, 7)); - _for_each_inner_wakeup_source!((Touch, 8)); _for_each_inner_wakeup_source!((Ulp, - 9)); _for_each_inner_wakeup_source!((Bt, 10)); - _for_each_inner_wakeup_source!((all(Ext0, 0), (Ext1, 1), (Gpio, 2), (Timer, 3), - (Sdio, 4), (Wifi, 5), (Uart0, 6), (Uart1, 7), (Touch, 8), (Ulp, 9), (Bt, 10))); - }; -} -#[macro_export] /// ESP-HAL must provide implementation for the following functions: /// ```rust, no_run /// // XTAL_CLK diff --git a/esp-metadata-generated/src/_generated_esp32h2.rs b/esp-metadata-generated/src/_generated_esp32h2.rs index 6c06aa9c78e..e3e177bb6d3 100644 --- a/esp-metadata-generated/src/_generated_esp32h2.rs +++ b/esp-metadata-generated/src/_generated_esp32h2.rs @@ -271,6 +271,18 @@ macro_rules! property { ("interrupts.disabled_interrupt") => { 31 }; + ("ledc.version") => { + 3 + }; + ("ledc.version", str) => { + stringify!(3) + }; + ("ledc.channel_count") => { + 6 + }; + ("ledc.channel_count", str) => { + stringify!(6) + }; ("mcpwm.swsync_can_propagate") => { true }; diff --git a/esp-metadata-generated/src/_generated_esp32p4.rs b/esp-metadata-generated/src/_generated_esp32p4.rs index 8c3235bbf67..ed1408e211e 100644 --- a/esp-metadata-generated/src/_generated_esp32p4.rs +++ b/esp-metadata-generated/src/_generated_esp32p4.rs @@ -283,6 +283,21 @@ macro_rules! property { ("lp_uart.ram_size", str) => { stringify!(32) }; + ("mcpwm.swsync_can_propagate") => { + false + }; + ("mcpwm.capture_clk_from_group") => { + false + }; + ("mcpwm.support_etm") => { + false + }; + ("mcpwm.support_sleep_retention") => { + false + }; + ("mcpwm.support_event_comparator") => { + false + }; ("psram.octal_spi") => { false }; @@ -4803,6 +4818,30 @@ macro_rules! for_each_uart { UART4_TXD, UART4_CTS, UART4_RTS))); }; } +/// This macro can be used to generate code for each peripheral instance of the MCPWM driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($id:literal, $instance:ident, $sys:ident)` +/// +/// Macro fragments: +/// +/// - `$id`: the index of the MCPWM instance +/// - `$instance`: the name of the MCPWM instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// +/// Example data: `(0, MCPWM0, Mcpwm0)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_mcpwm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_mcpwm { $(($pattern) => $code;)* ($other : tt) => {} + } _for_each_inner_mcpwm!((all)); + }; +} /// This macro can be used to generate code for each peripheral instance of the SPI master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata/devices/esp32/soc.toml b/esp-metadata/devices/esp32/soc.toml index 4e12811c02d..039d0c77aac 100644 --- a/esp-metadata/devices/esp32/soc.toml +++ b/esp-metadata/devices/esp32/soc.toml @@ -768,6 +768,8 @@ instances = [ ] [device.ledc] +version = 1 +channel_count = 6 [device.pcnt] [device.sdmmc] diff --git a/esp-metadata/devices/esp32c6/soc.toml b/esp-metadata/devices/esp32c6/soc.toml index 3f19077eb85..6319fe5c953 100644 --- a/esp-metadata/devices/esp32c6/soc.toml +++ b/esp-metadata/devices/esp32c6/soc.toml @@ -649,7 +649,6 @@ instances = [ [device.ledc] version = 3 channel_count = 6 -[device.mcpwm] [device.pcnt] [device.sd_slave] diff --git a/esp-metadata/devices/esp32h2/soc.toml b/esp-metadata/devices/esp32h2/soc.toml index 3a78a983ecf..6cc8c7ef4fc 100644 --- a/esp-metadata/devices/esp32h2/soc.toml +++ b/esp-metadata/devices/esp32h2/soc.toml @@ -515,16 +515,6 @@ version = 2 support_status = "partial" light_sleep = true deep_sleep = true - -[device.mcpwm] -support_status = "partial" -swsync_can_propagate = true -capture_clk_from_group = true -support_etm = true -support_sleep_retention = true -instances = [ - { name = "mcpwm0", sys_instance = "Mcpwm0" }, -] wakeup_sources = { Ext0 = 0, Ext1 = 1, @@ -540,6 +530,16 @@ wakeup_sources = { Usb = 14, } +[device.mcpwm] +support_status = "partial" +swsync_can_propagate = true +capture_clk_from_group = true +support_etm = true +support_sleep_retention = true +instances = [ + { name = "mcpwm0", sys_instance = "Mcpwm0" }, +] + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -572,7 +572,6 @@ instances = [ [device.ledc] version = 3 channel_count = 6 -[device.mcpwm] [device.pcnt] [device.twai] [device.usb_serial_jtag] diff --git a/esp-metadata/devices/esp32s3/soc.toml b/esp-metadata/devices/esp32s3/soc.toml index 02ef7039b87..72a9442a2cf 100644 --- a/esp-metadata/devices/esp32s3/soc.toml +++ b/esp-metadata/devices/esp32s3/soc.toml @@ -750,14 +750,6 @@ apb_cycle_wait_num = 16 # TODO support_status = "partial" light_sleep = true deep_sleep = true - -[device.mcpwm] -support_status = "partial" -swsync_can_propagate = true -instances = [ - { name = "mcpwm0", sys_instance = "Mcpwm0" }, - { name = "mcpwm1", sys_instance = "Mcpwm1" }, -] wakeup_sources = { Ext0 = 0, Ext1 = 1, @@ -771,9 +763,17 @@ wakeup_sources = { Ulp = 9, Bt = 10, UlpRiscv = 11, - UlpRiscvTrap = 13 + UlpRiscvTrap = 13, } +[device.mcpwm] +support_status = "partial" +swsync_can_propagate = true +instances = [ + { name = "mcpwm0", sys_instance = "Mcpwm0" }, + { name = "mcpwm1", sys_instance = "Mcpwm1" }, +] + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -819,7 +819,6 @@ instances = [ [device.ledc] version = 2 channel_count = 8 -[device.mcpwm] [device.pcnt] [device.sdmmc]