diff --git a/components/esp_driver_sdm/test_apps/sigma_delta/README.md b/components/esp_driver_sdm/test_apps/sigma_delta/README.md index c3221d0779..2ce6f477ac 100644 --- a/components/esp_driver_sdm/test_apps/sigma_delta/README.md +++ b/components/esp_driver_sdm/test_apps/sigma_delta/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- | diff --git a/components/esp_hal_gpio/esp32s31/include/hal/sdm_caps.h b/components/esp_hal_gpio/esp32s31/include/hal/sdm_caps.h new file mode 100644 index 0000000000..c91de33cff --- /dev/null +++ b/components/esp_hal_gpio/esp32s31/include/hal/sdm_caps.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#define SDM_CAPS_GET(_attr) _SDM_ ## _attr + +#define _SDM_INST_NUM 1 /* Number of SDM instances */ +#define _SDM_CHANS_PER_INST 8 /* Number of channels in each SDM instance */ diff --git a/components/esp_hal_gpio/esp32s31/include/hal/sdm_ll.h b/components/esp_hal_gpio/esp32s31/include/hal/sdm_ll.h new file mode 100644 index 0000000000..15f7403805 --- /dev/null +++ b/components/esp_hal_gpio/esp32s31/include/hal/sdm_ll.h @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "hal/misc.h" +#include "hal/assert.h" +#include "soc/gpio_ext_struct.h" +#include "soc/gpio_ext_reg.h" +#include "soc/soc.h" + +// Get SDM register base address with giving group number +#define SDM_LL_GET_HW(group_id) ((group_id == 0) ? (&SDM) : NULL) + +#define SDM_LL_PRESCALE_MAX (GPIO_EXT_SD0_PRESCALE_V + 1) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set Sigma-delta enable + * + * @param hw Peripheral SIGMADELTA hardware instance address. + * @param en Sigma-delta enable value + */ +static inline void sdm_ll_enable_clock(gpio_sd_dev_t *hw, bool en) +{ + hw->misc.sigmadelta_clk_en = en; +} + +/** + * @brief Set Sigma-delta channel duty. + * + * @param hw Peripheral SIGMADELTA hardware instance address. + * @param channel Sigma-delta channel number + * @param density Sigma-delta quantized density of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90. + * The waveform is more like a random one in this range. + */ +__attribute__((always_inline)) +static inline void sdm_ll_set_pulse_density(gpio_sd_dev_t *hw, int channel, int8_t density) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], sdn_in, (uint32_t)density); +} + +/** + * @brief Set Sigma-delta channel's clock pre-scale value. + * + * @param hw Peripheral SIGMADELTA hardware instance address. + * @param channel Sigma-delta channel number + * @param prescale The divider of source clock, ranges from 1 to 256 + */ +static inline void sdm_ll_set_prescale(gpio_sd_dev_t *hw, int channel, uint32_t prescale) +{ + HAL_ASSERT(prescale && prescale <= SDM_LL_PRESCALE_MAX); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], sdn_prescale, prescale - 1); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_gpio/esp32s31/sdm_periph.c b/components/esp_hal_gpio/esp32s31/sdm_periph.c new file mode 100644 index 0000000000..375d70fe8e --- /dev/null +++ b/components/esp_hal_gpio/esp32s31/sdm_periph.c @@ -0,0 +1,72 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/sdm_periph.h" +#include "soc/gpio_sig_map.h" +#include "soc/gpio_ext_reg.h" + +const soc_sdm_signal_desc_t soc_sdm_signals[1] = { + [0] = { + .module_name = "SDM0", + .channels = { + [0] = { + .sig_id_matrix = GPIO_SD0_OUT_IDX + }, + [1] = { + .sig_id_matrix = GPIO_SD1_OUT_IDX + }, + [2] = { + .sig_id_matrix = GPIO_SD2_OUT_IDX + }, + [3] = { + .sig_id_matrix = GPIO_SD3_OUT_IDX + }, + [4] = { + .sig_id_matrix = GPIO_SD4_OUT_IDX + }, + [5] = { + .sig_id_matrix = GPIO_SD5_OUT_IDX + }, + [6] = { + .sig_id_matrix = GPIO_SD6_OUT_IDX + }, + [7] = { + .sig_id_matrix = GPIO_SD7_OUT_IDX + } + } + } +}; + +#if SOC_PAU_SUPPORTED +/** + * @brief Registers in retention context: + * GPIO_EXT_SIGMADELTA[x]_REG + * GPIO_EXT_SIGMADELTA_MISC_REG + */ +#define GPIO_EXT_RETENTION_REGS_CNT 9 +#define GPIO_EXT_RETENTION_REGS_BASE (DR_REG_GPIO_EXT_BASE + 0x4) +static const uint32_t gpio_ext_regs_map[4] = {0x1ff, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t gpio_ext_regdma_entries[] = { + // backup stage: save configuration and status registers + // restore stage: restore the configuration and status registers + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GPIO_EXT_LINK(0x00), + GPIO_EXT_RETENTION_REGS_BASE, GPIO_EXT_RETENTION_REGS_BASE, + GPIO_EXT_RETENTION_REGS_CNT, 0, 0, + gpio_ext_regs_map[0], gpio_ext_regs_map[1], + gpio_ext_regs_map[2], gpio_ext_regs_map[3]), + .owner = ENTRY(0) | ENTRY(2), + }, +}; + +const soc_sdm_retention_desc_t soc_sdm_retention_infos[1] = { + [0] = { + .module = SLEEP_RETENTION_MODULE_SDM0, + .regdma_entry_array = gpio_ext_regdma_entries, + .array_size = ARRAY_SIZE(gpio_ext_regdma_entries) + } +}; +#endif // SOC_PAU_SUPPORTED diff --git a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in index 543475a83a..5aa7d992e5 100644 --- a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in @@ -19,6 +19,10 @@ config SOC_EFUSE_SUPPORTED bool default y +config SOC_SDM_SUPPORTED + bool + default y + config SOC_SYSTIMER_SUPPORTED bool default y @@ -191,6 +195,10 @@ config SOC_RTCIO_PIN_COUNT int default 8 +config SOC_SDM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MMU_PERIPH_NUM int default 2 diff --git a/components/soc/esp32s31/include/soc/clk_tree_defs.h b/components/soc/esp32s31/include/soc/clk_tree_defs.h index b683c296f3..a0915003d3 100644 --- a/components/soc/esp32s31/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s31/include/soc/clk_tree_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -308,6 +308,15 @@ typedef enum { MWDT_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL 40 MHz as the default clock choice */ } soc_periph_mwdt_clk_src_t; +/** + * @brief Sigma Delta Modulator clock source + */ +typedef enum { + SDM_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL clock as the source clock */ + SDM_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M clock as the source clock */ + SDM_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M clock as the default clock choice */ +} soc_periph_sdm_clk_src_t; + //////////////////////////////////////////////CLOCK OUTPUT/////////////////////////////////////////////////////////// typedef enum { CLKOUT_SIG_MPLL = 0, /*!< MPLL is from 40MHz XTAL oscillator frequency multipliers */ diff --git a/components/soc/esp32s31/include/soc/soc_caps.h b/components/soc/esp32s31/include/soc/soc_caps.h index 32a1bcbde2..09a672a5db 100644 --- a/components/soc/esp32s31/include/soc/soc_caps.h +++ b/components/soc/esp32s31/include/soc/soc_caps.h @@ -55,7 +55,7 @@ // #define SOC_RTC_MEM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14678 // #define SOC_RMT_SUPPORTED 1 // TODO: [ESP32S31] IDF-14794 // #define SOC_I2S_SUPPORTED 1 // TODO: [ESP32S31] IDF-14771 -// #define SOC_SDM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14783 +#define SOC_SDM_SUPPORTED 1 // #define SOC_GPSPI_SUPPORTED 1 // TODO: [ESP32S31] IDF-14734 // #define SOC_LEDC_SUPPORTED 1 // TODO: [ESP32S31] IDF-14709 // #define SOC_ISP_SUPPORTED 1 // TODO: [ESP32S31] IDF-14769 @@ -180,6 +180,9 @@ /*-------------------------- RTCIO CAPS --------------------------------------*/ #define SOC_RTCIO_PIN_COUNT 8 +/*-------------------------- Sigma Delta Modulator CAPS -----------------*/ +#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1 + /*-------------------------- MMU CAPS ----------------------------------------*/ // TODO: [ESP32S31] IDF-14669 #define SOC_MMU_PERIPH_NUM (2U) diff --git a/components/soc/esp32s31/ld/esp32s31.peripherals.ld b/components/soc/esp32s31/ld/esp32s31.peripherals.ld index 0651bd2097..aedc181988 100644 --- a/components/soc/esp32s31/ld/esp32s31.peripherals.ld +++ b/components/soc/esp32s31/ld/esp32s31.peripherals.ld @@ -72,6 +72,7 @@ PROVIDE ( TIMERG1 = 0x20581000 ); PROVIDE ( IO_MUX = 0x20582000 ); PROVIDE ( GPIO = 0x20583000 ); PROVIDE ( GPIO_EXT = 0x20583E00 ); +PROVIDE ( SDM = 0x20583E04 ); PROVIDE ( MSPI_IOMUX = 0x20584000 ); PROVIDE ( HP_SYSTEM = 0x20586000 ); PROVIDE ( HP_SYS_CLKRST = 0x20587000 ); diff --git a/components/soc/esp32s31/register/soc/gpio_ext_struct.h b/components/soc/esp32s31/register/soc/gpio_ext_struct.h index 00dee18929..319deb37b3 100644 --- a/components/soc/esp32s31/register/soc/gpio_ext_struct.h +++ b/components/soc/esp32s31/register/soc/gpio_ext_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -1207,10 +1207,14 @@ typedef union { } gpio_ext_version_reg_t; +typedef struct gpio_sd_dev_t { + volatile gpio_ext_sigmadelta_misc_reg_t misc; + volatile gpio_ext_sigmadeltan_reg_t channel[8]; +} gpio_sd_dev_t; + typedef struct { uint32_t reserved_000; - volatile gpio_ext_sigmadelta_misc_reg_t sigmadelta_misc; - volatile gpio_ext_sigmadeltan_reg_t sigmadeltan[8]; + volatile gpio_sd_dev_t sigma_delta; uint32_t reserved_028[44]; volatile gpio_ext_glitch_filter_chn_reg_t glitch_filter_chn[8]; uint32_t reserved_0f8[8]; @@ -1238,6 +1242,9 @@ typedef struct { _Static_assert(sizeof(gpio_ext_dev_t) == 0x200, "Invalid size of gpio_ext_dev_t structure"); #endif +extern gpio_sd_dev_t SDM; +extern gpio_ext_dev_t GPIO_EXT; + #ifdef __cplusplus } #endif diff --git a/examples/peripherals/sigma_delta/sdm_dac/README.md b/examples/peripherals/sigma_delta/sdm_dac/README.md index d6d670d346..cb932bf12c 100644 --- a/examples/peripherals/sigma_delta/sdm_dac/README.md +++ b/examples/peripherals/sigma_delta/sdm_dac/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- | # Sigma Delta Modulation DAC Example diff --git a/examples/peripherals/sigma_delta/sdm_led/README.md b/examples/peripherals/sigma_delta/sdm_led/README.md index feeaa37d6e..c1c5597bc2 100644 --- a/examples/peripherals/sigma_delta/sdm_led/README.md +++ b/examples/peripherals/sigma_delta/sdm_led/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- | # Sigma Delta Modulation LED Example