fix(mcpwm): fix pm_lock memory issues

This commit is contained in:
Chen Jichang 2024-09-26 20:06:01 +08:00
parent 1e4ebabe9b
commit e56f04fdd3
6 changed files with 22 additions and 10 deletions

View File

@ -69,9 +69,11 @@ static void mcpwm_cap_timer_unregister_from_group(mcpwm_cap_timer_t *cap_timer)
static esp_err_t mcpwm_cap_timer_destroy(mcpwm_cap_timer_t *cap_timer) static esp_err_t mcpwm_cap_timer_destroy(mcpwm_cap_timer_t *cap_timer)
{ {
#if !SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
if (cap_timer->pm_lock) { if (cap_timer->pm_lock) {
ESP_RETURN_ON_ERROR(esp_pm_lock_delete(cap_timer->pm_lock), TAG, "delete pm_lock failed"); ESP_RETURN_ON_ERROR(esp_pm_lock_delete(cap_timer->pm_lock), TAG, "delete pm_lock failed");
} }
#endif
if (cap_timer->group) { if (cap_timer->group) {
mcpwm_cap_timer_unregister_from_group(cap_timer); mcpwm_cap_timer_unregister_from_group(cap_timer);
} }
@ -101,6 +103,7 @@ esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mc
#if SOC_MCPWM_CAPTURE_CLK_FROM_GROUP #if SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
// capture timer clock source is same as the MCPWM group // capture timer clock source is same as the MCPWM group
ESP_GOTO_ON_ERROR(mcpwm_select_periph_clock(group, (soc_module_clk_t)clk_src), err, TAG, "set group clock failed"); ESP_GOTO_ON_ERROR(mcpwm_select_periph_clock(group, (soc_module_clk_t)clk_src), err, TAG, "set group clock failed");
cap_timer->pm_lock = group->pm_lock;
uint32_t periph_src_clk_hz = 0; uint32_t periph_src_clk_hz = 0;
ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), err, TAG, "get clock source freq failed"); ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), err, TAG, "get clock source freq failed");
ESP_LOGD(TAG, "periph_src_clk_hz %"PRIu32"", periph_src_clk_hz); ESP_LOGD(TAG, "periph_src_clk_hz %"PRIu32"", periph_src_clk_hz);

View File

@ -113,6 +113,9 @@ void mcpwm_release_group_handle(mcpwm_group_t *group)
MCPWM_RCC_ATOMIC() { MCPWM_RCC_ATOMIC() {
mcpwm_ll_enable_bus_clock(group_id, false); mcpwm_ll_enable_bus_clock(group_id, false);
} }
if (group->pm_lock) {
esp_pm_lock_delete(group->pm_lock);
}
free(group); free(group);
} }
_lock_release(&s_platform.mutex); _lock_release(&s_platform.mutex);

View File

@ -978,9 +978,9 @@ Power Management
When power management is enabled (i.e., :ref:`CONFIG_PM_ENABLE` is on), the system will adjust the PLL and APB frequency before going into Light-sleep, thus potentially changing the period of an MCPWM timers' counting step and leading to inaccurate time-keeping. When power management is enabled (i.e., :ref:`CONFIG_PM_ENABLE` is on), the system will adjust the PLL and APB frequency before going into Light-sleep, thus potentially changing the period of an MCPWM timers' counting step and leading to inaccurate time-keeping.
However, the driver can prevent the system from changing APB frequency by acquiring a power management lock of type :cpp:enumerator:`ESP_PM_APB_FREQ_MAX`. Whenever the driver creates an MCPWM timer instance that has selected :cpp:enumerator:`MCPWM_TIMER_CLK_SRC_PLL160M` as its clock source, the driver guarantees that the power management lock is acquired when enabling the timer by :cpp:func:`mcpwm_timer_enable`. On the contrary, the driver releases the lock when :cpp:func:`mcpwm_timer_disable` is called for that timer. However, the driver can prevent the system from going into Light-sleep by acquiring a power management lock of type :cpp:enumerator:`ESP_PM_NO_LIGHT_SLEEP`. Whenever the driver creates an MCPWM timer instance that has selected PLL as its clock source, the driver guarantees that the power management lock is acquired when enabling the timer by :cpp:func:`mcpwm_timer_enable`. On the contrary, the driver releases the lock when :cpp:func:`mcpwm_timer_disable` is called for that timer.
Likewise, whenever the driver creates an MCPWM capture timer instance that has selected :cpp:enumerator:`MCPWM_CAPTURE_CLK_SRC_APB` as its clock source, the driver guarantees that the power management lock is acquired when enabling the timer by :cpp:func:`mcpwm_capture_timer_enable`. And releases the lock in :cpp:func:`mcpwm_capture_timer_disable`. Likewise, whenever the driver creates an MCPWM capture timer instance, the driver guarantees that the power management lock is acquired when enabling the timer by :cpp:func:`mcpwm_capture_timer_enable`. And releases the lock in :cpp:func:`mcpwm_capture_timer_disable`.
.. _mcpwm-iram-safe: .. _mcpwm-iram-safe:

View File

@ -118,15 +118,18 @@ The following drivers hold the ``ESP_PM_APB_FREQ_MAX`` lock while the driver is
:SOC_TWAI_SUPPORTED: - **TWAI**: between calls to :cpp:func:`twai_driver_install` and :cpp:func:`twai_driver_uninstall` (only when the clock source is set to :cpp:enumerator:`TWAI_CLK_SRC_APB`). :SOC_TWAI_SUPPORTED: - **TWAI**: between calls to :cpp:func:`twai_driver_install` and :cpp:func:`twai_driver_uninstall` (only when the clock source is set to :cpp:enumerator:`TWAI_CLK_SRC_APB`).
:SOC_BT_SUPPORTED and esp32: - **Bluetooth**: between calls to :cpp:func:`esp_bt_controller_enable` and :cpp:func:`esp_bt_controller_disable`. If Bluetooth Modem-sleep is enabled, the ``ESP_PM_APB_FREQ_MAX`` lock will be released for the periods of time when radio is disabled. However the ``ESP_PM_NO_LIGHT_SLEEP`` lock will still be held, unless :ref:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` option is set to "External 32kHz crystal". :SOC_BT_SUPPORTED and esp32: - **Bluetooth**: between calls to :cpp:func:`esp_bt_controller_enable` and :cpp:func:`esp_bt_controller_disable`. If Bluetooth Modem-sleep is enabled, the ``ESP_PM_APB_FREQ_MAX`` lock will be released for the periods of time when radio is disabled. However the ``ESP_PM_NO_LIGHT_SLEEP`` lock will still be held, unless :ref:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` option is set to "External 32kHz crystal".
:SOC_BT_SUPPORTED and not esp32: - **Bluetooth**: between calls to :cpp:func:`esp_bt_controller_enable` and :cpp:func:`esp_bt_controller_disable`. If Bluetooth Modem-sleep is enabled, the ``ESP_PM_APB_FREQ_MAX`` lock will be released for the periods of time when radio is disabled. However the ``ESP_PM_NO_LIGHT_SLEEP`` lock will still be held. :SOC_BT_SUPPORTED and not esp32: - **Bluetooth**: between calls to :cpp:func:`esp_bt_controller_enable` and :cpp:func:`esp_bt_controller_disable`. If Bluetooth Modem-sleep is enabled, the ``ESP_PM_APB_FREQ_MAX`` lock will be released for the periods of time when radio is disabled. However the ``ESP_PM_NO_LIGHT_SLEEP`` lock will still be held.
:SOC_PCNT_SUPPORTED: - **PCNT**: between calls to :cpp:func:`pcnt_unit_enable` and :cpp:func:`pcnt_unit_disable`.
:SOC_SDM_SUPPORTED: - **Sigma-delta**: between calls to :cpp:func:`sdm_channel_enable` and :cpp:func:`sdm_channel_disable`.
:SOC_MCPWM_SUPPORTED: - **MCPWM**: between calls to :cpp:func:`mcpwm_timer_enable` and :cpp:func:`mcpwm_timer_disable`, as well as :cpp:func:`mcpwm_capture_timer_enable` and :cpp:func:`mcpwm_capture_timer_disable`.
The following peripheral drivers are not aware of DFS yet. Applications need to acquire/release locks themselves, when necessary: The following peripheral drivers are not aware of DFS yet. Applications need to acquire/release locks themselves, when necessary:
.. list:: .. list::
- PCNT :SOC_PCNT_SUPPORTED: - The legacy PCNT driver
- Sigma-delta :SOC_SDM_SUPPORTED: - The legacy Sigma-delta driver
- The legacy timer group driver - The legacy timer group driver
:SOC_MCPWM_SUPPORTED: - MCPWM :SOC_MCPWM_SUPPORTED: - The legacy MCPWM driver
.. only:: SOC_PM_SUPPORT_TOP_PD .. only:: SOC_PM_SUPPORT_TOP_PD

View File

@ -978,9 +978,9 @@ MCPWM 捕获通道支持在信号上检测到有效边沿时发送通知。须
启用电源管理(即开启 :ref:`CONFIG_PM_ENABLE`)时,系统会在进入 Light-sleep 前调整 PLL 和 APB 频率。该操作有可能会改变 MCPWM 定时器的计数步长,导致计时偏差。 启用电源管理(即开启 :ref:`CONFIG_PM_ENABLE`)时,系统会在进入 Light-sleep 前调整 PLL 和 APB 频率。该操作有可能会改变 MCPWM 定时器的计数步长,导致计时偏差。
不过,驱动程序可以获取 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 类型的电源管理锁,防止系统改变 APB 频率。每当驱动创建以 :cpp:enumerator:`MCPWM_TIMER_CLK_SRC_PLL160M` 作为时钟源的 MCPWM 定时器实例时,都会在通过 :cpp:func:`mcpwm_timer_enable` 启用定时器时获取电源管理锁。反之,调用 :cpp:func:`mcpwm_timer_disable` 时,驱动程序释放锁。 不过,驱动程序可以获取 :cpp:enumerator:`ESP_PM_NO_LIGHT_SLEEP` 类型的电源管理锁,防止系统进入 Light-sleep。每当驱动创建以 PLL 作为时钟源的 MCPWM 定时器实例时,都会在通过 :cpp:func:`mcpwm_timer_enable` 启用定时器时获取电源管理锁。反之,调用 :cpp:func:`mcpwm_timer_disable` 时,驱动程序释放锁。
同理,每当驱动创建一个以 :cpp:enumerator:`MCPWM_CAPTURE_CLK_SRC_APB` 作为时钟源的 MCPWM 捕获定时器实例时,都会在通过 :cpp:func:`mcpwm_capture_timer_enable` 启用定时器时获取电源管理锁,并在调用 :cpp:func:`mcpwm_capture_timer_disable` 时释放锁。 同理,每当驱动创建 MCPWM 捕获定时器实例时,都会在通过 :cpp:func:`mcpwm_capture_timer_enable` 启用定时器时获取电源管理锁,并在调用 :cpp:func:`mcpwm_capture_timer_disable` 时释放锁。
.. _mcpwm-iram-safe: .. _mcpwm-iram-safe:

View File

@ -118,15 +118,18 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
:SOC_TWAI_SUPPORTED: - **TWAI**:从调用 :cpp:func:`twai_driver_install` 至 :cpp:func:`twai_driver_uninstall` 期间 (只有在 TWAI 时钟源选择为 :cpp:enumerator:`TWAI_CLK_SRC_APB` 的时候生效)。 :SOC_TWAI_SUPPORTED: - **TWAI**:从调用 :cpp:func:`twai_driver_install` 至 :cpp:func:`twai_driver_uninstall` 期间 (只有在 TWAI 时钟源选择为 :cpp:enumerator:`TWAI_CLK_SRC_APB` 的时候生效)。
:SOC_BT_SUPPORTED and esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁,除非将 :ref:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` 选项设置为 “外部 32 kHz 晶振”。 :SOC_BT_SUPPORTED and esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁,除非将 :ref:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` 选项设置为 “外部 32 kHz 晶振”。
:SOC_BT_SUPPORTED and not esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁。 :SOC_BT_SUPPORTED and not esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁。
:SOC_PCNT_SUPPORTED: - **PCNT**:从调用 :cpp:func:`pcnt_unit_enable` 至 :cpp:func:`pcnt_unit_disable` 期间。
:SOC_SDM_SUPPORTED: - **Sigma-delta**:从调用 :cpp:func:`sdm_channel_enable` 至 :cpp:func:`sdm_channel_disable` 期间。
:SOC_MCPWM_SUPPORTED: - **MCPWM**: 从调用 :cpp:func:`mcpwm_timer_enable` 至 :cpp:func:`mcpwm_timer_disable` 期间,以及调用 :cpp:func:`mcpwm_capture_timer_enable` 至 :cpp:func:`mcpwm_capture_timer_disable` 期间。
以下外设驱动程序无法感知动态调频,应用程序需自己获取/释放管理锁: 以下外设驱动程序无法感知动态调频,应用程序需自己获取/释放管理锁:
.. list:: .. list::
- PCNT :SOC_PCNT_SUPPORTED: - 旧版 PCNT 驱动
- Sigma-delta :SOC_SDM_SUPPORTED: - 旧版 Sigma-delta 驱动
- 旧版定时器驱动 (Timer Group) - 旧版定时器驱动 (Timer Group)
:SOC_MCPWM_SUPPORTED: - MCPWM :SOC_MCPWM_SUPPORTED: - 旧版 MCPWM 驱动
.. only:: SOC_PM_SUPPORT_TOP_PD .. only:: SOC_PM_SUPPORT_TOP_PD