From fde22b2a2a090190d078fc875d239856fcc59d37 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 20 Jun 2024 23:46:21 +0800 Subject: [PATCH] fix(rmt): power up memory block --- components/driver/deprecated/driver/rmt.h | 8 ++--- components/driver/deprecated/rmt_legacy.c | 10 ++++-- components/hal/esp32/include/hal/rmt_ll.h | 31 ++++++++++++---- components/hal/esp32c3/include/hal/rmt_ll.h | 38 ++++++++++++++------ components/hal/esp32c6/include/hal/rmt_ll.h | 38 ++++++++++++++------ components/hal/esp32h2/include/hal/rmt_ll.h | 38 ++++++++++++++------ components/hal/esp32s2/include/hal/rmt_ll.h | 38 ++++++++++++++------ components/hal/esp32s3/include/hal/rmt_ll.h | 40 +++++++++++++++------ components/hal/rmt_hal.c | 4 +-- 9 files changed, 180 insertions(+), 65 deletions(-) diff --git a/components/driver/deprecated/driver/rmt.h b/components/driver/deprecated/driver/rmt.h index c99bde31be..e162b147aa 100644 --- a/components/driver/deprecated/driver/rmt.h +++ b/components/driver/deprecated/driver/rmt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -152,10 +152,10 @@ esp_err_t rmt_set_tx_carrier(rmt_channel_t channel, bool carrier_en, uint16_t hi esp_err_t rmt_set_mem_pd(rmt_channel_t channel, bool pd_en); /** -* @brief Get RMT memory low power mode. +* @brief Check if the RMT memory is force powered down * -* @param channel RMT channel -* @param pd_en Pointer to accept RMT memory low power mode. +* @param channel RMT channel (actually this function is configured for all channels) +* @param pd_en Pointer to accept the result * * @return * - ESP_ERR_INVALID_ARG Parameter error diff --git a/components/driver/deprecated/rmt_legacy.c b/components/driver/deprecated/rmt_legacy.c index 00fea4563e..f8b17e62ab 100644 --- a/components/driver/deprecated/rmt_legacy.c +++ b/components/driver/deprecated/rmt_legacy.c @@ -127,6 +127,7 @@ static void rmt_module_enable(void) if (rmt_contex.rmt_module_enabled == false) { periph_module_reset(rmt_periph_signals.groups[0].module); periph_module_enable(rmt_periph_signals.groups[0].module); + rmt_ll_mem_power_by_pmu(rmt_contex.hal.regs); rmt_contex.rmt_module_enabled = true; } RMT_EXIT_CRITICAL(); @@ -137,6 +138,7 @@ static void rmt_module_disable(void) { RMT_ENTER_CRITICAL(); if (rmt_contex.rmt_module_enabled == true) { + rmt_ll_mem_force_power_off(rmt_contex.hal.regs); periph_module_disable(rmt_periph_signals.groups[0].module); rmt_contex.rmt_module_enabled = false; } @@ -234,7 +236,11 @@ esp_err_t rmt_set_mem_pd(rmt_channel_t channel, bool pd_en) { ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); RMT_ENTER_CRITICAL(); - rmt_ll_power_down_mem(rmt_contex.hal.regs, pd_en); + if (pd_en) { + rmt_ll_mem_force_power_off(rmt_contex.hal.regs); + } else { + rmt_ll_mem_power_by_pmu(rmt_contex.hal.regs); + } RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -243,7 +249,7 @@ esp_err_t rmt_get_mem_pd(rmt_channel_t channel, bool *pd_en) { ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); RMT_ENTER_CRITICAL(); - *pd_en = rmt_ll_is_mem_powered_down(rmt_contex.hal.regs); + *pd_en = rmt_ll_is_mem_force_powered_down(rmt_contex.hal.regs); RMT_EXIT_CRITICAL(); return ESP_OK; } diff --git a/components/hal/esp32/include/hal/rmt_ll.h b/components/hal/esp32/include/hal/rmt_ll.h index d69998f38e..0344cd7242 100644 --- a/components/hal/esp32/include/hal/rmt_ll.h +++ b/components/hal/esp32/include/hal/rmt_ll.h @@ -52,14 +52,33 @@ static inline void rmt_ll_enable_periph_clock(rmt_dev_t *dev, bool enable) } /** - * @brief Power down memory + * @brief Force power on the RMT memory block, regardless of the outside PMU logic * * @param dev Peripheral instance address - * @param enable True to power down, False to power up */ -static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) +static inline void rmt_ll_mem_force_power_on(rmt_dev_t *dev) { - dev->conf_ch[0].conf0.mem_pd = enable; // Only conf0 register of channel0 has `mem_pd` + (void)dev; +} + +/** + * @brief Force power off the RMT memory block, regardless of the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_force_power_off(rmt_dev_t *dev) +{ + dev->conf_ch[0].conf0.mem_pd = 1; +} + +/** + * @brief Power control the RMT memory block by the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_power_by_pmu(rmt_dev_t *dev) +{ + dev->conf_ch[0].conf0.mem_pd = 0; } /** @@ -84,7 +103,7 @@ static inline void rmt_ll_enable_mem_access_nonfifo(rmt_dev_t *dev, bool enable) * @param divider_numerator Numerator part of the divider */ static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, rmt_clock_source_t src, - uint32_t divider_integral, uint32_t divider_denominator, uint32_t divider_numerator) + uint32_t divider_integral, uint32_t divider_denominator, uint32_t divider_numerator) { (void)divider_integral; (void)divider_denominator; @@ -595,7 +614,7 @@ static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel return dev->conf_ch[channel].conf1.idle_out_lv; } -static inline bool rmt_ll_is_mem_powered_down(rmt_dev_t *dev) +static inline bool rmt_ll_is_mem_force_powered_down(rmt_dev_t *dev) { // Only conf0 register of channel0 has `mem_pd` return dev->conf_ch[0].conf0.mem_pd; diff --git a/components/hal/esp32c3/include/hal/rmt_ll.h b/components/hal/esp32c3/include/hal/rmt_ll.h index 970b3570d2..121a9758fe 100644 --- a/components/hal/esp32c3/include/hal/rmt_ll.h +++ b/components/hal/esp32c3/include/hal/rmt_ll.h @@ -54,15 +54,36 @@ static inline void rmt_ll_enable_periph_clock(rmt_dev_t *dev, bool enable) } /** - * @brief Power down memory + * @brief Force power on the RMT memory block, regardless of the outside PMU logic * * @param dev Peripheral instance address - * @param enable True to power down, False to power up */ -static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) +static inline void rmt_ll_mem_force_power_on(rmt_dev_t *dev) { - dev->sys_conf.mem_force_pu = !enable; - dev->sys_conf.mem_force_pd = enable; + dev->sys_conf.mem_force_pu = 1; + dev->sys_conf.mem_force_pd = 0; +} + +/** + * @brief Force power off the RMT memory block, regardless of the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_force_power_off(rmt_dev_t *dev) +{ + dev->sys_conf.mem_force_pd = 1; + dev->sys_conf.mem_force_pu = 0; +} + +/** + * @brief Power control the RMT memory block by the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_power_by_pmu(rmt_dev_t *dev) +{ + dev->sys_conf.mem_force_pd = 0; + dev->sys_conf.mem_force_pu = 0; } /** @@ -779,12 +800,9 @@ static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel return dev->tx_conf[channel].idle_out_lv; } -static inline bool rmt_ll_is_mem_powered_down(rmt_dev_t *dev) +static inline bool rmt_ll_is_mem_force_powered_down(rmt_dev_t *dev) { - // the RTC domain can also power down RMT memory - // so it's probably not enough to detect whether it's powered down or not - // mem_force_pd has higher priority than mem_force_pu - return (dev->sys_conf.mem_force_pd) || !(dev->sys_conf.mem_force_pu); + return dev->sys_conf.mem_force_pd; } __attribute__((always_inline)) diff --git a/components/hal/esp32c6/include/hal/rmt_ll.h b/components/hal/esp32c6/include/hal/rmt_ll.h index 06075b330f..42477f373c 100644 --- a/components/hal/esp32c6/include/hal/rmt_ll.h +++ b/components/hal/esp32c6/include/hal/rmt_ll.h @@ -55,15 +55,36 @@ static inline void rmt_ll_enable_periph_clock(rmt_dev_t *dev, bool enable) } /** - * @brief Power down memory + * @brief Force power on the RMT memory block, regardless of the outside PMU logic * * @param dev Peripheral instance address - * @param enable True to power down, False to power up */ -static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) +static inline void rmt_ll_mem_force_power_on(rmt_dev_t *dev) { - dev->sys_conf.mem_force_pu = !enable; - dev->sys_conf.mem_force_pd = enable; + dev->sys_conf.mem_force_pu = 1; + dev->sys_conf.mem_force_pd = 0; +} + +/** + * @brief Force power off the RMT memory block, regardless of the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_force_power_off(rmt_dev_t *dev) +{ + dev->sys_conf.mem_force_pd = 1; + dev->sys_conf.mem_force_pu = 0; +} + +/** + * @brief Power control the RMT memory block by the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_power_by_pmu(rmt_dev_t *dev) +{ + dev->sys_conf.mem_force_pd = 0; + dev->sys_conf.mem_force_pu = 0; } /** @@ -794,12 +815,9 @@ static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel return dev->chnconf0[channel].idle_out_lv_chn; } -static inline bool rmt_ll_is_mem_powered_down(rmt_dev_t *dev) +static inline bool rmt_ll_is_mem_force_powered_down(rmt_dev_t *dev) { - // the RTC domain can also power down RMT memory - // so it's probably not enough to detect whether it's powered down or not - // mem_force_pd has higher priority than mem_force_pu - return (dev->sys_conf.mem_force_pd) || !(dev->sys_conf.mem_force_pu); + return dev->sys_conf.mem_force_pd; } __attribute__((always_inline)) diff --git a/components/hal/esp32h2/include/hal/rmt_ll.h b/components/hal/esp32h2/include/hal/rmt_ll.h index 105825f88f..ebd4615bfb 100644 --- a/components/hal/esp32h2/include/hal/rmt_ll.h +++ b/components/hal/esp32h2/include/hal/rmt_ll.h @@ -55,15 +55,36 @@ static inline void rmt_ll_enable_periph_clock(rmt_dev_t *dev, bool enable) } /** - * @brief Power down memory + * @brief Force power on the RMT memory block, regardless of the outside PMU logic * * @param dev Peripheral instance address - * @param enable True to power down, False to power up */ -static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) +static inline void rmt_ll_mem_force_power_on(rmt_dev_t *dev) { - dev->sys_conf.mem_force_pu = !enable; - dev->sys_conf.mem_force_pd = enable; + dev->sys_conf.mem_force_pu = 1; + dev->sys_conf.mem_force_pd = 0; +} + +/** + * @brief Force power off the RMT memory block, regardless of the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_force_power_off(rmt_dev_t *dev) +{ + dev->sys_conf.mem_force_pd = 1; + dev->sys_conf.mem_force_pu = 0; +} + +/** + * @brief Power control the RMT memory block by the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_power_by_pmu(rmt_dev_t *dev) +{ + dev->sys_conf.mem_force_pd = 0; + dev->sys_conf.mem_force_pu = 0; } /** @@ -788,12 +809,9 @@ static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel return dev->chnconf0[channel].idle_out_lv_chn; } -static inline bool rmt_ll_is_mem_powered_down(rmt_dev_t *dev) +static inline bool rmt_ll_is_mem_force_powered_down(rmt_dev_t *dev) { - // the RTC domain can also power down RMT memory - // so it's probably not enough to detect whether it's powered down or not - // mem_force_pd has higher priority than mem_force_pu - return (dev->sys_conf.mem_force_pd) || !(dev->sys_conf.mem_force_pu); + return dev->sys_conf.mem_force_pd; } __attribute__((always_inline)) diff --git a/components/hal/esp32s2/include/hal/rmt_ll.h b/components/hal/esp32s2/include/hal/rmt_ll.h index 841648312f..2d9a3389ce 100644 --- a/components/hal/esp32s2/include/hal/rmt_ll.h +++ b/components/hal/esp32s2/include/hal/rmt_ll.h @@ -55,15 +55,36 @@ static inline void rmt_ll_enable_periph_clock(rmt_dev_t *dev, bool enable) } /** - * @brief Power down memory + * @brief Force power on the RMT memory block, regardless of the outside PMU logic * * @param dev Peripheral instance address - * @param enable True to power down, False to power up */ -static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) +static inline void rmt_ll_mem_force_power_on(rmt_dev_t *dev) { - dev->apb_conf.mem_force_pu = !enable; - dev->apb_conf.mem_force_pd = enable; + dev->apb_conf.mem_force_pu = 1; + dev->apb_conf.mem_force_pd = 0; +} + +/** + * @brief Force power off the RMT memory block, regardless of the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_force_power_off(rmt_dev_t *dev) +{ + dev->apb_conf.mem_force_pd = 1; + dev->apb_conf.mem_force_pu = 0; +} + +/** + * @brief Power control the RMT memory block by the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_power_by_pmu(rmt_dev_t *dev) +{ + dev->apb_conf.mem_force_pd = 0; + dev->apb_conf.mem_force_pu = 0; } /** @@ -739,12 +760,9 @@ static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel return dev->conf_ch[channel].conf1.idle_out_lv_chn; } -static inline bool rmt_ll_is_mem_powered_down(rmt_dev_t *dev) +static inline bool rmt_ll_is_mem_force_powered_down(rmt_dev_t *dev) { - // the RTC domain can also power down RMT memory - // so it's probably not enough to detect whether it's powered down or not - // mem_force_pd has higher priority than mem_force_pu - return (dev->apb_conf.mem_force_pd) || !(dev->apb_conf.mem_force_pu); + return dev->apb_conf.mem_force_pd; } __attribute__((always_inline)) diff --git a/components/hal/esp32s3/include/hal/rmt_ll.h b/components/hal/esp32s3/include/hal/rmt_ll.h index 0dd673edd5..bb7e568066 100644 --- a/components/hal/esp32s3/include/hal/rmt_ll.h +++ b/components/hal/esp32s3/include/hal/rmt_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,15 +54,36 @@ static inline void rmt_ll_enable_periph_clock(rmt_dev_t *dev, bool enable) } /** - * @brief Power down memory + * @brief Force power on the RMT memory block, regardless of the outside PMU logic * * @param dev Peripheral instance address - * @param enable True to power down, False to power up */ -static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) +static inline void rmt_ll_mem_force_power_on(rmt_dev_t *dev) { - dev->sys_conf.mem_force_pu = !enable; - dev->sys_conf.mem_force_pd = enable; + dev->sys_conf.mem_force_pu = 1; + dev->sys_conf.mem_force_pd = 0; +} + +/** + * @brief Force power off the RMT memory block, regardless of the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_force_power_off(rmt_dev_t *dev) +{ + dev->sys_conf.mem_force_pd = 1; + dev->sys_conf.mem_force_pu = 0; +} + +/** + * @brief Power control the RMT memory block by the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_mem_power_by_pmu(rmt_dev_t *dev) +{ + dev->sys_conf.mem_force_pd = 0; + dev->sys_conf.mem_force_pu = 0; } /** @@ -817,12 +838,9 @@ static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel return dev->chnconf0[channel].idle_out_lv_chn; } -static inline bool rmt_ll_is_mem_powered_down(rmt_dev_t *dev) +static inline bool rmt_ll_is_mem_force_powered_down(rmt_dev_t *dev) { - // the RTC domain can also power down RMT memory - // so it's probably not enough to detect whether it's powered down or not - // mem_force_pd has higher priority than mem_force_pu - return (dev->sys_conf.mem_force_pd) || !(dev->sys_conf.mem_force_pu); + return dev->sys_conf.mem_force_pd; } __attribute__((always_inline)) diff --git a/components/hal/rmt_hal.c b/components/hal/rmt_hal.c index c14c8501cc..7fac79078b 100644 --- a/components/hal/rmt_hal.c +++ b/components/hal/rmt_hal.c @@ -10,7 +10,7 @@ void rmt_hal_init(rmt_hal_context_t *hal) { hal->regs = &RMT; - rmt_ll_power_down_mem(hal->regs, false); // turn on RMTMEM power domain + rmt_ll_mem_power_by_pmu(hal->regs); rmt_ll_enable_mem_access_nonfifo(hal->regs, true); // APB access the RMTMEM in nonfifo mode rmt_ll_enable_interrupt(hal->regs, UINT32_MAX, false); // disable all interupt events rmt_ll_clear_interrupt_status(hal->regs, UINT32_MAX); // clear all pending events @@ -24,7 +24,7 @@ void rmt_hal_deinit(rmt_hal_context_t *hal) { rmt_ll_enable_interrupt(hal->regs, UINT32_MAX, false); // disable all interupt events rmt_ll_clear_interrupt_status(hal->regs, UINT32_MAX); // clear all pending events - rmt_ll_power_down_mem(hal->regs, true); // turn off RMTMEM power domain + rmt_ll_mem_force_power_off(hal->regs); // power off RMTMEM power domain forcefully rmt_ll_enable_group_clock(hal->regs, false); // disable clock source hal->regs = NULL; }