Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion esp-hal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a
| SPI slave | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ |
| LP SPI master | | | | | | | | ❌ | | | |
| LP SPI slave | | | | | | | | ❌ | | | |
| I2S | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | |
| I2S | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ |
| LP I2S | | | | | | | | ❌ | | | |
| PARL_IO | | | | ⚒️ | ⚒️ | | ⚒️ | ❌ | | | ❌ |
| RMT | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! I2S clock programming via `HP_SYS_CLKRST`.
//! I2S clock programming via `HP_SYS_CLKRST` on ESP32-P4.

use super::master::private::I2sClockDividers;
use crate::{peripherals::HP_SYS_CLKRST, system::Peripheral};
Expand Down
150 changes: 150 additions & 0 deletions esp-hal/src/i2s/hp_sys_clkrst_s31.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
//! I2S clock programming via `HP_SYS_CLKRST` on ESP32-S31.
//!
//! Register layout differs from ESP32-P4: each instance has dedicated
//! `i2sN_{tx,rx}_{ctrl0,div_ctrl0}` registers. Sequence follows ESP-IDF
//! `i2s_ll_{tx,rx}_set_raw_clk_div`.

use super::master::private::I2sClockDividers;
use crate::{peripherals::HP_SYS_CLKRST, system::Peripheral};

pub(crate) fn set_tx_clock(peripheral: Peripheral, clock_settings: &I2sClockDividers) {
let clkm_div = clock_settings.mclk_dividers();
let clkrst = HP_SYS_CLKRST::regs();
let clock_source = property!("i2s.default_clock_source");

match peripheral {
Peripheral::I2s0 => {
// Bind MCLK to the TX module (`mst_clk_sel` lives on the RX ctrl register).
clkrst
.i2s0_rx_ctrl0()
.modify(|_, w| w.mst_clk_sel().set_bit());

// Workaround for the double-division issue documented in esp-idf i2s_ll.h.
clkrst
.i2s0_tx_ctrl0()
.modify(|_, w| unsafe { w.tx_div_n().bits(2) });
clkrst.i2s0_tx_div_ctrl0().modify(|_, w| {
w.tx_div_yn1().clear_bit();
unsafe {
w.tx_div_y().bits(1);
w.tx_div_z().bits(0);
w.tx_div_x().bits(0)
}
});

clkrst.i2s0_tx_div_ctrl0().modify(|_, w| {
w.tx_div_yn1().bit(clkm_div.yn1);
unsafe {
w.tx_div_z().bits(clkm_div.z as u16);
w.tx_div_y().bits(clkm_div.y as u16);
w.tx_div_x().bits(clkm_div.x as u16)
}
});
clkrst.i2s0_tx_ctrl0().modify(|_, w| unsafe {
w.tx_div_n().bits(clock_settings.mclk_divider as u8);
w.tx_clk_en().set_bit();
w.tx_clk_src_sel().bits(clock_source)
});
}
Peripheral::I2s1 => {
clkrst
.i2s1_rx_ctrl0()
.modify(|_, w| w.mst_clk_sel().set_bit());

clkrst
.i2s1_tx_ctrl0()
.modify(|_, w| unsafe { w.tx_div_n().bits(2) });
clkrst.i2s1_tx_div_ctrl0().modify(|_, w| {
w.tx_div_yn1().clear_bit();
unsafe {
w.tx_div_y().bits(1);
w.tx_div_z().bits(0);
w.tx_div_x().bits(0)
}
});

clkrst.i2s1_tx_div_ctrl0().modify(|_, w| {
w.tx_div_yn1().bit(clkm_div.yn1);
unsafe {
w.tx_div_z().bits(clkm_div.z as u16);
w.tx_div_y().bits(clkm_div.y as u16);
w.tx_div_x().bits(clkm_div.x as u16)
}
});
clkrst.i2s1_tx_ctrl0().modify(|_, w| unsafe {
w.tx_div_n().bits(clock_settings.mclk_divider as u8);
w.tx_clk_en().set_bit();
w.tx_clk_src_sel().bits(clock_source)
});
}
_ => unreachable!(),
}
}

pub(crate) fn set_rx_clock(peripheral: Peripheral, clock_settings: &I2sClockDividers) {
let clkm_div = clock_settings.mclk_dividers();
let clkrst = HP_SYS_CLKRST::regs();
let clock_source = property!("i2s.default_clock_source");

match peripheral {
Peripheral::I2s0 => {
// Bind MCLK to the RX module, then apply the double-division workaround
// documented in esp-idf i2s_ll.h (`mst_clk_sel` lives on this register).
clkrst.i2s0_rx_ctrl0().modify(|_, w| {
w.mst_clk_sel().clear_bit();
unsafe { w.rx_div_n().bits(2) }
});
clkrst.i2s0_rx_div_ctrl0().modify(|_, w| {
w.rx_div_yn1().clear_bit();
unsafe {
w.rx_div_y().bits(1);
w.rx_div_z().bits(0);
w.rx_div_x().bits(0)
}
});

clkrst.i2s0_rx_div_ctrl0().modify(|_, w| {
w.rx_div_yn1().bit(clkm_div.yn1);
unsafe {
w.rx_div_z().bits(clkm_div.z as u16);
w.rx_div_y().bits(clkm_div.y as u16);
w.rx_div_x().bits(clkm_div.x as u16)
}
});
clkrst.i2s0_rx_ctrl0().modify(|_, w| unsafe {
w.rx_div_n().bits(clock_settings.mclk_divider as u8);
w.rx_clk_en().set_bit();
w.rx_clk_src_sel().bits(clock_source)
});
}
Peripheral::I2s1 => {
clkrst.i2s1_rx_ctrl0().modify(|_, w| {
w.mst_clk_sel().clear_bit();
unsafe { w.rx_div_n().bits(2) }
});
clkrst.i2s1_rx_div_ctrl0().modify(|_, w| {
w.rx_div_yn1().clear_bit();
unsafe {
w.rx_div_y().bits(1);
w.rx_div_z().bits(0);
w.rx_div_x().bits(0)
}
});

clkrst.i2s1_rx_div_ctrl0().modify(|_, w| {
w.rx_div_yn1().bit(clkm_div.yn1);
unsafe {
w.rx_div_z().bits(clkm_div.z as u16);
w.rx_div_y().bits(clkm_div.y as u16);
w.rx_div_x().bits(clkm_div.x as u16)
}
});
clkrst.i2s1_rx_ctrl0().modify(|_, w| unsafe {
w.rx_div_n().bits(clock_settings.mclk_divider as u8);
w.rx_clk_en().set_bit();
w.rx_clk_src_sel().bits(clock_source)
});
}
_ => unreachable!(),
}
}
4 changes: 3 additions & 1 deletion esp-hal/src/i2s/master/low_level/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ pub(crate) struct I2sMclkDividers {
impl I2sClockDividers {
pub(crate) fn mclk_dividers(&self) -> I2sMclkDividers {
let (x, y, z, yn1) = if self.denominator == 0 || self.numerator == 0 {
(0, 0, 0, true)
// IDF `i2s_ll_tx_set_mclk`: no fraction → x/y/z/yn1 all 0.
// `yn1` with z=0 makes the hardware run at N+1.
(0, 0, 0, false)
} else if self.numerator > self.denominator / 2 {
let x = self
.denominator
Expand Down
2 changes: 2 additions & 0 deletions esp-hal/src/i2s/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
pub mod master;

#[cfg(i2s_clock_configured_by_hp_sys_clkrst)]
#[cfg_attr(esp32p4, path = "hp_sys_clkrst_p4.rs")]
#[cfg_attr(esp32s31, path = "hp_sys_clkrst_s31.rs")]
mod hp_sys_clkrst;

#[cfg(any(i2s_supports_pdm_tx, i2s_supports_pdm_rx))]
Expand Down
4 changes: 2 additions & 2 deletions esp-hal/src/i2s/pdm/regs_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ fn configure_rx(i2s: &Info, config: &super::PdmRxConfig) -> Result<(), PdmError>

i2s.set_rx_clock(clock.dividers);

#[cfg(all(i2s_supports_pdm2pcm, esp32p4))]
#[cfg(all(i2s_supports_pdm2pcm, i2s_supports_pdm_rx_hp_filter))]
{
let dsr16 = config.clock.downsample_rate == super::PdmDownsampleRate::Dsr16s;
let freq_x10 = (config.slot.hp_cut_off_freq_hz * 10.0) as u32;
Expand All @@ -228,7 +228,7 @@ fn configure_rx(i2s: &Info, config: &super::PdmRxConfig) -> Result<(), PdmError>
i2s.regs().rx_conf().modify(|_, w| {
w.rx_pdm_en().set_bit();
w.rx_tdm_en().clear_bit();
#[cfg(all(i2s_supports_pdm2pcm, not(esp32p4)))]
#[cfg(all(i2s_supports_pdm2pcm, not(i2s_supports_pdm_rx_hp_filter)))]
{
w.rx_pdm2pcm_en().bit(pcm);
w.rx_pdm_sinc_dsr_16_en()
Expand Down
4 changes: 3 additions & 1 deletion esp-hal/src/soc/esp32s31/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ pub(crate) use esp32s31 as pac;
#[cfg(i2s_driver_supported)]
#[cfg_attr(not(feature = "unstable"), allow(unused))]
pub(crate) fn i2s_sclk_frequency() -> u32 {
clocks::pll_f160m_frequency()
// XTAL matches `i2s.default_clock_source` (mux 0). Mux 1 is APLL, which has
// less MCLK jitter; switch both to APLL once it's modelled in the clock tree.
clocks::xtal_clk_frequency()
}

pub(crate) fn enable_branch_predictor() {
Expand Down
46 changes: 44 additions & 2 deletions esp-metadata-generated/src/_build_script_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7925,6 +7925,8 @@ impl Chip {
"soc_has_hp_sys_clkrst",
"soc_has_i2c0",
"soc_has_i2c1",
"soc_has_i2s0",
"soc_has_i2s1",
"soc_has_interrupt_core0",
"soc_has_interrupt_core1",
"soc_has_io_mux",
Expand Down Expand Up @@ -7987,6 +7989,7 @@ impl Chip {
"i2c_master_driver_supported",
"spi_master_driver_supported",
"spi_slave_driver_supported",
"i2s_driver_supported",
"rmt_driver_supported",
"sdmmc_driver_supported",
"usb_otg_hs_driver_supported",
Expand Down Expand Up @@ -8017,6 +8020,8 @@ impl Chip {
"spi_master_spi3",
"spi_slave_spi2",
"spi_slave_spi3",
"i2s_i2s0",
"i2s_i2s1",
"adc_adc1",
"adc_adc2",
"timergroup_timg0",
Expand Down Expand Up @@ -8056,6 +8061,20 @@ impl Chip {
"spi_master_has_octal",
"spi_master_has_app_interrupts",
"spi_master_has_dma_segmented_transfer",
"i2s_version=\"3\"",
"i2s_version_is_set",
"i2s_default_clock_source=\"0\"",
"i2s_default_clock_source_is_set",
"i2s_mclk_divider_bit_width=\"8\"",
"i2s_mclk_divider_bit_width_is_set",
"i2s_max_ws_width=\"512\"",
"i2s_max_ws_width_is_set",
"i2s_clock_configured_by_hp_sys_clkrst",
"i2s_supports_pdm_rx_hp_filter",
"i2s_supports_pdm_tx",
"i2s_supports_pdm_rx",
"i2s_supports_pcm2pdm",
"i2s_supports_pdm2pcm",
"rmt_ram_start=\"540366848\"",
"rmt_channel_ram_size=\"48\"",
"rmt_has_tx_immediate_stop",
Expand Down Expand Up @@ -8115,6 +8134,8 @@ impl Chip {
"dma_supports_mem2mem",
"uhci_supports_dma",
"uhci_dma_engine=\"AHB_GDMA\"",
"i2s_supports_dma",
"i2s_dma_engine=\"AHB_GDMA\"",
"spi_master_supports_dma",
"spi_master_dma_engine=\"AXI_GDMA\"",
"spi_slave_supports_dma",
Expand Down Expand Up @@ -8215,6 +8236,8 @@ impl Chip {
"cargo:rustc-cfg=soc_has_hp_sys_clkrst",
"cargo:rustc-cfg=soc_has_i2c0",
"cargo:rustc-cfg=soc_has_i2c1",
"cargo:rustc-cfg=soc_has_i2s0",
"cargo:rustc-cfg=soc_has_i2s1",
"cargo:rustc-cfg=soc_has_interrupt_core0",
"cargo:rustc-cfg=soc_has_interrupt_core1",
"cargo:rustc-cfg=soc_has_io_mux",
Expand Down Expand Up @@ -8277,6 +8300,7 @@ impl Chip {
"cargo:rustc-cfg=i2c_master_driver_supported",
"cargo:rustc-cfg=spi_master_driver_supported",
"cargo:rustc-cfg=spi_slave_driver_supported",
"cargo:rustc-cfg=i2s_driver_supported",
"cargo:rustc-cfg=rmt_driver_supported",
"cargo:rustc-cfg=sdmmc_driver_supported",
"cargo:rustc-cfg=usb_otg_hs_driver_supported",
Expand Down Expand Up @@ -8307,6 +8331,8 @@ impl Chip {
"cargo:rustc-cfg=spi_master_spi3",
"cargo:rustc-cfg=spi_slave_spi2",
"cargo:rustc-cfg=spi_slave_spi3",
"cargo:rustc-cfg=i2s_i2s0",
"cargo:rustc-cfg=i2s_i2s1",
"cargo:rustc-cfg=adc_adc1",
"cargo:rustc-cfg=adc_adc2",
"cargo:rustc-cfg=timergroup_timg0",
Expand Down Expand Up @@ -8346,6 +8372,20 @@ impl Chip {
"cargo:rustc-cfg=spi_master_has_octal",
"cargo:rustc-cfg=spi_master_has_app_interrupts",
"cargo:rustc-cfg=spi_master_has_dma_segmented_transfer",
"cargo:rustc-cfg=i2s_version=\"3\"",
"cargo:rustc-cfg=i2s_version_is_set",
"cargo:rustc-cfg=i2s_default_clock_source=\"0\"",
"cargo:rustc-cfg=i2s_default_clock_source_is_set",
"cargo:rustc-cfg=i2s_mclk_divider_bit_width=\"8\"",
"cargo:rustc-cfg=i2s_mclk_divider_bit_width_is_set",
"cargo:rustc-cfg=i2s_max_ws_width=\"512\"",
"cargo:rustc-cfg=i2s_max_ws_width_is_set",
"cargo:rustc-cfg=i2s_clock_configured_by_hp_sys_clkrst",
"cargo:rustc-cfg=i2s_supports_pdm_rx_hp_filter",
"cargo:rustc-cfg=i2s_supports_pdm_tx",
"cargo:rustc-cfg=i2s_supports_pdm_rx",
"cargo:rustc-cfg=i2s_supports_pcm2pdm",
"cargo:rustc-cfg=i2s_supports_pdm2pcm",
"cargo:rustc-cfg=rmt_ram_start=\"540366848\"",
"cargo:rustc-cfg=rmt_channel_ram_size=\"48\"",
"cargo:rustc-cfg=rmt_has_tx_immediate_stop",
Expand Down Expand Up @@ -8405,6 +8445,8 @@ impl Chip {
"cargo:rustc-cfg=dma_supports_mem2mem",
"cargo:rustc-cfg=uhci_supports_dma",
"cargo:rustc-cfg=uhci_dma_engine=\"AHB_GDMA\"",
"cargo:rustc-cfg=i2s_supports_dma",
"cargo:rustc-cfg=i2s_dma_engine=\"AHB_GDMA\"",
"cargo:rustc-cfg=spi_master_supports_dma",
"cargo:rustc-cfg=spi_master_dma_engine=\"AXI_GDMA\"",
"cargo:rustc-cfg=spi_slave_supports_dma",
Expand Down Expand Up @@ -9353,8 +9395,8 @@ impl Chip {
"spi_master_version, values(\"1\",\"3\",\"2\")",
"spi_master_fifo_size, values(\"64\",\"72\")",
"i2s_version, values(\"1\",\"2\",\"3\")",
"i2s_default_clock_source, values(\"2\",\"1\",\"3\")",
"i2s_mclk_divider_bit_width, values(\"6\",\"9\")",
"i2s_default_clock_source, values(\"2\",\"1\",\"3\",\"0\")",
"i2s_mclk_divider_bit_width, values(\"6\",\"9\",\"8\")",
"i2s_max_ws_width, values(\"128\",\"512\")",
"rmt_ram_start, \
values(\"1073047552\",\"1610703872\",\"1610638336\",\"1610642432\",\"1342842880\",\"\
Expand Down
Loading
Loading