Skip to content

Commit

Permalink
Merge branch 'fix/mcpwm_pm_lock_memory_leak' into 'master'
Browse files Browse the repository at this point in the history
fix(mcpwm): fix pm_lock memory issues

See merge request espressif/esp-idf!33852
  • Loading branch information
Kainarx committed Sep 27, 2024
2 parents 041a937 + e56f04f commit afffd0d
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 10 deletions.
3 changes: 3 additions & 0 deletions components/esp_driver_mcpwm/src/mcpwm_cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
#if !SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
if (cap_timer->pm_lock) {
ESP_RETURN_ON_ERROR(esp_pm_lock_delete(cap_timer->pm_lock), TAG, "delete pm_lock failed");
}
#endif
if (cap_timer->group) {
mcpwm_cap_timer_unregister_from_group(cap_timer);
}
Expand Down Expand Up @@ -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
// 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");
cap_timer->pm_lock = group->pm_lock;
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_LOGD(TAG, "periph_src_clk_hz %"PRIu32"", periph_src_clk_hz);
Expand Down
3 changes: 3 additions & 0 deletions components/esp_driver_mcpwm/src/mcpwm_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ void mcpwm_release_group_handle(mcpwm_group_t *group)
MCPWM_RCC_ATOMIC() {
mcpwm_ll_enable_bus_clock(group_id, false);
}
if (group->pm_lock) {
esp_pm_lock_delete(group->pm_lock);
}
free(group);
}
_lock_release(&s_platform.mutex);
Expand Down
4 changes: 2 additions & 2 deletions docs/en/api-reference/peripherals/mcpwm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

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:
Expand Down
9 changes: 6 additions & 3 deletions docs/en/api-reference/system/power_management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_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:

.. list::

- PCNT
- Sigma-delta
:SOC_PCNT_SUPPORTED: - The legacy PCNT driver
:SOC_SDM_SUPPORTED: - The legacy Sigma-delta driver
- The legacy timer group driver
:SOC_MCPWM_SUPPORTED: - MCPWM
:SOC_MCPWM_SUPPORTED: - The legacy MCPWM driver


.. only:: SOC_PM_SUPPORT_TOP_PD
Expand Down
4 changes: 2 additions & 2 deletions docs/zh_CN/api-reference/peripherals/mcpwm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -978,9 +978,9 @@ 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:
Expand Down
9 changes: 6 additions & 3 deletions docs/zh_CN/api-reference/system/power_management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_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::

- PCNT
- Sigma-delta
:SOC_PCNT_SUPPORTED: - 旧版 PCNT 驱动
:SOC_SDM_SUPPORTED: - 旧版 Sigma-delta 驱动
- 旧版定时器驱动 (Timer Group)
:SOC_MCPWM_SUPPORTED: - MCPWM
:SOC_MCPWM_SUPPORTED: - 旧版 MCPWM 驱动


.. only:: SOC_PM_SUPPORT_TOP_PD
Expand Down

0 comments on commit afffd0d

Please sign in to comment.