From 1d2ffd5941d941d70b98644725e8903e07c8e14f Mon Sep 17 00:00:00 2001 From: hebinglin Date: Mon, 1 Sep 2025 20:29:48 +0800 Subject: [PATCH] fix(hal): fix the issue of dual-core contention for RTC_CNTL regs --- components/bt/controller/esp32c3/bt.c | 26 +++++++++++----- components/esp_driver_gpio/src/gpio.c | 25 ++++++++++++---- .../include/esp_private/periph_ctrl.h | 2 +- components/esp_hw_support/periph_ctrl.c | 2 +- components/esp_hw_support/rtc_module.c | 21 +++++++++---- components/esp_phy/src/phy_init.c | 19 +++++++++--- components/hal/esp32/include/hal/gpio_ll.h | 16 ++++++++-- components/hal/esp32c2/include/hal/gpio_ll.h | 30 +++++++++++++++---- components/hal/esp32c3/include/hal/gpio_ll.h | 30 +++++++++++++++---- components/hal/esp32s2/include/hal/gpio_ll.h | 30 +++++++++++++++---- components/hal/esp32s3/include/hal/gpio_ll.h | 30 +++++++++++++++---- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32/include/soc/soc_caps.h | 4 +++ .../esp32c2/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32c2/include/soc/soc_caps.h | 4 +++ .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32c3/include/soc/soc_caps.h | 4 +++ .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32s2/include/soc/soc_caps.h | 4 +++ .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32s3/include/soc/soc_caps.h | 4 +++ components/ulp/ulp_fsm/ulp.c | 19 ++++++++++-- components/ulp/ulp_riscv/ulp_riscv.c | 25 +++++++++++----- 23 files changed, 258 insertions(+), 57 deletions(-) diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index 6dcefcb0f8..7a91341f90 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -69,6 +69,8 @@ #define BT_LOG_TAG "BLE_INIT" +#define RTC_CNTL_ATOMIC() PERIPH_RCC_ATOMIC() + #define BTDM_INIT_PERIOD (5000) /* ms */ /* Low Power Clock Selection */ @@ -805,8 +807,10 @@ void IRAM_ATTR btdm_hw_mac_power_down_wrapper(void) #if CONFIG_MAC_BB_PD #if SOC_PM_SUPPORT_BT_PD // Bluetooth module power down - SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); - SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + RTC_CNTL_ATOMIC() { + SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + } #endif esp_mac_bb_power_down(); #endif @@ -817,8 +821,10 @@ void IRAM_ATTR btdm_hw_mac_power_up_wrapper(void) #if CONFIG_MAC_BB_PD #if SOC_PM_SUPPORT_BT_PD // Bluetooth module power up - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + RTC_CNTL_ATOMIC() { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + } #endif esp_mac_bb_power_up(); #endif @@ -835,8 +841,10 @@ static inline void esp_bt_power_domain_on(void) { // Bluetooth module power up #if SOC_PM_SUPPORT_BT_PD - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + RTC_CNTL_ATOMIC() { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + } #endif esp_wifi_bt_power_domain_on(); } @@ -845,8 +853,10 @@ static inline void esp_bt_power_domain_off(void) { // Bluetooth module power down #if SOC_PM_SUPPORT_BT_PD - SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); - SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + RTC_CNTL_ATOMIC() { + SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + } #endif esp_wifi_bt_power_domain_off(); } diff --git a/components/esp_driver_gpio/src/gpio.c b/components/esp_driver_gpio/src/gpio.c index af1c6a62e9..b0bf670ca1 100644 --- a/components/esp_driver_gpio/src/gpio.c +++ b/components/esp_driver_gpio/src/gpio.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,7 @@ #include "hal/gpio_hal.h" #include "esp_private/esp_gpio_reserve.h" #include "esp_private/io_mux.h" +#include "esp_private/periph_ctrl.h" #if (SOC_RTCIO_PIN_COUNT > 0) #include "hal/rtc_io_hal.h" @@ -37,6 +38,12 @@ static const char *GPIO_TAG = "gpio"; #define SOC_GPIO_SUPPORT_RTC_INDEPENDENT 0 #endif +#if SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS +#define RTC_CNTL_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RTC_CNTL_ATOMIC() +#endif + typedef struct { gpio_isr_t fn; /*!< isr function */ void *args; /*!< isr function args */ @@ -761,14 +768,18 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num) void gpio_deep_sleep_hold_en(void) { portENTER_CRITICAL(&gpio_context.gpio_spinlock); - gpio_hal_deep_sleep_hold_en(gpio_context.gpio_hal); + RTC_CNTL_ATOMIC() { + gpio_hal_deep_sleep_hold_en(gpio_context.gpio_hal); + } portEXIT_CRITICAL(&gpio_context.gpio_spinlock); } void gpio_deep_sleep_hold_dis(void) { portENTER_CRITICAL(&gpio_context.gpio_spinlock); - gpio_hal_deep_sleep_hold_dis(gpio_context.gpio_hal); + RTC_CNTL_ATOMIC() { + gpio_hal_deep_sleep_hold_dis(gpio_context.gpio_hal); + } portEXIT_CRITICAL(&gpio_context.gpio_spinlock); } #endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP @@ -780,7 +791,9 @@ esp_err_t IRAM_ATTR gpio_force_hold_all() rtc_gpio_force_hold_en_all(); #endif portENTER_CRITICAL(&gpio_context.gpio_spinlock); - gpio_hal_force_hold_all(); + RTC_CNTL_ATOMIC() { + gpio_hal_force_hold_all(); + } portEXIT_CRITICAL(&gpio_context.gpio_spinlock); return ESP_OK; } @@ -788,7 +801,9 @@ esp_err_t IRAM_ATTR gpio_force_hold_all() esp_err_t IRAM_ATTR gpio_force_unhold_all() { portENTER_CRITICAL(&gpio_context.gpio_spinlock); - gpio_hal_force_unhold_all(); + RTC_CNTL_ATOMIC() { + gpio_hal_force_unhold_all(); + } portEXIT_CRITICAL(&gpio_context.gpio_spinlock); #if SOC_RTCIO_HOLD_SUPPORTED rtc_gpio_force_hold_dis_all(); diff --git a/components/esp_hw_support/include/esp_private/periph_ctrl.h b/components/esp_hw_support/include/esp_private/periph_ctrl.h index a126750ba1..57e15aea8b 100644 --- a/components/esp_hw_support/include/esp_private/periph_ctrl.h +++ b/components/esp_hw_support/include/esp_private/periph_ctrl.h @@ -48,7 +48,7 @@ extern "C" { * @note User code protected by this macro should be as short as possible, because it's a critical section */ #define PERIPH_RCC_ATOMIC() \ - for (int _rc_cnt = 1, __DECLARE_RCC_ATOMIC_ENV; \ + for (int _rc_cnt = 1, __DECLARE_RCC_ATOMIC_ENV __attribute__((unused)); \ _rc_cnt ? (periph_rcc_enter(), 1) : 0; \ periph_rcc_exit(), _rc_cnt--) diff --git a/components/esp_hw_support/periph_ctrl.c b/components/esp_hw_support/periph_ctrl.c index 0ce975e308..519bef1d0d 100644 --- a/components/esp_hw_support/periph_ctrl.c +++ b/components/esp_hw_support/periph_ctrl.c @@ -17,7 +17,7 @@ /// @brief For simplicity and backward compatible, we are using the same spin lock for both bus clock on/off and reset /// @note We may want to split them into two spin locks in the future -static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED; +static portMUX_TYPE __attribute__((unused)) periph_spinlock = portMUX_INITIALIZER_UNLOCKED; static uint8_t ref_counts[PERIPH_MODULE_MAX] = {0}; diff --git a/components/esp_hw_support/rtc_module.c b/components/esp_hw_support/rtc_module.c index dbc5b495a8..19defdf747 100644 --- a/components/esp_hw_support/rtc_module.c +++ b/components/esp_hw_support/rtc_module.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,8 +18,15 @@ #include "esp_intr_alloc.h" #include "sys/lock.h" #include "esp_private/rtc_ctrl.h" +#include "esp_private/periph_ctrl.h" #include "esp_attr.h" +#if SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS +#define RTC_CNTL_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RTC_CNTL_ATOMIC() +#endif + #ifndef NDEBUG // Enable built-in checks in queue.h in debug builds @@ -187,8 +194,10 @@ IRAM_ATTR void rtc_isr_noniram_disable(uint32_t cpu) { #if SOC_LP_PERIPH_SHARE_INTERRUPT // TODO: IDF-8008 if (rtc_isr_cpu == cpu) { - rtc_intr_enabled |= RTCCNTL.int_ena.val; - RTCCNTL.int_ena.val &= rtc_intr_cache; + RTC_CNTL_ATOMIC() { + rtc_intr_enabled |= RTCCNTL.int_ena.val; + RTCCNTL.int_ena.val &= rtc_intr_cache; + } } #endif } @@ -197,8 +206,10 @@ IRAM_ATTR void rtc_isr_noniram_enable(uint32_t cpu) { #if SOC_LP_PERIPH_SHARE_INTERRUPT // TODO: IDF-8008 if (rtc_isr_cpu == cpu) { - RTCCNTL.int_ena.val = rtc_intr_enabled; - rtc_intr_enabled = 0; + RTC_CNTL_ATOMIC() { + RTCCNTL.int_ena.val = rtc_intr_enabled; + rtc_intr_enabled = 0; + } } #endif } diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index 16ca899e31..ac5bb4d01c 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -88,6 +88,11 @@ static uint32_t* s_phy_digital_regs_mem = NULL; static uint8_t s_phy_modem_init_ref = 0; #endif +#if SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS +#define RTC_CNTL_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RTC_CNTL_ATOMIC() +#endif #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED @@ -398,7 +403,9 @@ void IRAM_ATTR esp_wifi_bt_power_domain_on(void) #if SOC_PM_MODEM_PD_BY_SW // TODO: [ESP32C5] IDF-8667 _lock_acquire(&s_wifi_bt_pd_controller.lock); if (s_wifi_bt_pd_controller.count++ == 0) { - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + RTC_CNTL_ATOMIC() { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + } esp_rom_delay_us(10); wifi_bt_common_module_enable(); #if CONFIG_IDF_TARGET_ESP32 @@ -409,7 +416,9 @@ void IRAM_ATTR esp_wifi_bt_power_domain_on(void) SET_PERI_REG_MASK(SYSCON_WIFI_RST_EN_REG, MODEM_RESET_FIELD_WHEN_PU); CLEAR_PERI_REG_MASK(SYSCON_WIFI_RST_EN_REG, MODEM_RESET_FIELD_WHEN_PU); #endif - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); + RTC_CNTL_ATOMIC() { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); + } wifi_bt_common_module_disable(); } _lock_release(&s_wifi_bt_pd_controller.lock); @@ -423,8 +432,10 @@ void esp_wifi_bt_power_domain_off(void) #if SOC_PM_MODEM_PD_BY_SW // TODO: [ESP32C5] IDF-8667 _lock_acquire(&s_wifi_bt_pd_controller.lock); if (--s_wifi_bt_pd_controller.count == 0) { - SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); - SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + RTC_CNTL_ATOMIC() { + SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); + SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + } } _lock_release(&s_wifi_bt_pd_controller.lock); #endif // SOC_PM_MODEM_PD_BY_SW diff --git a/components/hal/esp32/include/hal/gpio_ll.h b/components/hal/esp32/include/hal/gpio_ll.h index ba3640bbd2..6591268448 100644 --- a/components/hal/esp32/include/hal/gpio_ll.h +++ b/components/hal/esp32/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -601,22 +601,32 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_en(__VA_ARGS__) + /** * @brief Disable all digital gpio pad hold function during Deep-sleep. * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_dis(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_dis(__VA_ARGS__) + /** * @brief Get deep sleep hold status * diff --git a/components/hal/esp32c2/include/hal/gpio_ll.h b/components/hal/esp32c2/include/hal/gpio_ll.h index c1c71c6c74..628e8dfeca 100644 --- a/components/hal/esp32c2/include/hal/gpio_ll.h +++ b/components/hal/esp32c2/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -407,22 +407,32 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_en(__VA_ARGS__) + /** * @brief Disable all digital gpio pad hold function during Deep-sleep. * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_dis(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_dis(__VA_ARGS__) + /** * @brief Get deep sleep hold status * @@ -574,18 +584,23 @@ static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in * @brief Force hold all digital(VDD3P3_CPU) and rtc(VDD3P3_RTC) gpio pads. * @note GPIO force hold, whether the chip in sleep mode or wakeup mode. */ -static inline void gpio_ll_force_hold_all(void) +static inline void _gpio_ll_force_hold_all(void) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD); SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, RTC_CNTL_PWC_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_force_hold_all(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_force_hold_all(__VA_ARGS__) + /** * @brief Force unhold all digital(VDD3P3_CPU) and rtc(VDD3P3_RTC) gpio pads. * @note GPIO force unhold, whether the chip in sleep mode or wakeup mode. */ -static inline void gpio_ll_force_unhold_all(void) +static inline void _gpio_ll_force_unhold_all(void) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); @@ -593,6 +608,11 @@ static inline void gpio_ll_force_unhold_all(void) CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, RTC_CNTL_PWC_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_force_unhold_all(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_force_unhold_all(__VA_ARGS__) + /** * @brief Enable GPIO pin used for wakeup from sleep. * diff --git a/components/hal/esp32c3/include/hal/gpio_ll.h b/components/hal/esp32c3/include/hal/gpio_ll.h index 809ddf9a31..728f7089e1 100644 --- a/components/hal/esp32c3/include/hal/gpio_ll.h +++ b/components/hal/esp32c3/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -393,22 +393,32 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_en(__VA_ARGS__) + /** * @brief Disable all digital gpio pad hold function during Deep-sleep. * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_dis(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_dis(__VA_ARGS__) + /** * @brief Get deep sleep hold status * @@ -564,18 +574,23 @@ static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in * @brief Force hold all digital(VDD3P3_CPU) and rtc(VDD3P3_RTC) gpio pads. * @note GPIO force hold, whether the chip in sleep mode or wakeup mode. */ -static inline void gpio_ll_force_hold_all(void) +static inline void _gpio_ll_force_hold_all(void) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD); SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, RTC_CNTL_PWC_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_force_hold_all(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_force_hold_all(__VA_ARGS__) + /** * @brief Force unhold all digital(VDD3P3_CPU) and rtc(VDD3P3_RTC) gpio pads. * @note GPIO force unhold, whether the chip in sleep mode or wakeup mode. */ -static inline void gpio_ll_force_unhold_all(void) +static inline void _gpio_ll_force_unhold_all(void) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); @@ -583,6 +598,11 @@ static inline void gpio_ll_force_unhold_all(void) CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, RTC_CNTL_PWC_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_force_unhold_all(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_force_unhold_all(__VA_ARGS__) + /** * @brief Enable GPIO pin used for wakeup from sleep. * diff --git a/components/hal/esp32s2/include/hal/gpio_ll.h b/components/hal/esp32s2/include/hal/gpio_ll.h index f6b46bf1bd..8cc66889ce 100644 --- a/components/hal/esp32s2/include/hal/gpio_ll.h +++ b/components/hal/esp32s2/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -427,22 +427,32 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_en(__VA_ARGS__) + /** * @brief Disable all digital gpio pad hold function during Deep-sleep. * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_dis(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_dis(__VA_ARGS__) + /** * @brief Get deep sleep hold status * @@ -585,23 +595,33 @@ static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in * @brief Force hold digital gpio pad. * @note GPIO force hold, whether the chip in sleep mode or wakeup mode. */ -static inline void gpio_ll_force_hold_all(void) +static inline void _gpio_ll_force_hold_all(void) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_force_hold_all(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_force_hold_all(__VA_ARGS__) + /** * @brief Force unhold digital gpio pad. * @note GPIO force unhold, whether the chip in sleep mode or wakeup mode. */ -static inline void gpio_ll_force_unhold_all(void) +static inline void _gpio_ll_force_unhold_all(void) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_force_unhold_all(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_force_unhold_all(__VA_ARGS__) + /** * @brief Enable GPIO pin used for wakeup from sleep. * diff --git a/components/hal/esp32s3/include/hal/gpio_ll.h b/components/hal/esp32s3/include/hal/gpio_ll.h index eda75b8074..e7d41191f5 100644 --- a/components/hal/esp32s3/include/hal/gpio_ll.h +++ b/components/hal/esp32s3/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -416,22 +416,32 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_en(__VA_ARGS__) + /** * @brief Disable all digital gpio pad hold function during Deep-sleep. * * @param hw Peripheral GPIO hardware instance address. */ -static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) +static inline void _gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_deep_sleep_hold_dis(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_deep_sleep_hold_dis(__VA_ARGS__) + /** * @brief Get deep sleep hold status * @@ -578,23 +588,33 @@ static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in * @brief Force hold digital gpio pad. * @note GPIO force hold, whether the chip in sleep mode or wakeup mode. */ -static inline void gpio_ll_force_hold_all(void) +static inline void _gpio_ll_force_hold_all(void) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_force_hold_all(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_force_hold_all(__VA_ARGS__) + /** * @brief Force unhold digital gpio pad. * @note GPIO force unhold, whether the chip in sleep mode or wakeup mode. */ -static inline void gpio_ll_force_unhold_all(void) +static inline void _gpio_ll_force_unhold_all(void) { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD); } +/// 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 +/// When operating RTC_CNTL_DIG_ISO_REG, PERIPH_RCC_ATOMIC() must be used to ensure atomicity. +#define gpio_ll_force_unhold_all(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gpio_ll_force_unhold_all(__VA_ARGS__) + /** * @brief Enable GPIO pin used for wakeup from sleep. * diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 9863806644..30085fb975 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -619,6 +619,10 @@ config SOC_RTCIO_WAKE_SUPPORTED bool default y +config SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS + bool + default y + config SOC_SDM_GROUPS int default 1 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index efbf5c650c..127acdd1e9 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -289,6 +289,10 @@ #define SOC_RTCIO_HOLD_SUPPORTED 1 #define SOC_RTCIO_WAKE_SUPPORTED 1 +/* RTC_CNTL registers on this SoC are not atomic and require software protection + * (e.g., spinlocks) when accessed from multiple cores or threads. */ +#define SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS 1 + /*-------------------------- Sigma Delta Modulator CAPS -----------------*/ #define SOC_SDM_GROUPS 1U #define SOC_SDM_CHANNELS_PER_GROUP 8 diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 12e0ea0b2c..b28647bee4 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -439,6 +439,10 @@ config SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM int default 108 +config SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS + bool + default y + config SOC_RTCIO_PIN_COUNT int default 0 diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 9827a2b58b..455bb93952 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -193,6 +193,10 @@ #define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) +/* RTC_CNTL registers on this SoC are not atomic and require software protection + * (e.g., spinlocks) when accessed from multiple cores or threads. */ +#define SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS 1 + /*-------------------------- RTCIO CAPS --------------------------------------*/ /* No dedicated RTCIO subsystem on ESP32-C2. RTC functions are still supported * for hold, wake & 32kHz crystal functions - via rtc_cntl_reg */ diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index be3a00da01..2fea238111 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -639,6 +639,10 @@ config SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM int default 108 +config SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS + bool + default y + config SOC_SLEEP_SYSTIMER_STALL_WORKAROUND bool default y diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 17ed62de5b..6f7ec9de14 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -262,6 +262,10 @@ #define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) +/* RTC_CNTL registers on this SoC are not atomic and require software protection + * (e.g., spinlocks) when accessed from multiple cores or threads. */ +#define SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS 1 + #define SOC_SLEEP_SYSTIMER_STALL_WORKAROUND 1 #define SOC_SLEEP_TGWDT_STOP_WORKAROUND 1 diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index a6cdc87bef..fcbf902308 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -407,6 +407,10 @@ config SOC_GPIO_CLOCKOUT_CHANNEL_NUM int default 3 +config SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS + bool + default y + config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM int default 8 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 09a5e2d668..8205e19211 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -182,6 +182,10 @@ #define SOC_GPIO_CLOCKOUT_BY_IO_MUX (1) #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) +/* RTC_CNTL registers on this SoC are not atomic and require software protection + * (e.g., spinlocks) when accessed from multiple cores or threads. */ +#define SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS 1 + /*-------------------------- Dedicated GPIO CAPS ---------------------------------------*/ #define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 1b9e5ab80d..8a4832aad9 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -823,6 +823,10 @@ config SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH int default 128 +config SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS + bool + default y + config SOC_RTCIO_PIN_COUNT int default 22 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 5e61125992..bf1543cee3 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -314,6 +314,10 @@ #define SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH (128) #define SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH >> 3) +/* RTC_CNTL registers on this SoC are not atomic and require software protection + * (e.g., spinlocks) when accessed from multiple cores or threads. */ +#define SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS 1 + /*-------------------------- RTCIO CAPS --------------------------------------*/ #define SOC_RTCIO_PIN_COUNT 22 #define SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1 /* This macro indicates that the target has separate RTC IOMUX hardware feature, diff --git a/components/ulp/ulp_fsm/ulp.c b/components/ulp/ulp_fsm/ulp.c index e03751b0eb..220146b94f 100644 --- a/components/ulp/ulp_fsm/ulp.c +++ b/components/ulp/ulp_fsm/ulp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,13 @@ #include "esp_check.h" #include "esp_private/rtc_ctrl.h" +#include "esp_private/periph_ctrl.h" + +#if SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS +#define RTC_CNTL_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RTC_CNTL_ATOMIC() +#endif typedef struct { uint32_t magic; @@ -46,7 +53,10 @@ static const char* TAG = "ulp"; esp_err_t ulp_isr_register(intr_handler_t fn, void *arg) { ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TAG, "ULP ISR is NULL"); - REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M); + /* Enable the interrupt bit atomically to avoid race condition with other code accessing RTC_CNTL_INT_ENA_REG */ + RTC_CNTL_ATOMIC() { + REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M); + } #if CONFIG_IDF_TARGET_ESP32 return rtc_isr_register(fn, arg, RTC_CNTL_SAR_INT_ST_M, 0); #else @@ -57,7 +67,10 @@ esp_err_t ulp_isr_register(intr_handler_t fn, void *arg) esp_err_t ulp_isr_deregister(intr_handler_t fn, void *arg) { ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TAG, "ULP ISR is NULL"); - REG_CLR_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M); + /* Disable the interrupt bit atomically to avoid race condition with other code accessing RTC_CNTL_INT_ENA_REG */ + RTC_CNTL_ATOMIC() { + REG_CLR_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M); + } return rtc_isr_deregister(fn, arg); } diff --git a/components/ulp/ulp_riscv/ulp_riscv.c b/components/ulp/ulp_riscv/ulp_riscv.c index d958c4bc0b..4f37464ff4 100644 --- a/components/ulp/ulp_riscv/ulp_riscv.c +++ b/components/ulp/ulp_riscv/ulp_riscv.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,13 @@ #include "esp_rom_sys.h" #include "esp_check.h" #include "esp_private/rtc_ctrl.h" +#include "esp_private/periph_ctrl.h" + +#if SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS +#define RTC_CNTL_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RTC_CNTL_ATOMIC() +#endif __attribute__((unused)) static const char* TAG = "ulp-riscv"; @@ -44,8 +51,10 @@ esp_err_t ulp_riscv_isr_register(intr_handler_t fn, void *arg, uint32_t mask) /* Register the RTC ISR */ ESP_RETURN_ON_ERROR(rtc_isr_register(fn, arg, mask, 0), TAG, "rtc_isr_register() failed"); - /* Enable the interrupt bits */ - SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, mask); + /* Enable the interrupt bits atomically to avoid race condition with other code accessing RTC_CNTL_INT_ENA_REG */ + RTC_CNTL_ATOMIC() { + SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, mask); + } return ESP_OK; } @@ -64,8 +73,10 @@ esp_err_t ulp_riscv_isr_deregister(intr_handler_t fn, void *arg, uint32_t mask) /* Make sure we disable only the ULP interrupt bits */ mask &= (RTC_CNTL_COCPU_INT_ST_M | RTC_CNTL_COCPU_TRAP_INT_ST_M); - /* Disable the interrupt bits */ - CLEAR_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, mask); + /* Disable the interrupt bits atomically to avoid race condition with other code accessing RTC_CNTL_INT_ENA_REG */ + RTC_CNTL_ATOMIC() { + CLEAR_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, mask); + } /* Deregister the RTC ISR */ ESP_RETURN_ON_ERROR(rtc_isr_deregister(fn, arg), TAG, "rtc_isr_deregister() failed"); @@ -103,7 +114,7 @@ esp_err_t ulp_riscv_config_and_run(ulp_riscv_cfg_t* cfg) /* Reset COCPU when power on. */ SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN); - /* The coprocessor cpu trap signal doesnt have a stable reset value, + /* The coprocessor cpu trap signal doesn't have a stable reset value, force ULP-RISC-V clock on to stop RTC_COCPU_TRAP_TRIG_EN from waking the CPU*/ SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLK_FO); @@ -123,7 +134,7 @@ esp_err_t ulp_riscv_config_and_run(ulp_riscv_cfg_t* cfg) /* Reset COCPU when power on. */ SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN); - /* The coprocessor cpu trap signal doesnt have a stable reset value, + /* The coprocessor cpu trap signal doesn't have a stable reset value, force ULP-RISC-V clock on to stop RTC_COCPU_TRAP_TRIG_EN from waking the CPU*/ SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLK_FO);