pcnt: add const qualifier to event data

This commit is contained in:
morris 2022-06-22 18:08:25 +08:00
parent ee771c1d08
commit 9e532696f4
9 changed files with 65 additions and 65 deletions

View File

@ -44,7 +44,7 @@ typedef struct {
* @param[in] user_ctx User data, passed from `pcnt_unit_register_event_callbacks()` * @param[in] user_ctx User data, passed from `pcnt_unit_register_event_callbacks()`
* @return Whether a high priority task has been woken up by this function * @return Whether a high priority task has been woken up by this function
*/ */
typedef bool (*pcnt_watch_cb_t)(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *edata, void *user_ctx); typedef bool (*pcnt_watch_cb_t)(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx);
/** /**
* @brief Group of supported PCNT callbacks * @brief Group of supported PCNT callbacks

View File

@ -49,7 +49,7 @@ rmt_group_t *rmt_acquire_group_handle(int group_id)
// initial occupy_mask: 1111...100...0 // initial occupy_mask: 1111...100...0
group->occupy_mask = UINT32_MAX & ~((1 << SOC_RMT_CHANNELS_PER_GROUP) - 1); group->occupy_mask = UINT32_MAX & ~((1 << SOC_RMT_CHANNELS_PER_GROUP) - 1);
// group clock won't be configured at this stage, it will be set when allocate the first channel // group clock won't be configured at this stage, it will be set when allocate the first channel
group->clk_src = RMT_CLK_SRC_NONE; group->clk_src = 0;
// enable APB access RMT registers // enable APB access RMT registers
periph_module_enable(rmt_periph_signals.groups[group_id].module); periph_module_enable(rmt_periph_signals.groups[group_id].module);
periph_module_reset(rmt_periph_signals.groups[group_id].module); periph_module_reset(rmt_periph_signals.groups[group_id].module);
@ -102,7 +102,7 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t
bool clock_selection_conflict = false; bool clock_selection_conflict = false;
// check if we need to update the group clock source, group clock source is shared by all channels // check if we need to update the group clock source, group clock source is shared by all channels
portENTER_CRITICAL(&group->spinlock); portENTER_CRITICAL(&group->spinlock);
if (group->clk_src == RMT_CLK_SRC_NONE) { if (group->clk_src == 0) {
group->clk_src = clk_src; group->clk_src = clk_src;
} else { } else {
clock_selection_conflict = (group->clk_src != clk_src); clock_selection_conflict = (group->clk_src != clk_src);

View File

@ -218,7 +218,7 @@ typedef struct {
} test_pcnt_quadrature_context_t; } test_pcnt_quadrature_context_t;
TEST_PCNT_CALLBACK_ATTR TEST_PCNT_CALLBACK_ATTR
static bool test_pcnt_quadrature_reach_watch_point(pcnt_unit_handle_t handle, pcnt_watch_event_data_t *event_data, void *user_data) static bool test_pcnt_quadrature_reach_watch_point(pcnt_unit_handle_t handle, const pcnt_watch_event_data_t *event_data, void *user_data)
{ {
test_pcnt_quadrature_context_t *user_ctx = (test_pcnt_quadrature_context_t *)user_data; test_pcnt_quadrature_context_t *user_ctx = (test_pcnt_quadrature_context_t *)user_data;
user_ctx->triggered_watch_values[user_ctx->index++] = event_data->watch_point_value; user_ctx->triggered_watch_values[user_ctx->index++] = event_data->watch_point_value;
@ -338,7 +338,7 @@ typedef struct {
} test_pcnt_zero_cross_context_t; } test_pcnt_zero_cross_context_t;
TEST_PCNT_CALLBACK_ATTR TEST_PCNT_CALLBACK_ATTR
static bool test_pcnt_on_zero_cross(pcnt_unit_handle_t handle, pcnt_watch_event_data_t *event_data, void *user_data) static bool test_pcnt_on_zero_cross(pcnt_unit_handle_t handle, const pcnt_watch_event_data_t *event_data, void *user_data)
{ {
test_pcnt_zero_cross_context_t *user_ctx = (test_pcnt_zero_cross_context_t *)user_data; test_pcnt_zero_cross_context_t *user_ctx = (test_pcnt_zero_cross_context_t *)user_data;
user_ctx->mode = event_data->zero_cross_mode; user_ctx->mode = event_data->zero_cross_mode;

View File

@ -20,7 +20,7 @@
#if CONFIG_PCNT_ISR_IRAM_SAFE #if CONFIG_PCNT_ISR_IRAM_SAFE
static bool IRAM_ATTR test_pcnt_iram_safe_callback(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *event_data, void *user_data) static bool IRAM_ATTR test_pcnt_iram_safe_callback(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *event_data, void *user_data)
{ {
uint32_t *data = (uint32_t *)user_data; uint32_t *data = (uint32_t *)user_data;
(*data)++; (*data)++;

View File

@ -20,19 +20,19 @@ Functional Overview
Description of the PCNT functionality is divided into the following sections: Description of the PCNT functionality is divided into the following sections:
- :ref:`allocating-resource` - covers how to allocate PCNT units and channels with properly set of configurations. It also covers how to recycle the resources when they finished working. - :ref:`pcnt-resource-allocation` - covers how to allocate PCNT units and channels with properly set of configurations. It also covers how to recycle the resources when they finished working.
- :ref:`set-up-channel-actions` - covers how to configure the PCNT channel to behave on different signal edges and levels. - :ref:`pcnt-setup-channel-actions` - covers how to configure the PCNT channel to behave on different signal edges and levels.
- :ref:`watch-points` - describes how to configure PCNT watch points (i.e., tell PCNT unit to trigger an event when the count reaches a certain value). - :ref:`pcnt-watch-points` - describes how to configure PCNT watch points (i.e., tell PCNT unit to trigger an event when the count reaches a certain value).
- :ref:`callbacks-register-event` - describes how to hook your specific code to the watch point event callback function. - :ref:`pcnt-register-event-callbacks` - describes how to hook your specific code to the watch point event callback function.
- :ref:`set-glitch-filter` - describes how to enable and set the timing parameters for the internal glitch filter. - :ref:`pcnt-set-glitch-filter` - describes how to enable and set the timing parameters for the internal glitch filter.
- :ref:`enable-and-disable-unit` - describes how to enable and disable the PCNT unit. - :ref:`pcnt-enable-disable-unit` - describes how to enable and disable the PCNT unit.
- :ref:`unit-io-control` - describes IO control functions of PCNT unit, like enable glitch filter, start and stop unit, get and clear count value. - :ref:`pcnt-unit-io-control` - describes IO control functions of PCNT unit, like enable glitch filter, start and stop unit, get and clear count value.
- :ref:`managing-power` - describes what functionality will prevent the chip from going into low power mode. - :ref:`pcnt-power-management` - describes what functionality will prevent the chip from going into low power mode.
- :ref:`iram-safety` - describes tips on how to make the PCNT interrupt and IO control functions work better along with a disabled cache. - :ref:`pcnt-iram-safe` - describes tips on how to make the PCNT interrupt and IO control functions work better along with a disabled cache.
- :ref:`thread-safe` - lists which APIs are guaranteed to be thread safe by the driver. - :ref:`pcnt-thread-safe` - lists which APIs are guaranteed to be thread safe by the driver.
- :ref:`kconfig-option` - lists the supported Kconfig options that can be used to make a different effect on driver behavior. - :ref:`pcnt-kconfig-options` - lists the supported Kconfig options that can be used to make a different effect on driver behavior.
.. _allocating-resource: .. _pcnt-resource-allocation:
Resource Allocation Resource Allocation
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
@ -91,7 +91,7 @@ If a previously created PCNT channel is no longer needed, it's recommended to re
pcnt_channel_handle_t pcnt_chan = NULL; pcnt_channel_handle_t pcnt_chan = NULL;
ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan)); ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
.. _set-up-channel-actions: .. _pcnt-setup-channel-actions:
Set Up Channel Actions Set Up Channel Actions
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
@ -108,12 +108,12 @@ The PCNT will increase/decrease/hold its internal count value when the input pul
// keep the counting mode when the control signal is high level, and reverse the counting mode when the control signal is low level // keep the counting mode when the control signal is high level, and reverse the counting mode when the control signal is low level
ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE)); ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
.. _watch-points: .. _pcnt-watch-points:
Watch Points Watch Points
^^^^^^^^^^^^ ^^^^^^^^^^^^
Each PCNT unit can be configured to watch several different values that you're interested in. The value to be watched is also called **Watch Point**. The watch point itself can't exceed the range set in :cpp:type:`pcnt_unit_config_t` by :cpp:member:`pcnt_unit_config_t::low_limit` and :cpp:member:`pcnt_unit_config_t::high_limit`. When the counter reaches either watch point, a watch event will be triggered and notify you by interrupt if any watch event callback has ever registered in :cpp:func:`pcnt_unit_register_event_callbacks`. See :ref:`callbacks-register-event` for how to register event callbacks. Each PCNT unit can be configured to watch several different values that you're interested in. The value to be watched is also called **Watch Point**. The watch point itself can't exceed the range set in :cpp:type:`pcnt_unit_config_t` by :cpp:member:`pcnt_unit_config_t::low_limit` and :cpp:member:`pcnt_unit_config_t::high_limit`. When the counter reaches either watch point, a watch event will be triggered and notify you by interrupt if any watch event callback has ever registered in :cpp:func:`pcnt_unit_register_event_callbacks`. See :ref:`pcnt-register-event-callbacks` for how to register event callbacks.
The watch point can be added and removed by :cpp:func:`pcnt_unit_add_watch_point` and :cpp:func:`pcnt_unit_remove_watch_point`. The commonly used watch points are: **zero cross**, **maximum / minimum count** and other threshold values. The number of available watch point is limited, :cpp:func:`pcnt_unit_add_watch_point` will return error :c:macro:`ESP_ERR_NOT_FOUND` if it can't find any free hardware resource to save the watch point. You can't add the same watch point for multiple times, otherwise it will return error :c:macro:`ESP_ERR_INVALID_STATE`. The watch point can be added and removed by :cpp:func:`pcnt_unit_add_watch_point` and :cpp:func:`pcnt_unit_remove_watch_point`. The commonly used watch points are: **zero cross**, **maximum / minimum count** and other threshold values. The number of available watch point is limited, :cpp:func:`pcnt_unit_add_watch_point` will return error :c:macro:`ESP_ERR_NOT_FOUND` if it can't find any free hardware resource to save the watch point. You can't add the same watch point for multiple times, otherwise it will return error :c:macro:`ESP_ERR_INVALID_STATE`.
@ -126,7 +126,7 @@ It is recommended to remove the unused watch point by :cpp:func:`pcnt_unit_remov
// add high limit watch point // add high limit watch point
ESP_ERROR_CHECK(pcnt_unit_add_watch_point(pcnt_unit, EXAMPLE_PCNT_HIGH_LIMIT)); ESP_ERROR_CHECK(pcnt_unit_add_watch_point(pcnt_unit, EXAMPLE_PCNT_HIGH_LIMIT));
.. _callbacks-register-event: .. _pcnt-register-event-callbacks:
Register Event Callbacks Register Event Callbacks
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
@ -146,7 +146,7 @@ Registering callback function will result in lazy installation of interrupt serv
.. code:: c .. code:: c
static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *edata, void *user_ctx) static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx)
{ {
BaseType_t high_task_wakeup; BaseType_t high_task_wakeup;
QueueHandle_t queue = (QueueHandle_t)user_ctx; QueueHandle_t queue = (QueueHandle_t)user_ctx;
@ -162,7 +162,7 @@ Registering callback function will result in lazy installation of interrupt serv
QueueHandle_t queue = xQueueCreate(10, sizeof(int)); QueueHandle_t queue = xQueueCreate(10, sizeof(int));
ESP_ERROR_CHECK(pcnt_unit_register_event_callbacks(pcnt_unit, &cbs, queue)); ESP_ERROR_CHECK(pcnt_unit_register_event_callbacks(pcnt_unit, &cbs, queue));
.. _set-glitch-filter: .. _pcnt-set-glitch-filter:
Set Glitch Filter Set Glitch Filter
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
@ -177,7 +177,7 @@ This function should be called when the the unit is in the init state. Otherwise
.. note:: .. note::
The glitch filter is clocked from APB. For the counter not to miss any pulses, the maximum glitch width should be longer than one APB_CLK cycle (usually 12.5 ns if APB equals 80MHz). As the APB frequency would be changed after DFS (Dynamic Frequency Scaling) enabled, which means the filter won't work as expect in that case. So the driver will install a PM lock for PCNT unit during the first time you enable the glitch filter. For more information related to power management strategy used in PCNT driver, please see :ref:`managing-power`. The glitch filter is clocked from APB. For the counter not to miss any pulses, the maximum glitch width should be longer than one APB_CLK cycle (usually 12.5 ns if APB equals 80MHz). As the APB frequency would be changed after DFS (Dynamic Frequency Scaling) enabled, which means the filter won't work as expect in that case. So the driver will install a PM lock for PCNT unit during the first time you enable the glitch filter. For more information related to power management strategy used in PCNT driver, please see :ref:`pcnt-power-management`.
.. code:: c .. code:: c
@ -186,7 +186,7 @@ This function should be called when the the unit is in the init state. Otherwise
}; };
ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit, &filter_config)); ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit, &filter_config));
.. _enable-and-disable-unit: .. _pcnt-enable-disable-unit:
Enable and Disable Unit Enable and Disable Unit
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
@ -195,7 +195,7 @@ Before doing IO control to the PCNT unit, you need to enable it first, by callin
* switch the PCNT driver state from **init** to **enable**. * switch the PCNT driver state from **init** to **enable**.
* enable the interrupt service if it has been lazy installed in :cpp:func:`pcnt_unit_register_event_callbacks`. * enable the interrupt service if it has been lazy installed in :cpp:func:`pcnt_unit_register_event_callbacks`.
* acquire a proper power management lock if it has been lazy installed in :cpp:func:`pcnt_unit_set_glitch_filter`. See also :ref:`managing-power` for more information. * acquire a proper power management lock if it has been lazy installed in :cpp:func:`pcnt_unit_set_glitch_filter`. See also :ref:`pcnt-power-management` for more information.
On the contrary, calling :cpp:func:`pcnt_unit_disable` will do the opposite, that is, put the PCNT driver back to the **init** state, disable the interrupts service and release the power management lock. On the contrary, calling :cpp:func:`pcnt_unit_disable` will do the opposite, that is, put the PCNT driver back to the **init** state, disable the interrupts service and release the power management lock.
@ -203,7 +203,7 @@ On the contrary, calling :cpp:func:`pcnt_unit_disable` will do the opposite, tha
ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit)); ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit));
.. _unit-io-control: .. _pcnt-unit-io-control:
Unit IO Control Unit IO Control
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
@ -234,7 +234,7 @@ You can check current count value at any time by calling :cpp:func:`pcnt_unit_ge
int pulse_count = 0; int pulse_count = 0;
ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit, &pulse_count)); ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit, &pulse_count));
.. _managing-power: .. _pcnt-power-management:
Power Management Power Management
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
@ -243,7 +243,7 @@ When power management is enabled (i.e. :ref:`CONFIG_PM_ENABLE` is on), the syste
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 you enable the glitch filter by :cpp:func:`pcnt_unit_set_glitch_filter`, the driver will guarantee that the power management lock is acquired after the PCNT unit is enabled by :cpp:func:`pcnt_unit_enable`. Likewise, the driver releases the lock after :cpp:func:`pcnt_unit_disable` is called. 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 you enable the glitch filter by :cpp:func:`pcnt_unit_set_glitch_filter`, the driver will guarantee that the power management lock is acquired after the PCNT unit is enabled by :cpp:func:`pcnt_unit_enable`. Likewise, the driver releases the lock after :cpp:func:`pcnt_unit_disable` is called.
.. _iram-safety: .. _pcnt-iram-safe:
IRAM Safe IRAM Safe
^^^^^^^^^ ^^^^^^^^^
@ -265,7 +265,7 @@ There's another Kconfig option :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` that can put
- :cpp:func:`pcnt_unit_clear_count` - :cpp:func:`pcnt_unit_clear_count`
- :cpp:func:`pcnt_unit_get_count` - :cpp:func:`pcnt_unit_get_count`
.. _thread-safe: .. _pcnt-thread-safe:
Thread Safety Thread Safety
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@ -280,13 +280,13 @@ The following functions are allowed to run under ISR context, the driver uses a
Other functions that take the :cpp:type:`pcnt_unit_handle_t` and :cpp:type:`pcnt_channel_handle_t` as the first positional parameter, are not treated as thread safe. This means you should avoid calling them from multiple tasks. Other functions that take the :cpp:type:`pcnt_unit_handle_t` and :cpp:type:`pcnt_channel_handle_t` as the first positional parameter, are not treated as thread safe. This means you should avoid calling them from multiple tasks.
.. _kconfig-option: .. _pcnt-kconfig-options:
Kconfig Options Kconfig Options
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
- :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` controls where to place the PCNT control functions (IRAM or Flash), see :ref:`iram-safety` for more information. - :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` controls where to place the PCNT control functions (IRAM or Flash), see :ref:`pcnt-iram-safe` for more information.
- :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` controls whether the default ISR handler can work when cache is disabled, see :ref:`iram-safety` for more information. - :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` controls whether the default ISR handler can work when cache is disabled, see :ref:`pcnt-iram-safe` for more information.
- :ref:`CONFIG_PCNT_ENABLE_DEBUG_LOG` is used to enabled the debug log output. Enable this option will increase the firmware binary size. - :ref:`CONFIG_PCNT_ENABLE_DEBUG_LOG` is used to enabled the debug log output. Enable this option will increase the firmware binary size.
Application Examples Application Examples

View File

@ -20,19 +20,19 @@ PCNT 模块通常用于:
PCNT 的功能从以下几个方面进行说明: PCNT 的功能从以下几个方面进行说明:
- :ref:`allocating-resource` - 说明如何通过配置分配 PCNT 单元和通道,以及在相应操作完成之后,如何回收单元和通道。 - :ref:`pcnt-resource-allocation` - 说明如何通过配置分配 PCNT 单元和通道,以及在相应操作完成之后,如何回收单元和通道。
- :ref:`set-up-channel-actions` - 说明如何设置通道针对不同信号沿和电平进行操作。 - :ref:`pcnt-setup-channel-actions` - 说明如何设置通道针对不同信号沿和电平进行操作。
- :ref:`watch-points` - 说明如何配置观察点,即当计数达到某个数值时,命令 PCNT 单元触发某个事件。 - :ref:`pcnt-watch-points` - 说明如何配置观察点,即当计数达到某个数值时,命令 PCNT 单元触发某个事件。
- :ref:`callbacks-register-event` - 说明如何将您的代码挂载到观察点事件的回调函数上。 - :ref:`pcnt-register-event-callbacks` - 说明如何将您的代码挂载到观察点事件的回调函数上。
- :ref:`set-glitch-filter` - 说明如何使能毛刺滤波器并设置其时序参数。 - :ref:`pcnt-set-glitch-filter` - 说明如何使能毛刺滤波器并设置其时序参数。
- :ref:`enable-and-disable-unit` - 说明如何使能和关闭 PCNT 单元。 - :ref:`pcnt-enable-disable-unit` - 说明如何使能和关闭 PCNT 单元。
- :ref:`unit-io-control` - 说明 PCNT 单元的 IO 控制功能,例如使能毛刺滤波器,开启和停用 PCNT 单元,获取和清除计数。 - :ref:`pcnt-unit-io-control` - 说明 PCNT 单元的 IO 控制功能,例如使能毛刺滤波器,开启和停用 PCNT 单元,获取和清除计数。
- :ref:`managing-power` - 说明哪些功能会阻止芯片进入低功耗模式。 - :ref:`pcnt-power-management` - 说明哪些功能会阻止芯片进入低功耗模式。
- :ref:`iram-safety` - 说明在缓存禁用的情况下,如何执行 PCNT 中断和 IO 控制功能。 - :ref:`pcnt-iram-safe` - 说明在缓存禁用的情况下,如何执行 PCNT 中断和 IO 控制功能。
- :ref:`thread-safe` - 列出线程安全的 API。 - :ref:`pcnt-thread-safe` - 列出线程安全的 API。
- :ref:`kconfig-option` - 列出了支持的 Kconfig 选项,这些选项可实现不同的驱动效果。 - :ref:`pcnt-kconfig-options` - 列出了支持的 Kconfig 选项,这些选项可实现不同的驱动效果。
.. _allocating-resource: .. _pcnt-resource-allocation:
分配资源 分配资源
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@ -91,7 +91,7 @@ PCNT 单元和通道分别用 :cpp:type:`pcnt_unit_handle_t` 与 :cpp:type:`pcnt
pcnt_channel_handle_t pcnt_chan = NULL; pcnt_channel_handle_t pcnt_chan = NULL;
ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan)); ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
.. _set-up-channel-actions: .. _pcnt-setup-channel-actions:
设置通道操作 设置通道操作
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
@ -108,12 +108,12 @@ PCNT 单元和通道分别用 :cpp:type:`pcnt_unit_handle_t` 与 :cpp:type:`pcnt
// keep the counting mode when the control signal is high level, and reverse the counting mode when the control signal is low level // keep the counting mode when the control signal is high level, and reverse the counting mode when the control signal is low level
ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE)); ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
.. _watch-points: .. _pcnt-watch-points:
配置观察点 配置观察点
^^^^^^^^^^ ^^^^^^^^^^
PCNT 单元可被设置为观察几个特定的数值,这些被观察的数值被称为 **观察点**。观察点不能超过 :cpp:type:`pcnt_unit_config_t` 设置的范围,最小值和最大值分别为 :cpp:member:`pcnt_unit_config_t::low_limit`:cpp:member:`pcnt_unit_config_t::high_limit`。当计数器到达任一观察点时,会触发一个观察事件,如果在 :cpp:func:`pcnt_unit_register_event_callbacks` 注册过事件回调函数,该事件就会通过中断通知您。关于如何注册事件回调函数,请参考 :ref:`callbacks-register-event`。 PCNT 单元可被设置为观察几个特定的数值,这些被观察的数值被称为 **观察点**。观察点不能超过 :cpp:type:`pcnt_unit_config_t` 设置的范围,最小值和最大值分别为 :cpp:member:`pcnt_unit_config_t::low_limit`:cpp:member:`pcnt_unit_config_t::high_limit`。当计数器到达任一观察点时,会触发一个观察事件,如果在 :cpp:func:`pcnt_unit_register_event_callbacks` 注册过事件回调函数,该事件就会通过中断通知您。关于如何注册事件回调函数,请参考 :ref:`pcnt-register-event-callbacks`。
观察点分别可以通过 :cpp:func:`pcnt_unit_add_watch_point`:cpp:func:`pcnt_unit_remove_watch_point` 进行添加和删除。常用的观察点包括 **过零**, **最大/最小计数** 以及其他的阈值。可用的观察点是有限的,如果 :cpp:func:`pcnt_unit_add_watch_point` 无法获得空闲硬件资源来存储观察点,会返回错误 :c:macro:`ESP_ERR_NOT_FOUND`。不能多次添加同一个观察点,否则将返回错误 :c:macro:`ESP_ERR_INVALID_STATE` 观察点分别可以通过 :cpp:func:`pcnt_unit_add_watch_point`:cpp:func:`pcnt_unit_remove_watch_point` 进行添加和删除。常用的观察点包括 **过零**, **最大/最小计数** 以及其他的阈值。可用的观察点是有限的,如果 :cpp:func:`pcnt_unit_add_watch_point` 无法获得空闲硬件资源来存储观察点,会返回错误 :c:macro:`ESP_ERR_NOT_FOUND`。不能多次添加同一个观察点,否则将返回错误 :c:macro:`ESP_ERR_INVALID_STATE`
@ -126,7 +126,7 @@ PCNT 单元可被设置为观察几个特定的数值,这些被观察的数值
// add high limit watch point // add high limit watch point
ESP_ERROR_CHECK(pcnt_unit_add_watch_point(pcnt_unit, EXAMPLE_PCNT_HIGH_LIMIT)); ESP_ERROR_CHECK(pcnt_unit_add_watch_point(pcnt_unit, EXAMPLE_PCNT_HIGH_LIMIT));
.. _callbacks-register-event: .. _pcnt-register-event-callbacks:
注册事件回调函数 注册事件回调函数
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
@ -146,7 +146,7 @@ PCNT 单元可被设置为观察几个特定的数值,这些被观察的数值
.. code:: c .. code:: c
static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *edata, void *user_ctx) static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx)
{ {
BaseType_t high_task_wakeup; BaseType_t high_task_wakeup;
QueueHandle_t queue = (QueueHandle_t)user_ctx; QueueHandle_t queue = (QueueHandle_t)user_ctx;
@ -162,7 +162,7 @@ PCNT 单元可被设置为观察几个特定的数值,这些被观察的数值
QueueHandle_t queue = xQueueCreate(10, sizeof(int)); QueueHandle_t queue = xQueueCreate(10, sizeof(int));
ESP_ERROR_CHECK(pcnt_unit_register_event_callbacks(pcnt_unit, &cbs, queue)); ESP_ERROR_CHECK(pcnt_unit_register_event_callbacks(pcnt_unit, &cbs, queue));
.. _set-glitch-filter: .. _pcnt-set-glitch-filter:
设置毛刺滤波器 设置毛刺滤波器
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
@ -177,7 +177,7 @@ PCNT 单元的滤波器可滤除信号中的短时毛刺,:cpp:type:`pcnt_glitc
.. note:: .. note::
毛刺滤波器的时钟信息来自 APB。为确保 PCNT 单元不会滤除脉冲信号,最大毛刺宽度应大于一个 APB_CLK 周期(如果 APB 的频率为 80 MHz则最大毛刺宽度为 12.5 ns。使能动态频率缩放 (DFS) 后APB 的频率会发生变化,从而最大毛刺宽度也会发生变化,这会导致计数器无法正常工作。因此,第一次使能毛刺滤波器时,驱动会为 PCNT 单元安装 PM 锁。关于 PCNT 驱动的电源管理的更多信息,请参考 :ref:`managing-power`。 毛刺滤波器的时钟信息来自 APB。为确保 PCNT 单元不会滤除脉冲信号,最大毛刺宽度应大于一个 APB_CLK 周期(如果 APB 的频率为 80 MHz则最大毛刺宽度为 12.5 ns。使能动态频率缩放 (DFS) 后APB 的频率会发生变化,从而最大毛刺宽度也会发生变化,这会导致计数器无法正常工作。因此,第一次使能毛刺滤波器时,驱动会为 PCNT 单元安装 PM 锁。关于 PCNT 驱动的电源管理的更多信息,请参考 :ref:`pcnt-power-management`。
.. code:: c .. code:: c
@ -186,7 +186,7 @@ PCNT 单元的滤波器可滤除信号中的短时毛刺,:cpp:type:`pcnt_glitc
}; };
ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit, &filter_config)); ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit, &filter_config));
.. _enable-and-disable-unit: .. _pcnt-enable-disable-unit:
使能和禁用单元 使能和禁用单元
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
@ -195,7 +195,7 @@ PCNT 单元的滤波器可滤除信号中的短时毛刺,:cpp:type:`pcnt_glitc
* 将 PCNT 单元的驱动状态从 **初始** 切换到 **使能** 。 * 将 PCNT 单元的驱动状态从 **初始** 切换到 **使能** 。
* 如果中断服务已经在 :cpp:func:`pcnt_unit_register_event_callbacks` 延迟安装,使能中断服务。 * 如果中断服务已经在 :cpp:func:`pcnt_unit_register_event_callbacks` 延迟安装,使能中断服务。
* 如果电源管理锁已经在 :cpp:func:`pcnt_unit_set_glitch_filter` 延迟安装,获取该电源管理锁。请参考 :ref:`managing-power` 获取更多信息。 * 如果电源管理锁已经在 :cpp:func:`pcnt_unit_set_glitch_filter` 延迟安装,获取该电源管理锁。请参考 :ref:`pcnt-power-management` 获取更多信息。
调用函数 :cpp:func:`pcnt_unit_disable` 会进行相反的操作,即将 PCNT 单元的驱动状态切换回 **初始** 状态,禁用中断服务并释放电源管理锁。 调用函数 :cpp:func:`pcnt_unit_disable` 会进行相反的操作,即将 PCNT 单元的驱动状态切换回 **初始** 状态,禁用中断服务并释放电源管理锁。
@ -203,7 +203,7 @@ PCNT 单元的滤波器可滤除信号中的短时毛刺,:cpp:type:`pcnt_glitc
ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit)); ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit));
.. _unit-io-control: .. _pcnt-unit-io-control:
控制单元 IO 控制单元 IO
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
@ -234,7 +234,7 @@ PCNT 单元的滤波器可滤除信号中的短时毛刺,:cpp:type:`pcnt_glitc
int pulse_count = 0; int pulse_count = 0;
ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit, &pulse_count)); ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit, &pulse_count));
.. _managing-power: .. _pcnt-power-management:
电源管理 电源管理
^^^^^^^^^^ ^^^^^^^^^^
@ -243,7 +243,7 @@ PCNT 单元的滤波器可滤除信号中的短时毛刺,:cpp:type:`pcnt_glitc
驱动通过获取 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 类型的电源管理锁来防止系统修改 APB 频率。每当通过 :cpp:func:`pcnt_unit_set_glitch_filter` 使能毛刺滤波器时,驱动可以保证系统在 :cpp:func:`pcnt_unit_enable` 使能 PCNT 单元后获取电源管理锁。而系统调用 :cpp:func:`pcnt_unit_disable` 之后,驱动会释放电源管理锁。 驱动通过获取 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 类型的电源管理锁来防止系统修改 APB 频率。每当通过 :cpp:func:`pcnt_unit_set_glitch_filter` 使能毛刺滤波器时,驱动可以保证系统在 :cpp:func:`pcnt_unit_enable` 使能 PCNT 单元后获取电源管理锁。而系统调用 :cpp:func:`pcnt_unit_disable` 之后,驱动会释放电源管理锁。
.. _iram-safety: .. _pcnt-iram-safe:
支持 IRAM 安全中断 支持 IRAM 安全中断
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
@ -265,7 +265,7 @@ Konfig 选项 :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` 可以实现以下功能:
- :cpp:func:`pcnt_unit_clear_count` - :cpp:func:`pcnt_unit_clear_count`
- :cpp:func:`pcnt_unit_get_count` - :cpp:func:`pcnt_unit_get_count`
.. _thread-safe: .. _pcnt-thread-safe:
支持线程安全 支持线程安全
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@ -280,13 +280,13 @@ Konfig 选项 :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` 可以实现以下功能:
其他以 :cpp:type:`pcnt_unit_handle_t`:cpp:type:`pcnt_channel_handle_t` 作为第一个参数的函数被视为线程不安全函数,在多任务场景下应避免调用这些函数。 其他以 :cpp:type:`pcnt_unit_handle_t`:cpp:type:`pcnt_channel_handle_t` 作为第一个参数的函数被视为线程不安全函数,在多任务场景下应避免调用这些函数。
.. _kconfig-option: .. _pcnt-kconfig-options:
支持的 Kconfig 选项 支持的 Kconfig 选项
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
- :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` 用于确定 PCNT 控制函数的位置 (放在 IRAM 还是 flash 中),请参考 :ref:`iram-safety` 获取更多信息。 - :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` 用于确定 PCNT 控制函数的位置 (放在 IRAM 还是 flash 中),请参考 :ref:`pcnt-iram-safe` 获取更多信息。
- :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` 用于控制当缓存禁用时,默认的 ISR 句柄是否可以工作,请参考 :ref:`iram-safety` 获取更多信息。 - :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` 用于控制当缓存禁用时,默认的 ISR 句柄是否可以工作,请参考 :ref:`pcnt-iram-safe` 获取更多信息。
- :ref:`CONFIG_PCNT_ENABLE_DEBUG_LOG` 用于使能调试日志输出,而这会增大固件二进制文件。 - :ref:`CONFIG_PCNT_ENABLE_DEBUG_LOG` 用于使能调试日志输出,而这会增大固件二进制文件。
应用实例 应用实例

View File

@ -57,7 +57,7 @@ typedef struct {
pid_ctrl_block_handle_t pid_ctrl; pid_ctrl_block_handle_t pid_ctrl;
} motor_control_task_context_t; } motor_control_task_context_t;
static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *edata, void *user_ctx) static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx)
{ {
motor_control_timer_context_t *ctx = (motor_control_timer_context_t *)user_ctx; motor_control_timer_context_t *ctx = (motor_control_timer_context_t *)user_ctx;
ctx->accumu_count += edata->watch_point_value; ctx->accumu_count += edata->watch_point_value;

View File

@ -18,7 +18,7 @@ static const char *TAG = "example";
#define EXAMPLE_EC11_GPIO_A 0 #define EXAMPLE_EC11_GPIO_A 0
#define EXAMPLE_EC11_GPIO_B 2 #define EXAMPLE_EC11_GPIO_B 2
static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *edata, void *user_ctx) static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx)
{ {
BaseType_t high_task_wakeup; BaseType_t high_task_wakeup;
QueueHandle_t queue = (QueueHandle_t)user_ctx; QueueHandle_t queue = (QueueHandle_t)user_ctx;

View File

@ -39,7 +39,7 @@ static rmt_channel_handle_t s_rmt_chan;
static rmt_encoder_handle_t s_rmt_encoder; static rmt_encoder_handle_t s_rmt_encoder;
static volatile uint32_t s_milliseconds; static volatile uint32_t s_milliseconds;
static bool on_reach_watch_point(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *edata, void *user_ctx) static bool on_reach_watch_point(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx)
{ {
s_milliseconds += REF_CLOCK_PRESCALER_MS; s_milliseconds += REF_CLOCK_PRESCALER_MS;
return false; return false;