fix(sdmmc): corrected the control of dedicated sdmmc pads

- only slot1 takes dedicated pads
- remove slot1 should clear the control of dedicated pads
- fix the current leakage in deep sleep caused by the sdmmc pads
This commit is contained in:
Song Ruo Jing
2026-09-17 11:31:53 +08:00
parent 9e20a2b27f
commit 34c3915938
22 changed files with 182 additions and 53 deletions
@@ -108,9 +108,6 @@ esp_err_t sd_host_create_sdmmc_controller(const sd_host_sdmmc_cfg_t *config, sd_
#endif //CONFIG_PM_ENABLE
sdmmc_hal_init(&ctlr->hal);
PERIPH_RCC_ATOMIC() {
sdmmc_ll_pad_set_pin_dedicated_ctrl(ctlr->hal.dev, true);
}
ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src(SDMMC_CLK_SRC_DEFAULT, true), err, TAG, "failed to acquire clk");
uint32_t src_freq_hz = 0;
esp_clk_tree_src_get_freq_hz(SDMMC_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_freq_hz);
@@ -398,6 +395,11 @@ static esp_err_t sd_host_controller_remove_sdmmc_slot(sd_host_slot_handle_t slot
gpio_output_disable(slot_ctx->io_config.d7_io);
}
// release the pads so that they can be used as normal GPIOs
PERIPH_RCC_ATOMIC() {
sdmmc_ll_pad_set_pin_dedicated_ctrl(ctlr->hal.dev, slot_ctx->slot_id, false);
}
xSemaphoreGive(ctlr->mutex);
free(slot);
@@ -1394,6 +1396,10 @@ static esp_err_t sdmmc_slot_io_config(sd_host_sdmmc_slot_t *slot, const sd_host_
GPIO_NUM_CHECK(slot_gpio->d7_io);
}
PERIPH_RCC_ATOMIC() {
sdmmc_ll_pad_set_pin_dedicated_ctrl(slot->ctlr->hal.dev, slot_id, true);
}
configure_pin(slot_gpio->clk_io, sdmmc_slot_gpio_sig[slot_id].clk, GPIO_MODE_OUTPUT, "clk", use_gpio_matrix);
configure_pin(slot_gpio->cmd_io, sdmmc_slot_gpio_sig[slot_id].cmd, GPIO_MODE_INPUT_OUTPUT, "cmd", use_gpio_matrix);
configure_pin(slot_gpio->d0_io, sdmmc_slot_gpio_sig[slot_id].d0, GPIO_MODE_INPUT_OUTPUT, "d0", use_gpio_matrix);
@@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
@@ -762,6 +762,15 @@ static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint3
hw->func_out_sel_cfg[gpio_num].inv_sel = out_inv;
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -769,6 +769,15 @@ static inline bool gpio_ll_hp_periph_powerdown_sleep_wakeup_is_enabled(gpio_dev_
return GET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, 1 << (RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_S - gpio_num));
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -790,6 +790,15 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
io_config->slp_sel = (iomux_reg_val & SLP_SEL_M) >> SLP_SEL_S;
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -735,6 +735,15 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num
IO_MUX.gpio[gpio_num].mcu_oe = 1;
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -696,6 +696,15 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num
PIN_SLP_OUTPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -735,6 +735,15 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num
IO_MUX.gpion[gpio_num].gpion_mcu_oe = 1;
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -804,6 +804,15 @@ static inline bool gpio_ll_hp_periph_powerdown_sleep_wakeup_is_enabled(gpio_dev_
return wakeup_sel_mask & BIT(gpio_num - 7);
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -788,6 +788,15 @@ static inline bool gpio_ll_hp_periph_powerdown_sleep_wakeup_is_enabled(gpio_dev_
return wakeup_sel_mask & BIT(gpio_num - 5);
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -778,6 +778,15 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num
IO_MUX.gpio[gpio_num].mcu_oe = 1;
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -872,6 +872,15 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num
IO_MUX.gpio[gpio_num].mcu_oe = 1;
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -734,6 +734,15 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num
PIN_SLP_OUTPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -761,6 +761,15 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
io_config->slp_sel = (iomux_reg_val & SLP_SEL_M) >> SLP_SEL_S;
}
/**
* @brief Clear all GPIO dedicated control signals
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
// no dedicated ctrl pad
}
#ifdef __cplusplus
}
#endif
@@ -28,6 +28,7 @@
#include "soc/lp_system_reg.h"
#include "soc/pmu_struct.h"
#include "soc/usb_serial_jtag_struct.h"
#include "soc/cnnt_io_mux_struct.h"
#include "soc/clk_tree_defs.h"
#include "soc/interrupts.h"
#include "hal/gpio_types.h"
@@ -881,6 +882,17 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num
IO_MUX.gpio[gpio_num].mcu_oe = 1;
}
/**
* @brief Clear all GPIO dedicated control signals (e.g. sdmmc, emac)
*
* Set is done in each peripheral's own LL layer.
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_dedicated_ctrl(void)
{
CNNT_PAD_CTRL.ctrl.val = 0;
}
#ifdef __cplusplus
}
#endif
@@ -201,11 +201,13 @@ static inline void sdmmc_ll_mem_set_low_power_mode(sdmmc_dev_t *dev, sdmmc_ll_me
* @brief Set SDMMC pad pin dedicated ctrl
*
* @param dev Peripheral instance address
* @param slot Slot index
* @param enable True to enable, False to disable
*/
static inline void sdmmc_ll_pad_set_pin_dedicated_ctrl(sdmmc_dev_t *dev, bool enable)
static inline void sdmmc_ll_pad_set_pin_dedicated_ctrl(sdmmc_dev_t *dev, uint32_t slot, bool enable)
{
(void)dev;
(void)slot;
(void)enable;
}
@@ -234,11 +234,13 @@ static inline void sdmmc_ll_mem_set_low_power_mode(sdmmc_dev_t *dev, sdmmc_ll_me
* @brief Set SDMMC pad pin dedicated ctrl
*
* @param dev Peripheral instance address
* @param slot Slot index
* @param enable True to enable, False to disable
*/
static inline void sdmmc_ll_pad_set_pin_dedicated_ctrl(sdmmc_dev_t *dev, bool enable)
static inline void sdmmc_ll_pad_set_pin_dedicated_ctrl(sdmmc_dev_t *dev, uint32_t slot, bool enable)
{
(void)dev;
(void)slot;
(void)enable;
}
@@ -210,11 +210,13 @@ static inline void sdmmc_ll_mem_set_low_power_mode(sdmmc_dev_t *dev, sdmmc_ll_me
* @brief Set SDMMC pad pin dedicated ctrl
*
* @param dev Peripheral instance address
* @param slot Slot index
* @param enable True to enable, False to disable
*/
static inline void sdmmc_ll_pad_set_pin_dedicated_ctrl(sdmmc_dev_t *dev, bool enable)
static inline void sdmmc_ll_pad_set_pin_dedicated_ctrl(sdmmc_dev_t *dev, uint32_t slot, bool enable)
{
(void)dev;
(void)slot;
(void)enable;
}
@@ -233,14 +233,20 @@ static inline void sdmmc_ll_mem_set_low_power_mode(sdmmc_dev_t *dev, sdmmc_ll_me
/**
* @brief Set SDMMC pad pin dedicated ctrl
*
* Enable it when the slot is in use, disable it when the slot is released, so
* that the pads can be used as normal GPIOs again.
*
* @param dev Peripheral instance address
* @param slot Slot index
* @param enable True to enable, False to disable
*/
static inline void sdmmc_ll_pad_set_pin_dedicated_ctrl(sdmmc_dev_t *dev, bool enable)
static inline void sdmmc_ll_pad_set_pin_dedicated_ctrl(sdmmc_dev_t *dev, uint32_t slot, bool enable)
{
CNNT_PAD_CTRL.ctrl.sdio_pad_pin_ctrl_ded_sel = enable;
// only slot 0 is routed to the dedicated SDIO pads, slot 1 doesn't rely on this bit
if (slot == 0) {
CNNT_PAD_CTRL.ctrl.sdio_pad_pin_ctrl_ded_sel = enable;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define sdmmc_ll_pad_set_pin_dedicated_ctrl(...) do { \
@@ -7,6 +7,8 @@
#pragma once
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "hal/gpio_ll.h"
#ifdef __cplusplus
extern "C" {
@@ -39,6 +41,15 @@ void esp_sleep_gpio_pupd_config_workaround_apply(void);
void esp_sleep_gpio_pupd_config_workaround_unapply(void);
#endif // CONFIG_IDF_TARGET_ESP32
/**
* @brief Clear all GPIO dedicated control signals
*/
FORCE_INLINE_ATTR void esp_sleep_gpio_clear_dedicated_ctrl(void)
{
gpio_ll_clear_dedicated_ctrl();
}
#ifdef __cplusplus
}
#endif
+1 -1
View File
@@ -116,7 +116,7 @@ void esp_sleep_gpio_pupd_config_workaround_unapply(void)
}
}
}
#endif
#endif // CONFIG_IDF_TARGET_ESP32
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
void esp_sleep_config_gpio_isolate(void)
+4 -43
View File
@@ -41,6 +41,7 @@
#include "hal/efuse_hal.h"
#include "hal/rtc_io_hal.h"
#include "hal/clk_tree_hal.h"
#include "rom/rtc.h"
#if RNG_LL_NEEDS_RESET_WHEN_WAKEUP
#include "hal/rng_ll.h"
@@ -66,6 +67,7 @@
#include "soc/rtc.h"
#include "hal/clk_gate_ll.h"
#include "hal/clk_tree_ll.h"
#if SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED || SOC_SLEEP_TGWDT_STOP_WORKAROUND
#include "hal/wdt_hal.h"
@@ -80,6 +82,7 @@
#endif
#include "hal/temperature_sensor_hal.h"
#include "hal/mspi_ll.h"
#include "hal/gpio_ll.h"
#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE
#include "hal/lp_aon_hal.h"
#endif
@@ -99,62 +102,19 @@
#include "esp_private/esp_task_wdt.h"
#include "esp_private/sar_periph_ctrl.h"
#if SOC_PM_SUPPORT_EXT1_WAKEUP && SOC_RTCIO_PIN_COUNT > 0
#include "esp_private/sleep_gpio.h"
#endif
#ifdef CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/rtc.h"
#include "esp_private/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/rtc.h"
#include "soc/extmem_reg.h"
#include "esp_private/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C2
#include "esp32c2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/rtc.h"
#include "hal/gpio_ll.h"
#include "hal/clk_gate_ll.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/rtc.h"
#include "hal/gpio_ll.h"
#include "hal/clk_gate_ll.h"
#elif CONFIG_IDF_TARGET_ESP32C61
#include "esp32c61/rom/rtc.h"
#include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h"
#include "soc/extmem_reg.h"
#include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32H21
#include "esp32h21/rom/rtc.h"
#include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32H4
#include "esp32h4/rom/rtc.h"
#include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/rtc.h"
#include "hal/gpio_ll.h"
#include "hal/clk_gate_ll.h"
#elif CONFIG_IDF_TARGET_ESP32S31
#include "esp32s31/rom/rtc.h"
#include "hal/gpio_ll.h"
#include "hal/clk_gate_ll.h"
#endif
#if CONFIG_ESP_INT_WDT && CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
#include "esp_private/eco3_livelock_workaround.h"
#endif
#if SOC_MSPI_HAS_INDEPENT_IOMUX
#include "hal/mspi_ll.h"
#endif
#include "hal/rtc_timer_hal.h"
#if SOC_VBAT_SUPPORTED
@@ -872,6 +832,7 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
}
#endif
if (deep_sleep) {
esp_sleep_gpio_clear_dedicated_ctrl();
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
esp_sleep_isolate_digital_gpio(true);
#endif