Merge branch 'feat/pcnt_support_s31' into 'master'

feat(pcnt): support pcnt on esp32s31

Closes IDF-14699

See merge request espressif/esp-idf!47767
This commit is contained in:
Chen Chen
2026-04-27 12:07:33 +08:00
19 changed files with 859 additions and 176 deletions

View File

@@ -50,15 +50,19 @@ To install a PCNT unit, there is a configuration structure that needs to be give
.. list::
- :cpp:member:`pcnt_unit_config_t::group_id` specifies which PCNT peripheral group (hardware instance) to allocate the unit from. Must be a valid group index in range ``[0, PCNT_LL_INST_NUM)``. When you have multiple independent PCNT groups on a chip (e.g., ESP32-S31), this field allows you to pin a unit to a specific group.
- :cpp:member:`pcnt_unit_config_t::clk_src` selects the clock source for the PCNT unit.
- :cpp:member:`pcnt_unit_config_t::low_limit` and :cpp:member:`pcnt_unit_config_t::high_limit` specify the range for the internal hardware counter. The counter will reset to zero automatically when it crosses either the high or low limit.
- :cpp:member:`pcnt_unit_config_t::intr_priority` sets the interrupt priority. If it is set to ``0``, the driver will allocate an interrupt with a default priority. Otherwise, the driver will use the given priority.
- :cpp:member:`pcnt_unit_config_t::flags::accum_count` sets whether to create an internal accumulator for the counter. This is helpful when you want to extend the counter's width, which by default is 16 bit at most, defined in the hardware. See also :ref:`pcnt-compensate-overflow-loss` for how to use this feature to compensate the overflow loss.
:SOC_PCNT_SUPPORT_STEP_NOTIFY: - :cpp:member:`pcnt_unit_config_t::flags::en_step_notify_up` Configure whether to enable watch step to count in the positive direction.
:SOC_PCNT_SUPPORT_STEP_NOTIFY: - :cpp:member:`pcnt_unit_config_t::flags::en_step_notify_down` Configure whether to enable watch step to count in the negative direction.
- :cpp:member:`pcnt_unit_config_t::intr_priority` sets the priority of the interrupt. If it is set to ``0``, the driver will allocate an interrupt with a default priority. Otherwise, the driver will use the given priority.
.. note::
Since all PCNT units share the same interrupt source, when installing multiple PCNT units make sure that the interrupt priority :cpp:member:`pcnt_unit_config_t::intr_priority` is the same for each unit.
All units within the **same PCNT group** share the same hardware interrupt source and the same peripheral clock. Therefore, when installing multiple PCNT units in the same group, the following constraints apply:
- Both :cpp:member:`pcnt_unit_config_t::intr_priority` and :cpp:member:`pcnt_unit_config_t::clk_src` must be the same for all units within the same group. If there is a mismatch, :cpp:func:`pcnt_new_unit` will return :c:macro:`ESP_ERR_INVALID_ARG`.
Unit allocation and initialization is done by calling a function :cpp:func:`pcnt_new_unit` with :cpp:type:`pcnt_unit_config_t` as an input parameter. The function will return a PCNT unit handle only when it runs correctly. Specifically, when there are no more free PCNT units in the pool (i.e., unit resources have been used up), then this function will return :c:macro:`ESP_ERR_NOT_FOUND` error.

View File

@@ -50,15 +50,19 @@ PCNT 单元和通道分别用 :cpp:type:`pcnt_unit_handle_t` 与 :cpp:type:`pcnt
.. list::
- :cpp:member:`pcnt_unit_config_t::group_id` 用于指定从哪个 PCNT 外设组(硬件实例)中分配该单元。必须是合法的组索引,范围为 ``[0, PCNT_LL_INST_NUM)``。当芯片拥有多个独立 PCNT 组时(例如 ESP32-S31可通过此字段将单元绑定到特定的组。
- :cpp:member:`pcnt_unit_config_t::clk_src` 用于选择 PCNT 单元的时钟源。
- :cpp:member:`pcnt_unit_config_t::low_limit`:cpp:member:`pcnt_unit_config_t::high_limit` 用于指定内部计数器的最小值和最大值。当计数器超过任一限值时,计数器将归零。
- :cpp:member:`pcnt_unit_config_t::intr_priority` 设置中断的优先级。如果设置为 ``0``,则会分配一个默认优先级的中断,否则会使用指定的优先级。
- :cpp:member:`pcnt_unit_config_t::flags::accum_count` 用于设置是否需要软件在硬件计数值溢出的时候进行累加保存,这有助于“拓宽”计数器的实际位宽。默认情况下,计数器的位宽最高只有 16 比特。请参考 :ref:`pcnt-compensate-overflow-loss` 了解如何利用此功能来补偿硬件计数器的溢出损失。
:SOC_PCNT_SUPPORT_STEP_NOTIFY: - :cpp:member:`pcnt_unit_config_t::flags::en_step_notify_up` 配置是否使能观察正方向步进。
:SOC_PCNT_SUPPORT_STEP_NOTIFY: - :cpp:member:`pcnt_unit_config_t::flags::en_step_notify_down` 配置是否使能观察负方向步进。
- :cpp:member:`pcnt_unit_config_t::intr_priority` 设置中断的优先级。如果设置为 ``0``,则会分配一个默认优先级的中断,否则会使用指定的优先级。
.. note::
由于所有 PCNT 单元共享一个中断源,安装多个 PCNT 单元时请确保每个单元的中断优先级 :cpp:member:`pcnt_unit_config_t::intr_priority` 一致。
**同一 PCNT 组** 内的所有单元共享同一硬件中断源和同一外设时钟,因此在同一组内安装多个 PCNT 单元时,需满足以下约束:
- :cpp:member:`pcnt_unit_config_t::intr_priority`:cpp:member:`pcnt_unit_config_t::clk_src` 在同组内须一致,不一致将导致 :cpp:func:`pcnt_new_unit` 返回 :c:macro:`ESP_ERR_INVALID_ARG`
调用函数 :cpp:func:`pcnt_new_unit` 并将 :cpp:type:`pcnt_unit_config_t` 作为其输入值,可对 PCNT 单元进行分配和初始化。该函数正常运行时,会返回一个 PCNT 单元句柄。没有可用的 PCNT 单元时(即 PCNT 单元全部被占用),该函数会返回错误 :c:macro:`ESP_ERR_NOT_FOUND`