Merge branch 'feat/support_pcnt_on_h4' into 'master'

feat(pcnt): support pcnt on esp32h4

Closes IDF-12338 and IDF-13637

See merge request espressif/esp-idf!41526
This commit is contained in:
morris
2025-09-03 17:15:11 +08:00
67 changed files with 1542 additions and 791 deletions

View File

@@ -257,7 +257,7 @@ TEST_CASE("DAC_dma_convert_frequency_test", "[dac]")
gpio_set_direction(GPIO_NUM_4, GPIO_MODE_INPUT_OUTPUT);
// The DAC conversion frequency is equal to I2S bclk.
esp_rom_gpio_connect_out_signal(GPIO_NUM_4, i2s_periph_signal[0].m_tx_ws_sig, 0, 0);
esp_rom_gpio_connect_in_signal(GPIO_NUM_4, pcnt_periph_signals.groups[0].units[0].channels[0].pulse_sig, 0);
esp_rom_gpio_connect_in_signal(GPIO_NUM_4, soc_pcnt_signals[0].units[0].channels[0].pulse_sig_id_matrix, 0);
size_t len = 800;
uint8_t data[len];

View File

@@ -847,7 +847,7 @@ static void i2s_test_common_sample_rate(i2s_chan_handle_t rx_chan, i2s_std_clk_c
gpio_func_sel(MASTER_WS_IO, PIN_FUNC_GPIO);
gpio_set_direction(MASTER_WS_IO, GPIO_MODE_INPUT_OUTPUT);
esp_rom_gpio_connect_out_signal(MASTER_WS_IO, i2s_periph_signal[0].m_rx_ws_sig, 0, 0);
esp_rom_gpio_connect_in_signal(MASTER_WS_IO, pcnt_periph_signals.groups[0].units[0].channels[0].pulse_sig, 0);
esp_rom_gpio_connect_in_signal(MASTER_WS_IO, soc_pcnt_signals[0].units[0].channels[0].pulse_sig_id_matrix, 0);
const uint32_t test_freq[] = {
8000, 10000, 11025, 12000, 16000, 22050,

View File

@@ -59,6 +59,7 @@ typedef struct {
* @brief PCNT unit configuration
*/
typedef struct {
pcnt_clock_source_t clk_src; /*!< Clock source for PCNT unit */
int low_limit; /*!< Low limitation of the count unit, should be lower than 0 */
int high_limit; /*!< High limitation of the count unit, should be higher than 0 */
int intr_priority; /*!< PCNT interrupt priority,

View File

@@ -25,12 +25,13 @@
#include "soc/gpio_pins.h"
#include "hal/pcnt_hal.h"
#include "hal/pcnt_ll.h"
#include "driver/gpio.h"
#include "driver/pulse_cnt.h"
#include "esp_private/esp_clk.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/sleep_retention.h"
#include "driver/gpio.h"
#include "esp_private/gpio.h"
#include "driver/pulse_cnt.h"
#include "esp_private/esp_clk_tree_common.h"
#include "esp_memory_utils.h"
// If ISR handler is allowed to run whilst cache is disabled,
@@ -49,6 +50,12 @@
#define PCNT_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED
#if SOC_PERIPH_CLK_CTRL_SHARED
#define PCNT_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define PCNT_CLOCK_SRC_ATOMIC()
#endif
#if !SOC_RCC_IS_INDEPENDENT
#define PCNT_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
@@ -68,16 +75,17 @@ typedef struct pcnt_chan_t pcnt_chan_t;
struct pcnt_platform_t {
_lock_t mutex; // platform level mutex lock
pcnt_group_t *groups[SOC_PCNT_GROUPS]; // pcnt group pool
int group_ref_counts[SOC_PCNT_GROUPS]; // reference count used to protect group install/uninstall
pcnt_group_t *groups[SOC_PCNT_ATTR(INST_NUM)]; // pcnt group pool
int group_ref_counts[SOC_PCNT_ATTR(INST_NUM)]; // reference count used to protect group install/uninstall
};
struct pcnt_group_t {
int group_id; // Group ID, index from 0
int intr_priority; // PCNT interrupt priority
pcnt_clock_source_t clk_src; // PCNT clock source
portMUX_TYPE spinlock; // to protect per-group register level concurrent access
pcnt_hal_context_t hal;
pcnt_unit_t *units[SOC_PCNT_UNITS_PER_GROUP]; // array of PCNT units
pcnt_unit_t *units[SOC_PCNT_ATTR(UNITS_PER_INST)]; // array of PCNT units
#if CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock; // power management lock
#endif
@@ -112,7 +120,7 @@ struct pcnt_unit_t {
int clear_signal_gpio_num; // which gpio clear signal input
int accum_value; // accumulated count value
pcnt_step_interval_t step_info; // step interval info
pcnt_chan_t *channels[SOC_PCNT_CHANNELS_PER_UNIT]; // array of PCNT channels
pcnt_chan_t *channels[SOC_PCNT_ATTR(CHANS_PER_UNIT)]; // array of PCNT channels
pcnt_watch_point_t watchers[PCNT_LL_WATCH_EVENT_MAX]; // array of PCNT watchers
intr_handle_t intr; // interrupt handle
pcnt_unit_fsm_t fsm; // record PCNT unit's driver state
@@ -140,17 +148,18 @@ static pcnt_platform_t s_platform;
static pcnt_group_t *pcnt_acquire_group_handle(int group_id);
static void pcnt_release_group_handle(pcnt_group_t *group);
static void pcnt_default_isr(void *args);
static esp_err_t pcnt_select_periph_clock(pcnt_unit_t *unit, pcnt_clock_source_t clk_src);
static esp_err_t pcnt_register_to_group(pcnt_unit_t *unit)
{
pcnt_group_t *group = NULL;
int unit_id = -1;
for (int i = 0; i < SOC_PCNT_GROUPS; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(INST_NUM); i++) {
group = pcnt_acquire_group_handle(i);
ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no mem for group (%d)", i);
// loop to search free unit in the group
portENTER_CRITICAL(&group->spinlock);
for (int j = 0; j < SOC_PCNT_UNITS_PER_GROUP; j++) {
for (int j = 0; j < SOC_PCNT_ATTR(UNITS_PER_INST); j++) {
if (!group->units[j]) {
unit_id = j;
group->units[j] = unit;
@@ -222,6 +231,10 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re
int group_id = group->group_id;
int unit_id = unit->unit_id;
pcnt_clock_source_t pcnt_clk_src = config->clk_src ? config->clk_src : PCNT_CLK_SRC_DEFAULT;
ESP_GOTO_ON_ERROR(pcnt_select_periph_clock(unit, pcnt_clk_src), err, TAG, "select periph clock failed");
ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)group->clk_src, true), err, TAG, "clock source enable failed");
// if interrupt priority specified before, it cannot be changed until the group is released
// check if the new priority specified consistents with the old one
bool intr_priority_conflict = false;
@@ -243,7 +256,7 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re
} else {
isr_flags |= PCNT_ALLOW_INTR_PRIORITY_MASK;
}
ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(pcnt_periph_signals.groups[group_id].irq, isr_flags,
ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(soc_pcnt_signals[group_id].irq_id, isr_flags,
(uint32_t)pcnt_ll_get_intr_status_reg(group->hal.dev), PCNT_LL_UNIT_WATCH_EVENT(unit_id),
pcnt_default_isr, unit, &unit->intr), err,
TAG, "install interrupt service failed");
@@ -311,18 +324,20 @@ esp_err_t pcnt_del_unit(pcnt_unit_handle_t unit)
int group_id = group->group_id;
int unit_id = unit->unit_id;
for (int i = 0; i < SOC_PCNT_CHANNELS_PER_UNIT; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(CHANS_PER_UNIT); i++) {
ESP_RETURN_ON_FALSE(!unit->channels[i], ESP_ERR_INVALID_STATE, TAG, "channel %d still in working", i);
}
#if SOC_PCNT_SUPPORT_CLEAR_SIGNAL
if (unit->clear_signal_gpio_num >= 0) {
uint32_t clear_signal_idx = pcnt_periph_signals.groups[group_id].units[unit_id].clear_sig;
uint32_t clear_signal_idx = soc_pcnt_signals[group_id].units[unit_id].clear_sig_id_matrix;
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, clear_signal_idx, 0);
}
#endif // SOC_PCNT_SUPPORT_CLEAR_SIGNAL
ESP_LOGD(TAG, "del unit (%d,%d)", group_id, unit_id);
// disable clock source
ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)group->clk_src, false), TAG, "clock source disable failed");
// recycle memory resource
ESP_RETURN_ON_ERROR(pcnt_destroy(unit), TAG, "destroy pcnt unit failed");
return ESP_OK;
@@ -335,7 +350,7 @@ esp_err_t pcnt_unit_set_clear_signal(pcnt_unit_handle_t unit, const pcnt_clear_s
pcnt_group_t *group = unit->group;
int group_id = group->group_id;
int unit_id = unit->unit_id;
uint32_t clear_signal_idx = pcnt_periph_signals.groups[group_id].units[unit_id].clear_sig;
uint32_t clear_signal_idx = soc_pcnt_signals[group_id].units[unit_id].clear_sig_id_matrix;
if (config) {
int io_num = config->clear_signal_gpio_num;
@@ -534,7 +549,7 @@ esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt
} else {
isr_flags |= PCNT_ALLOW_INTR_PRIORITY_MASK;
}
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(pcnt_periph_signals.groups[group_id].irq, isr_flags,
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(soc_pcnt_signals[group_id].irq_id, isr_flags,
(uint32_t)pcnt_ll_get_intr_status_reg(group->hal.dev), PCNT_LL_UNIT_WATCH_EVENT(unit_id),
pcnt_default_isr, unit, &unit->intr),
TAG, "install interrupt service failed");
@@ -592,7 +607,7 @@ esp_err_t pcnt_unit_add_watch_point(pcnt_unit_handle_t unit, int watch_point)
}
// other threshold watch point
else {
int thres_num = SOC_PCNT_THRES_POINT_PER_UNIT - 1;
int thres_num = SOC_PCNT_ATTR(THRES_POINT_PER_UNIT) - 1;
switch (thres_num) {
case 1:
if (unit->watchers[PCNT_LL_WATCH_EVENT_THRES1].event_id == PCNT_LL_WATCH_EVENT_INVALID) {
@@ -779,7 +794,7 @@ esp_err_t pcnt_new_channel(pcnt_unit_handle_t unit, const pcnt_chan_config_t *co
// search for a free channel
int channel_id = -1;
portENTER_CRITICAL(&unit->spinlock);
for (int i = 0; i < SOC_PCNT_CHANNELS_PER_UNIT; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(CHANS_PER_UNIT); i++) {
if (!unit->channels[i]) {
channel_id = i;
unit->channels[channel_id] = channel;
@@ -794,12 +809,12 @@ esp_err_t pcnt_new_channel(pcnt_unit_handle_t unit, const pcnt_chan_config_t *co
gpio_func_sel(config->edge_gpio_num, PIN_FUNC_GPIO);
gpio_input_enable(config->edge_gpio_num);
esp_rom_gpio_connect_in_signal(config->edge_gpio_num,
pcnt_periph_signals.groups[group_id].units[unit_id].channels[channel_id].pulse_sig,
soc_pcnt_signals[group_id].units[unit_id].channels[channel_id].pulse_sig_id_matrix,
config->flags.invert_edge_input);
} else {
// using virtual IO
esp_rom_gpio_connect_in_signal(config->flags.virt_edge_io_level ? GPIO_MATRIX_CONST_ONE_INPUT : GPIO_MATRIX_CONST_ZERO_INPUT,
pcnt_periph_signals.groups[group_id].units[unit_id].channels[channel_id].pulse_sig,
soc_pcnt_signals[group_id].units[unit_id].channels[channel_id].pulse_sig_id_matrix,
config->flags.invert_edge_input);
}
@@ -807,12 +822,12 @@ esp_err_t pcnt_new_channel(pcnt_unit_handle_t unit, const pcnt_chan_config_t *co
gpio_func_sel(config->level_gpio_num, PIN_FUNC_GPIO);
gpio_input_enable(config->level_gpio_num);
esp_rom_gpio_connect_in_signal(config->level_gpio_num,
pcnt_periph_signals.groups[group_id].units[unit_id].channels[channel_id].control_sig,
soc_pcnt_signals[group_id].units[unit_id].channels[channel_id].ctl_sig_id_matrix,
config->flags.invert_level_input);
} else {
// using virtual IO
esp_rom_gpio_connect_in_signal(config->flags.virt_level_io_level ? GPIO_MATRIX_CONST_ONE_INPUT : GPIO_MATRIX_CONST_ZERO_INPUT,
pcnt_periph_signals.groups[group_id].units[unit_id].channels[channel_id].control_sig,
soc_pcnt_signals[group_id].units[unit_id].channels[channel_id].ctl_sig_id_matrix,
config->flags.invert_level_input);
}
@@ -846,12 +861,12 @@ esp_err_t pcnt_del_channel(pcnt_channel_handle_t chan)
if (chan->level_gpio_num >= 0) {
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT,
pcnt_periph_signals.groups[group_id].units[unit_id].channels[channel_id].control_sig,
soc_pcnt_signals[group_id].units[unit_id].channels[channel_id].ctl_sig_id_matrix,
0);
}
if (chan->edge_gpio_num >= 0) {
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT,
pcnt_periph_signals.groups[group_id].units[unit_id].channels[channel_id].pulse_sig,
soc_pcnt_signals[group_id].units[unit_id].channels[channel_id].pulse_sig_id_matrix,
0);
}
@@ -930,14 +945,6 @@ static pcnt_group_t *pcnt_acquire_group_handle(int group_id)
_lock_release(&s_platform.mutex);
if (new_group) {
#if CONFIG_PM_ENABLE
// PCNT uses the APB as its function clock,
// and its filter module is sensitive to the clock frequency
// thus we choose the APM_MAX lock to prevent the function clock from being changed
if (esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, pcnt_periph_signals.groups[group_id].module_name, &group->pm_lock) != ESP_OK) {
ESP_LOGW(TAG, "create pm lock failed");
}
#endif
ESP_LOGD(TAG, "new group (%d) at %p", group_id, group);
}
@@ -975,6 +982,48 @@ static void pcnt_release_group_handle(pcnt_group_t *group)
}
}
static esp_err_t pcnt_select_periph_clock(pcnt_unit_t *unit, pcnt_clock_source_t clk_src)
{
esp_err_t ret = ESP_OK;
pcnt_group_t *group = unit->group;
bool clock_selection_conflict = false;
bool do_clock_init = false;
// group clock source is shared by all units
portENTER_CRITICAL(&group->spinlock);
if (group->clk_src == 0) {
group->clk_src = clk_src;
do_clock_init = true;
} else {
clock_selection_conflict = (group->clk_src != clk_src);
}
portEXIT_CRITICAL(&group->spinlock);
ESP_RETURN_ON_FALSE(!clock_selection_conflict, ESP_ERR_INVALID_ARG, TAG,
"group clock conflict, already is %d but attempt to %d", group->clk_src, clk_src);
if (do_clock_init) {
#if CONFIG_PM_ENABLE
// PCNT filter module is sensitive to the clock frequency
// to make the pcnt works reliable, the source clock must stay alive and unchanged
esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP;
#if PCNT_LL_CLOCK_SUPPORT_APB
if (clk_src == PCNT_CLK_SRC_APB) {
// APB clock frequency can be changed during DFS
// thus we choose the APM_MAX lock to prevent the function clock from being changed
pm_lock_type = ESP_PM_APB_FREQ_MAX;
}
#endif // PCNT_LL_CLOCK_SUPPORT_APB
ret = esp_pm_lock_create(pm_lock_type, 0, soc_pcnt_signals[group->group_id].module_name, &group->pm_lock);
ESP_RETURN_ON_ERROR(ret, TAG, "create pm lock failed");
#endif // CONFIG_PM_ENABLE
PCNT_CLOCK_SRC_ATOMIC() {
pcnt_ll_set_clock_source(group->hal.dev, clk_src);
}
}
return ret;
}
IRAM_ATTR static void pcnt_default_isr(void *args)
{
bool need_yield = false;

View File

@@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |

View File

@@ -9,12 +9,13 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "soc/soc_caps.h"
#include "soc/pcnt_periph.h"
#include "hal/pcnt_ll.h"
#include "driver/pulse_cnt.h"
#include "driver/gpio.h"
#include "soc/soc_caps.h"
#include "esp_attr.h"
#include "test_pulse_cnt_board.h"
#include "hal/pcnt_ll.h"
TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
{
@@ -23,11 +24,11 @@ TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
.high_limit = 100,
.intr_priority = 0,
};
pcnt_unit_handle_t units[SOC_PCNT_UNITS_PER_GROUP];
pcnt_unit_handle_t units[SOC_PCNT_ATTR(UNITS_PER_INST)];
int count_value = 0;
printf("install pcnt units and check initial count\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP - 1; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST) - 1; i++) {
TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
TEST_ASSERT_EQUAL(0, count_value);
@@ -35,9 +36,9 @@ TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
// unit with a different interrupt priority
unit_config.intr_priority = 3;
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, pcnt_new_unit(&unit_config, &units[SOC_PCNT_UNITS_PER_GROUP - 1]));
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, pcnt_new_unit(&unit_config, &units[SOC_PCNT_ATTR(UNITS_PER_INST) - 1]));
unit_config.intr_priority = 0;
TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[SOC_PCNT_UNITS_PER_GROUP - 1]));
TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[SOC_PCNT_ATTR(UNITS_PER_INST) - 1]));
// no more free pcnt units
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, pcnt_new_unit(&unit_config, &units[0]));
@@ -46,7 +47,7 @@ TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
pcnt_glitch_filter_config_t filter_config = {
.max_glitch_ns = 1000,
};
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_unit_set_glitch_filter(units[i], &filter_config));
}
// invalid glitch configuration
@@ -56,30 +57,30 @@ TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
.on_reach = NULL,
};
printf("enable pcnt units\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_unit_register_event_callbacks(units[i], &cbs, NULL));
TEST_ESP_OK(pcnt_unit_enable(units[i]));
}
printf("start pcnt units\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_unit_start(units[i]));
}
printf("stop pcnt units\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_unit_stop(units[i]));
}
// can't uninstall unit before disable it
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[0]));
printf("disable pcnt units\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_unit_disable(units[i]));
}
printf("uninstall pcnt units\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_del_unit(units[i]));
}
}
@@ -96,17 +97,17 @@ TEST_CASE("pcnt_channel_install_uninstall", "[pcnt]")
.edge_gpio_num = TEST_PCNT_GPIO_A, // only detect edge signal in this case
.level_gpio_num = -1,
};
pcnt_unit_handle_t units[SOC_PCNT_UNITS_PER_GROUP];
pcnt_channel_handle_t chans[SOC_PCNT_UNITS_PER_GROUP][SOC_PCNT_CHANNELS_PER_UNIT];
pcnt_unit_handle_t units[SOC_PCNT_ATTR(UNITS_PER_INST)];
pcnt_channel_handle_t chans[SOC_PCNT_ATTR(UNITS_PER_INST)][SOC_PCNT_ATTR(CHANS_PER_UNIT)];
printf("install pcnt units\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
}
printf("install pcnt channels\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int j = 0; j < SOC_PCNT_CHANNELS_PER_UNIT; j++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
for (int j = 0; j < SOC_PCNT_ATTR(CHANS_PER_UNIT); j++) {
TEST_ESP_OK(pcnt_new_channel(units[i], &chan_config, &chans[i][j]));
TEST_ESP_OK(pcnt_channel_set_edge_action(chans[i][j], PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
TEST_ESP_OK(pcnt_channel_set_level_action(chans[i][j], PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
@@ -117,55 +118,55 @@ TEST_CASE("pcnt_channel_install_uninstall", "[pcnt]")
printf("start units\r\n");
int count_value = 0;
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
// start unit
TEST_ESP_OK(pcnt_unit_start(units[i]));
// trigger 10 rising edge on GPIO0
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
// each channel increases to the same unit counter
TEST_ASSERT_EQUAL(10 * SOC_PCNT_CHANNELS_PER_UNIT, count_value);
TEST_ASSERT_EQUAL(10 * SOC_PCNT_ATTR(CHANS_PER_UNIT), count_value);
}
printf("clear counts\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_unit_clear_count(units[i]));
TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
TEST_ASSERT_EQUAL(0, count_value);
}
printf("stop unit\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
// stop unit
TEST_ESP_OK(pcnt_unit_stop(units[i]));
}
// trigger 10 rising edge on GPIO0 shouldn't increase the counter
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
TEST_ASSERT_EQUAL(0, count_value);
}
printf("restart units\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
// start unit
TEST_ESP_OK(pcnt_unit_start(units[i]));
// trigger 10 rising edge on GPIO
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
// each channel increases to the same unit counter
TEST_ASSERT_EQUAL(10 * SOC_PCNT_CHANNELS_PER_UNIT, count_value);
TEST_ASSERT_EQUAL(10 * SOC_PCNT_ATTR(CHANS_PER_UNIT), count_value);
}
printf("uninstall channels and units\r\n");
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
for (int i = 0; i < SOC_PCNT_ATTR(UNITS_PER_INST); i++) {
// stop unit
TEST_ESP_OK(pcnt_unit_stop(units[i]));
TEST_ESP_OK(pcnt_unit_disable(units[i]));
// can't uninstall unit when channel is still alive
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[i]));
for (int j = 0; j < SOC_PCNT_CHANNELS_PER_UNIT; j++) {
for (int j = 0; j < SOC_PCNT_ATTR(CHANS_PER_UNIT); j++) {
TEST_ESP_OK(pcnt_del_channel(chans[i][j]));
}
TEST_ESP_OK(pcnt_del_unit(units[i]));

View File

@@ -19,10 +19,11 @@
#include <stdbool.h>
#include <soc/soc.h>
#include "soc/pcnt_struct.h"
#include "hal/pcnt_types.h"
#include "hal/misc.h"
#include "soc/dport_access.h"
#include "soc/dport_reg.h"
#include "hal/pcnt_types.h"
#include "hal/misc.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -45,6 +46,19 @@ typedef enum {
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
#define PCNT_LL_CLOCK_SUPPORT_APB 1
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
HAL_ASSERT(clk_src == PCNT_CLK_SRC_APB && "unsupported clock source");
}
/**
* @brief Set PCNT channel edge action

View File

@@ -10,9 +10,10 @@
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "soc/pcr_struct.h"
#include "hal/pcnt_types.h"
#include "hal/misc.h"
#include "soc/pcr_struct.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -40,6 +41,19 @@ typedef enum {
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
#define PCNT_LL_CLOCK_SUPPORT_APB 1
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
HAL_ASSERT(clk_src == PCNT_CLK_SRC_APB && "unsupported clock source");
}
/**
* @brief Set PCNT channel edge action

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,8 +18,9 @@
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "hal/pcnt_types.h"
#include "soc/pcr_struct.h"
#include "hal/pcnt_types.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -42,6 +43,19 @@ typedef enum {
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
#define PCNT_LL_CLOCK_SUPPORT_APB 1
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
HAL_ASSERT(clk_src == PCNT_CLK_SRC_APB && "unsupported clock source");
}
/**
* @brief Set PCNT channel edge action

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,11 +18,12 @@
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "hal/pcnt_types.h"
#include "hal/misc.h"
#include "hal/efuse_hal.h"
#include "soc/chip_revision.h"
#include "soc/pcr_struct.h"
#include "hal/pcnt_types.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/efuse_hal.h"
#ifdef __cplusplus
extern "C" {
@@ -48,9 +49,22 @@ typedef enum {
PCNT_LL_STEP_EVENT_REACH_INTERVAL
} pcnt_ll_step_event_id_t;
#define PCNT_LL_STEP_NOTIFY_DIR_LIMIT 1
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
#define PCNT_LL_STEP_NOTIFY_DIR_LIMIT 1
#define PCNT_LL_CLOCK_SUPPORT_APB 1
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
HAL_ASSERT(clk_src == PCNT_CLK_SRC_APB && "unsupported clock source");
}
/**
* @brief Set PCNT channel edge action

View File

@@ -10,9 +10,10 @@
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "soc/pcr_struct.h"
#include "hal/pcnt_types.h"
#include "hal/misc.h"
#include "soc/pcr_struct.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -40,6 +41,19 @@ typedef enum {
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
#define PCNT_LL_CLOCK_SUPPORT_APB 1
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
HAL_ASSERT(clk_src == PCNT_CLK_SRC_APB && "unsupported clock source");
}
/**
* @brief Set PCNT channel edge action

View File

@@ -0,0 +1,527 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <limits.h>
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "soc/pcr_struct.h"
#include "hal/pcnt_types.h"
#include "hal/misc.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL)
#define PCNT_LL_MAX_GLITCH_WIDTH 1023
#define PCNT_LL_MAX_LIM SHRT_MAX
#define PCNT_LL_MIN_LIM SHRT_MIN
typedef enum {
PCNT_LL_WATCH_EVENT_INVALID = -1,
PCNT_LL_WATCH_EVENT_THRES1,
PCNT_LL_WATCH_EVENT_THRES0,
PCNT_LL_WATCH_EVENT_LOW_LIMIT,
PCNT_LL_WATCH_EVENT_HIGH_LIMIT,
PCNT_LL_WATCH_EVENT_ZERO_CROSS,
PCNT_LL_WATCH_EVENT_MAX
} pcnt_ll_watch_event_id_t;
typedef enum {
PCNT_LL_STEP_EVENT_REACH_INTERVAL_FORWARD = PCNT_LL_WATCH_EVENT_MAX,
PCNT_LL_STEP_EVENT_REACH_INTERVAL_BACKWARD,
} pcnt_ll_step_event_id_t;
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
switch (clk_src) {
case PCNT_CLK_SRC_XTAL:
PCR.pcnt_conf.pcnt_clk_sel = 0;
break;
case PCNT_CLK_SRC_RC_FAST:
PCR.pcnt_conf.pcnt_clk_sel = 1;
break;
default:
HAL_ASSERT(false && "unsupported clock source");
break;
}
}
/**
* @brief Set PCNT channel edge action
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param channel PCNT channel number
* @param pos_act Counter action when detecting positive edge
* @param neg_act Counter action when detecting negative edge
*/
static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act)
{
if (channel == 0) {
hw->conf_unit[unit].conf0.ch0_pos_mode_un = pos_act;
hw->conf_unit[unit].conf0.ch0_neg_mode_un = neg_act;
} else {
hw->conf_unit[unit].conf0.ch1_pos_mode_un = pos_act;
hw->conf_unit[unit].conf0.ch1_neg_mode_un = neg_act;
}
}
/**
* @brief Set PCNT channel level action
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param channel PCNT channel number
* @param high_act Counter action when control signal is high level
* @param low_act Counter action when control signal is low level
*/
static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act)
{
if (channel == 0) {
hw->conf_unit[unit].conf0.ch0_hctrl_mode_un = high_act;
hw->conf_unit[unit].conf0.ch0_lctrl_mode_un = low_act;
} else {
hw->conf_unit[unit].conf0.ch1_hctrl_mode_un = high_act;
hw->conf_unit[unit].conf0.ch1_lctrl_mode_un = low_act;
}
}
/**
* @brief Get pulse counter value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit Pulse Counter unit number
* @return PCNT count value (a signed integer)
*/
__attribute__((always_inline))
static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit)
{
pcnt_un_cnt_reg_t cnt_reg;
cnt_reg.val = hw->cnt_unit[unit].val;
int16_t value = cnt_reg.pulse_cnt_un;
return value;
}
/**
* @brief Pause PCNT counter of PCNT unit
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
*/
__attribute__((always_inline))
static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit)
{
hw->ctrl.val |= 1 << (2 * unit + 1);
}
/**
* @brief Resume counting for PCNT counter
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number, select from uint32_t
*/
__attribute__((always_inline))
static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit)
{
hw->ctrl.val &= ~(1 << (2 * unit + 1));
}
/**
* @brief Clear PCNT counter value to zero
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number, select from uint32_t
*/
__attribute__((always_inline))
static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit)
{
hw->ctrl.val |= 1 << (2 * unit);
hw->ctrl.val &= ~(1 << (2 * unit));
}
/**
* @brief Enable PCNT step comparator event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_step_notify(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
if (enable) {
hw->ctrl.val |= 1 << (8 + unit);
} else {
hw->ctrl.val &= ~(1 << (8 + unit));
}
}
/**
* @brief Set PCNT step value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param direction PCNT step direction
* @param value PCNT step value
*/
static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, pcnt_step_direction_t direction, uint16_t value)
{
if (direction == PCNT_STEP_FORWARD) {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->conf_unit[unit].conf3, cnt_h_step_un, value);
} else {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->conf_unit[unit].conf3, cnt_l_step_un, value);
}
}
/**
* @brief Enable PCNT interrupt for PCNT unit
* @note Each PCNT unit has five watch point events that share the same interrupt bit.
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit_mask PCNT units mask
* @param enable True to enable interrupt, False to disable interrupt
*/
static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable)
{
if (enable) {
hw->int_ena.val |= unit_mask;
} else {
hw->int_ena.val &= ~unit_mask;
}
}
/**
* @brief Get PCNT interrupt status
*
* @param hw Peripheral PCNT hardware instance address.
* @return Interrupt status word
*/
__attribute__((always_inline))
static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw)
{
return hw->int_st.val;
}
/**
* @brief Clear PCNT interrupt status
*
* @param hw Peripheral PCNT hardware instance address.
* @param status value to clear interrupt status
*/
__attribute__((always_inline))
static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
{
hw->int_clr.val = status;
}
/**
* @brief Enable PCNT high limit event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
hw->conf_unit[unit].conf0.thr_h_lim_en_un = enable;
}
/**
* @brief Enable PCNT low limit event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
hw->conf_unit[unit].conf0.thr_l_lim_en_un = enable;
}
/**
* @brief Enable PCNT zero cross event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
hw->conf_unit[unit].conf0.thr_zero_en_un = enable;
}
/**
* @brief Enable PCNT threshold event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param thres Threshold ID
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable)
{
if (thres == 0) {
hw->conf_unit[unit].conf0.thr_thres0_en_un = enable;
} else {
hw->conf_unit[unit].conf0.thr_thres1_en_un = enable;
}
}
/**
* @brief Disable all PCNT threshold events
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit unit number
*/
static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit)
{
hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_WATCH_EVENT_MASK << 11);
}
/**
* @brief Set PCNT high limit value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param value PCNT high limit value
*/
static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
{
pcnt_un_conf2_reg_t conf2_reg;
conf2_reg.val = hw->conf_unit[unit].conf2.val;
conf2_reg.cnt_h_lim_un = value;
hw->conf_unit[unit].conf2.val = conf2_reg.val;
}
/**
* @brief Set PCNT low limit value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param value PCNT low limit value
*/
static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
{
pcnt_un_conf2_reg_t conf2_reg;
conf2_reg.val = hw->conf_unit[unit].conf2.val;
conf2_reg.cnt_l_lim_un = value;
hw->conf_unit[unit].conf2.val = conf2_reg.val;
}
/**
* @brief Set PCNT threshold value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param thres Threshold ID
* @param value PCNT threshold value
*/
static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value)
{
pcnt_un_conf1_reg_t conf1_reg;
conf1_reg.val = hw->conf_unit[unit].conf1.val;
if (thres == 0) {
conf1_reg.cnt_thres0_un = value;
} else {
conf1_reg.cnt_thres1_un = value;
}
hw->conf_unit[unit].conf1.val = conf1_reg.val;
}
/**
* @brief Get PCNT high limit value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return PCNT high limit value
*/
static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit)
{
pcnt_un_conf2_reg_t conf2_reg;
conf2_reg.val = hw->conf_unit[unit].conf2.val;
int16_t value = conf2_reg.cnt_h_lim_un;
return value;
}
/**
* @brief Get PCNT low limit value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return PCNT high limit value
*/
static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit)
{
pcnt_un_conf2_reg_t conf2_reg;
conf2_reg.val = hw->conf_unit[unit].conf2.val;
int16_t value = conf2_reg.cnt_l_lim_un ;
return value;
}
/**
* @brief Get PCNT threshold value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param thres Threshold ID
* @return PCNT threshold value
*/
__attribute__((always_inline))
static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres)
{
int16_t value;
pcnt_un_conf1_reg_t conf1_reg;
conf1_reg.val = hw->conf_unit[unit].conf1.val;
if (thres == 0) {
value = conf1_reg.cnt_thres0_un ;
} else {
value = conf1_reg.cnt_thres1_un ;
}
return value;
}
/**
* @brief Get PCNT unit runtime status
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return PCNT unit runtime status
*/
static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit)
{
return hw->status_unit[unit].val;
}
/**
* @brief Get PCNT zero cross mode
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return Zero cross mode
*/
__attribute__((always_inline))
static inline pcnt_unit_zero_cross_mode_t pcnt_ll_get_zero_cross_mode(pcnt_dev_t *hw, uint32_t unit)
{
return (pcnt_unit_zero_cross_mode_t)(hw->status_unit[unit].val & 0x03);
}
/**
* @brief Get PCNT event status
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return Event status word
*/
__attribute__((always_inline))
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit)
{
return hw->status_unit[unit].val >> 2;
}
/**
* @brief Set PCNT glitch filter threshold
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param filter_val PCNT signal filter value, counter in APB_CLK cycles.
* Any pulses lasting shorter than this will be ignored when the filter is enabled.
*/
static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val)
{
hw->conf_unit[unit].conf0.filter_thres_un = filter_val;
}
/**
* @brief Get PCNT glitch filter threshold
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return glitch filter threshold
*/
static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit)
{
return hw->conf_unit[unit].conf0.filter_thres_un;
}
/**
* @brief Enable PCNT glitch filter
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable True to enable the filter, False to disable the filter
*/
static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
hw->conf_unit[unit].conf0.filter_en_un = enable;
}
/**
* @brief Get interrupt status register address.
*
* @param hw Beginning address of the peripheral registers.
*
* @return Interrupt status register address
*/
static inline volatile void *pcnt_ll_get_intr_status_reg(pcnt_dev_t *hw)
{
return &hw->int_st.val;
}
/**
* @brief Enable or disable the bus clock for the PCNT module
*
* @param set_bit True to set bit, false to clear bit
*/
static inline void pcnt_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
PCR.pcnt_conf.pcnt_clk_en = enable;
PCR.pcnt_conf.pcnt_reg_clk_en = enable;
}
/**
* @brief Reset the PCNT module
*/
static inline void pcnt_ll_reset_register(int group_id)
{
(void)group_id;
PCR.pcnt_conf.pcnt_rst_en = 1;
PCR.pcnt_conf.pcnt_rst_en = 0;
}
/**
* @brief Check if the step notify is supported
*/
static inline bool pcnt_ll_is_step_notify_supported(int group_id)
{
(void)group_id;
return true;
}
#ifdef __cplusplus
}
#endif

View File

@@ -18,9 +18,10 @@
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "hal/pcnt_types.h"
#include "hal/misc.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -43,6 +44,26 @@ typedef enum {
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
#define PCNT_LL_CLOCK_SUPPORT_APB 1
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void _pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
HAL_ASSERT(clk_src == PCNT_CLK_SRC_APB && "unsupported clock source");
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define pcnt_ll_set_clock_source(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_pcnt_ll_set_clock_source(__VA_ARGS__); \
} while(0)
/**
* @brief Set PCNT channel edge action

View File

@@ -18,9 +18,10 @@
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "hal/pcnt_types.h"
#include "soc/dport_reg.h"
#include "soc/dport_access.h"
#include "hal/pcnt_types.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -43,6 +44,19 @@ typedef enum {
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
#define PCNT_LL_CLOCK_SUPPORT_APB 1
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
HAL_ASSERT(clk_src == PCNT_CLK_SRC_APB && "unsupported clock source");
}
/**
* @brief Set PCNT channel edge action

View File

@@ -18,8 +18,9 @@
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "hal/pcnt_types.h"
#include "soc/system_struct.h"
#include "hal/pcnt_types.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -42,6 +43,19 @@ typedef enum {
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
#define PCNT_LL_CLOCK_SUPPORT_APB 1
/**
* @brief Set clock source for pcnt group
*
* @param hw Peripheral PCNT hardware instance address.
* @param clk_src Clock source
*/
static inline void pcnt_ll_set_clock_source(pcnt_dev_t *hw, pcnt_clock_source_t clk_src)
{
(void)hw;
HAL_ASSERT(clk_src == PCNT_CLK_SRC_APB && "unsupported clock source");
}
/**
* @brief Set PCNT channel edge action

View File

@@ -6,10 +6,26 @@
#pragma once
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_HAS(PCNT)
/**
* @brief PCNT clock source
* @note User should select the clock source based on the power and resolution requirement
*/
typedef soc_periph_pcnt_clk_src_t pcnt_clock_source_t;
#else
/**
* @brief Default type
*/
typedef int pcnt_clock_source_t;
#endif
/**
* @brief PCNT channel action on control level
*/

View File

@@ -559,22 +559,6 @@ config SOC_MPU_REGION_WO_SUPPORTED
bool
default n
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 8
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_RMT_GROUPS
int
default 1

View File

@@ -218,6 +218,21 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_APB, /*!< RMT source clock default choice is APB */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
} soc_periph_pcnt_clk_src_t;
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
/**

View File

@@ -275,12 +275,6 @@
#define SOC_MPU_REGION_RO_SUPPORTED 0
#define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS (1U)
#define SOC_PCNT_UNITS_PER_GROUP (8)
#define SOC_PCNT_CHANNELS_PER_UNIT (2)
#define SOC_PCNT_THRES_POINT_PER_UNIT (2)
/*-------------------------- RMT CAPS ----------------------------------------*/
#define SOC_RMT_GROUPS 1U /*!< One RMT group */
#define SOC_RMT_TX_CANDIDATES_PER_GROUP 8 /*!< Number of channels that capable of Transmit in each group */

View File

@@ -23,3 +23,9 @@
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 8 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 8 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -8,106 +8,104 @@
#include "soc/gpio_sig_map.h"
#include "soc/soc.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.irq = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_IN0_IDX
}
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN0_IDX
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_IN1_IDX
}
}
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN1_IDX
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_IN2_IDX
}
}
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN2_IDX
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_IN3_IDX
}
}
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN3_IDX
}
},
[4] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN4_IDX,
.pulse_sig = PCNT_SIG_CH0_IN4_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN4_IDX,
.pulse_sig = PCNT_SIG_CH1_IN4_IDX
}
}
},
[4] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN4_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN4_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN4_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN4_IDX
}
},
[5] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN5_IDX,
.pulse_sig = PCNT_SIG_CH0_IN5_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN5_IDX,
.pulse_sig = PCNT_SIG_CH1_IN5_IDX
}
}
},
[5] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN5_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN5_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN5_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN5_IDX
}
},
[6] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN6_IDX,
.pulse_sig = PCNT_SIG_CH0_IN6_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN6_IDX,
.pulse_sig = PCNT_SIG_CH1_IN6_IDX
}
}
},
[6] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN6_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN6_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN6_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN6_IDX
}
},
[7] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN7_IDX,
.pulse_sig = PCNT_SIG_CH0_IN7_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN7_IDX,
.pulse_sig = PCNT_SIG_CH1_IN7_IDX
}
}
},
[7] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN7_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN7_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN7_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN7_IDX
}
}
}

View File

@@ -839,22 +839,6 @@ config SOC_MMU_DI_VADDR_SHARED
bool
default y
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 4
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
bool
default y

View File

@@ -87,6 +87,7 @@ typedef enum {
SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL_D2 or RC_FAST by configuring soc_rtc_fast_clk_src_t */
SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or OSC_SLOW by configuring soc_rtc_slow_clk_src_t */
// For digital domain: peripherals, WIFI, BLE
SOC_MOD_CLK_APB, /*!< APB_CLK is highly dependent on the CPU_CLK source */
SOC_MOD_CLK_PLL_F12M, /*!< PLL_F12M_CLK is derived from SPLL (clock gating + fixed divider of 40), it has a fixed frequency of 12MHz */
SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + fixed divider of 24), it has a fixed frequency of 20MHz */
SOC_MOD_CLK_PLL_F40M, /*!< PLL_F40M_CLK is derived from SPLL (clock gating + fixed divider of 12), it has a fixed frequency of 40MHz */
@@ -218,6 +219,21 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< RMT source clock default choice is PLL_F80M */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
} soc_periph_pcnt_clk_src_t;
//////////////////////////////////////////////////Temp Sensor///////////////////////////////////////////////////////////
/**

View File

@@ -339,10 +339,6 @@
// #define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS 1U
#define SOC_PCNT_UNITS_PER_GROUP 4
#define SOC_PCNT_CHANNELS_PER_UNIT 2
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
#define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1
#define SOC_PCNT_SUPPORT_STEP_NOTIFY 1

View File

@@ -24,6 +24,12 @@
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 4 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -8,64 +8,62 @@
#include "soc/gpio_sig_map.h"
#include "soc/pcnt_reg.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.irq = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_IN0_IDX
}
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN0_IDX
},
.clear_sig = PCNT_RST_IN0_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN0_IDX
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_IN1_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_IN1_IDX
}
.clear_sig_id_matrix = PCNT_RST_IN0_IDX
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN1_IDX,
},
.clear_sig = PCNT_RST_IN1_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN1_IDX
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_IN2_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_IN2_IDX
}
.clear_sig_id_matrix = PCNT_RST_IN1_IDX
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN2_IDX,
},
.clear_sig = PCNT_RST_IN2_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN2_IDX
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_IN3_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_IN3_IDX
}
.clear_sig_id_matrix = PCNT_RST_IN2_IDX
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN3_IDX,
},
.clear_sig = PCNT_RST_IN3_IDX
}
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN3_IDX
}
},
.clear_sig_id_matrix = PCNT_RST_IN3_IDX
}
}
}

View File

@@ -783,22 +783,6 @@ config SOC_MPU_REGION_WO_SUPPORTED
bool
default n
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 4
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
bool
default y

View File

@@ -140,6 +140,7 @@ typedef enum {
SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL_D2 or RC_FAST by configuring soc_rtc_fast_clk_src_t */
SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, RC32K, or OSC_SLOW by configuring soc_rtc_slow_clk_src_t */
// For digital domain: peripherals, WIFI, BLE
SOC_MOD_CLK_APB, /*!< APB_CLK is highly dependent on the CPU_CLK source */
SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from PLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */
SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from PLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */
SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from PLL (clock gating + fixed divider of 2), it has a fixed frequency of 240MHz */
@@ -215,6 +216,21 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< RMT source clock default choice is PLL_F80M */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
} soc_periph_pcnt_clk_src_t;
//////////////////////////////////////////////////Temp Sensor///////////////////////////////////////////////////////////
/**

View File

@@ -315,10 +315,6 @@
#define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS 1U
#define SOC_PCNT_UNITS_PER_GROUP 4
#define SOC_PCNT_CHANNELS_PER_UNIT 2
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
/*--------------------------- RMT CAPS ---------------------------------------*/

View File

@@ -24,6 +24,12 @@
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 4 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -8,58 +8,56 @@
#include "soc/gpio_sig_map.h"
#include "soc/pcnt_reg.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.irq = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_IN0_IDX
}
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN0_IDX
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_IN1_IDX
}
}
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN1_IDX
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_IN2_IDX
}
}
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN2_IDX
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_IN3_IDX
}
}
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN3_IDX
}
}
}

View File

@@ -775,22 +775,6 @@ config SOC_MPU_REGION_WO_SUPPORTED
bool
default n
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 4
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
bool
default y

View File

@@ -152,6 +152,7 @@ typedef enum {
SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL_D2, RC_FAST, or LP_PLL by configuring soc_rtc_fast_clk_src_t */
SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, OSC_SLOW, or RC32K by configuring soc_rtc_slow_clk_src_t */
// For digital domain: peripherals, WIFI, BLE
SOC_MOD_CLK_APB, /*!< APB_CLK is highly dependent on the CPU_CLK source */
SOC_MOD_CLK_PLL_F48M, /*!< PLL_F48M_CLK is derived from PLL (clock gating + fixed divider of 2), it has a fixed frequency of 48MHz */
SOC_MOD_CLK_PLL_F64M, /*!< PLL_F64M_CLK is derived from FLASH_PLL (clock gating), it has a fixed frequency of 64MHz */
SOC_MOD_CLK_PLL_F96M, /*!< PLL_F96M_CLK is derived from PLL (clock gating), it has a fixed frequency of 96MHz */
@@ -222,6 +223,21 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_XTAL, /*!< RMT source clock default choice is XTAL */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
} soc_periph_pcnt_clk_src_t;
//////////////////////////////////////////////////Temp Sensor///////////////////////////////////////////////////////////
/**

View File

@@ -328,10 +328,6 @@
#define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS 1U
#define SOC_PCNT_UNITS_PER_GROUP 4
#define SOC_PCNT_CHANNELS_PER_UNIT 2
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
#define SOC_PCNT_SUPPORT_STEP_NOTIFY 1 /*!< Only avliable in chip version above 1.2*/

View File

@@ -24,6 +24,12 @@
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 4 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -8,58 +8,56 @@
#include "soc/gpio_sig_map.h"
#include "soc/pcnt_reg.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.irq = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_IN0_IDX
}
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN0_IDX
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_IN1_IDX
}
}
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN1_IDX
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_IN2_IDX
}
}
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN2_IDX
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_IN3_IDX
}
}
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN3_IDX
}
}
}

View File

@@ -475,22 +475,6 @@ config SOC_LEDC_CHANNEL_NUM
int
default 6
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 4
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
bool
default y

View File

@@ -133,6 +133,7 @@ typedef enum {
SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL_D2, RC_FAST, or LP_PLL by configuring soc_rtc_fast_clk_src_t */
SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, OSC_SLOW, or RC32K by configuring soc_rtc_slow_clk_src_t */
// For digital domain: peripherals, BLE
SOC_MOD_CLK_APB, /*!< APB_CLK is highly dependent on the CPU_CLK source */
SOC_MOD_CLK_PLL_F48M, /*!< PLL_F48M_CLK is derived from PLL (clock gating + fixed divider of 2), it has a fixed frequency of 48MHz */
// SOC_MOD_CLK_XTAL_X2_F64M, /*!< XTAL_X2_F64M_CLK is derived from XTAL_X2 (clock gating), it has a fixed frequency of 64MHz */
SOC_MOD_CLK_PLL_F96M, /*!< PLL_F96M_CLK is derived from PLL (clock gating), it has a fixed frequency of 96MHz */
@@ -211,6 +212,21 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_XTAL, /*!< RMT source clock default choice is XTAL */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
} soc_periph_pcnt_clk_src_t;
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
/**

View File

@@ -304,10 +304,6 @@
// #define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS 1U
#define SOC_PCNT_UNITS_PER_GROUP 4
#define SOC_PCNT_CHANNELS_PER_UNIT 2
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
#define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1
#define SOC_PCNT_SUPPORT_STEP_NOTIFY 1

View File

@@ -24,6 +24,12 @@
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 4 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -8,64 +8,62 @@
#include "soc/gpio_sig_map.h"
#include "soc/pcnt_reg.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.irq = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_IN0_IDX
}
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN0_IDX
},
.clear_sig = PCNT_RST_IN0_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN0_IDX
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_IN1_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_IN1_IDX
}
.clear_sig_id_matrix = PCNT_RST_IN0_IDX
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN1_IDX,
},
.clear_sig = PCNT_RST_IN1_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN1_IDX
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_IN2_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_IN2_IDX
}
.clear_sig_id_matrix = PCNT_RST_IN1_IDX
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN2_IDX,
},
.clear_sig = PCNT_RST_IN2_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN2_IDX
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_IN3_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_IN3_IDX
}
.clear_sig_id_matrix = PCNT_RST_IN2_IDX
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN3_IDX,
},
.clear_sig = PCNT_RST_IN3_IDX
}
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN3_IDX
}
},
.clear_sig_id_matrix = PCNT_RST_IN3_IDX
}
}
}

View File

@@ -19,6 +19,10 @@ config SOC_GPTIMER_SUPPORTED
bool
default y
config SOC_PCNT_SUPPORTED
bool
default y
config SOC_TWAI_SUPPORTED
bool
default y
@@ -523,6 +527,18 @@ config SOC_MMU_DI_VADDR_SHARED
bool
default y
config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
bool
default y
config SOC_PCNT_SUPPORT_CLEAR_SIGNAL
bool
default y
config SOC_PCNT_SUPPORT_STEP_NOTIFY
bool
default y
config SOC_RMT_GROUPS
int
default 1

View File

@@ -214,6 +214,23 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_XTAL, /*!< RMT source clock default choice is XTAL */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
PCNT_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
// PCNT_CLK_SRC_XTAL_X2_F32M = SOC_MOD_CLK_XTAL_X2_F32M, /*!< Select XTAL_X2_F32M as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default choice */
} soc_periph_pcnt_clk_src_t;
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
/**

View File

@@ -38,7 +38,7 @@
#define SOC_GDMA_SUPPORTED 1
#define SOC_AHB_GDMA_SUPPORTED 1
#define SOC_GPTIMER_SUPPORTED 1
// #define SOC_PCNT_SUPPORTED 1 // TODO: [ESP32H4] IDF-12338
#define SOC_PCNT_SUPPORTED 1
// #define SOC_MCPWM_SUPPORTED 1 // TODO: [ESP32H4] IDF-12380
#define SOC_TWAI_SUPPORTED 1
#define SOC_ETM_SUPPORTED 1
@@ -315,11 +315,9 @@
// #define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
// #define SOC_PCNT_GROUPS 1U
// #define SOC_PCNT_UNITS_PER_GROUP 4
// #define SOC_PCNT_CHANNELS_PER_UNIT 2
// #define SOC_PCNT_THRES_POINT_PER_UNIT 2
// #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
#define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1
#define SOC_PCNT_SUPPORT_STEP_NOTIFY 1
/*--------------------------- RMT CAPS ---------------------------------------*/
#define SOC_RMT_GROUPS 1U /*!< One RMT group */

View File

@@ -24,6 +24,12 @@
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 4 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 4 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/pcnt_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/pcnt_reg.h"
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN0_IDX
}
},
.clear_sig_id_matrix = PCNT_RST_IN0_IDX
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN1_IDX,
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN1_IDX
}
},
.clear_sig_id_matrix = PCNT_RST_IN1_IDX
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN2_IDX,
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN2_IDX
}
},
.clear_sig_id_matrix = PCNT_RST_IN2_IDX
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN3_IDX,
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN3_IDX
}
},
.clear_sig_id_matrix = PCNT_RST_IN3_IDX
}
}
}
};

View File

@@ -148,73 +148,22 @@ typedef union {
uint32_t val;
} pcnt_un_conf2_reg_t;
/** Type of u0_conf3 register
* Configuration register for unit $n's step value.
/** Type of un_conf3 register
* Configuration register for unit n's step value.
*/
typedef union {
struct {
/** cnt_h_step_u0 : R/W; bitpos: [15:0]; default: 0;
* Configures the forward rotation step value for unit 0.
/** cnt_h_step_un : R/W; bitpos: [15:0]; default: 0;
* Configures the forward rotation step value for unit n.
*/
uint32_t cnt_h_step_u0:16;
/** cnt_l_step_u0 : R/W; bitpos: [31:16]; default: 0;
* Configures the reverse rotation step value for unit 0.
uint32_t cnt_h_step_un:16;
/** cnt_l_step_un : R/W; bitpos: [31:16]; default: 0;
* Configures the reverse rotation step value for unit n.
*/
uint32_t cnt_l_step_u0:16;
uint32_t cnt_l_step_un:16;
};
uint32_t val;
} pcnt_u0_conf3_reg_t;
/** Type of u1_conf3 register
* Configuration register for unit $n's step value.
*/
typedef union {
struct {
/** cnt_h_step_u1 : R/W; bitpos: [15:0]; default: 0;
* Configures the forward rotation step value for unit 1.
*/
uint32_t cnt_h_step_u1:16;
/** cnt_l_step_u1 : R/W; bitpos: [31:16]; default: 0;
* Configures the reverse rotation step value for unit 1.
*/
uint32_t cnt_l_step_u1:16;
};
uint32_t val;
} pcnt_u1_conf3_reg_t;
/** Type of u2_conf3 register
* Configuration register for unit $n's step value.
*/
typedef union {
struct {
/** cnt_h_step_u2 : R/W; bitpos: [15:0]; default: 0;
* Configures the forward rotation step value for unit 2.
*/
uint32_t cnt_h_step_u2:16;
/** cnt_l_step_u2 : R/W; bitpos: [31:16]; default: 0;
* Configures the reverse rotation step value for unit 2.
*/
uint32_t cnt_l_step_u2:16;
};
uint32_t val;
} pcnt_u2_conf3_reg_t;
/** Type of u3_conf3 register
* Configuration register for unit $n's step value.
*/
typedef union {
struct {
/** cnt_h_step_u3 : R/W; bitpos: [15:0]; default: 0;
* Configures the forward rotation step value for unit 3.
*/
uint32_t cnt_h_step_u3:16;
/** cnt_l_step_u3 : R/W; bitpos: [31:16]; default: 0;
* Configures the reverse rotation step value for unit 3.
*/
uint32_t cnt_l_step_u3:16;
};
uint32_t val;
} pcnt_u3_conf3_reg_t;
} pcnt_un_conf3_reg_t;
/** Type of ctrl register
* Control register for all counters
@@ -484,29 +433,19 @@ typedef union {
} pcnt_date_reg_t;
typedef struct {
volatile pcnt_un_conf0_reg_t u0_conf0;
volatile pcnt_un_conf1_reg_t u0_conf1;
volatile pcnt_un_conf2_reg_t u0_conf2;
volatile pcnt_u0_conf3_reg_t u0_conf3;
volatile pcnt_un_conf0_reg_t u1_conf0;
volatile pcnt_un_conf1_reg_t u1_conf1;
volatile pcnt_un_conf2_reg_t u1_conf2;
volatile pcnt_u1_conf3_reg_t u1_conf3;
volatile pcnt_un_conf0_reg_t u2_conf0;
volatile pcnt_un_conf1_reg_t u2_conf1;
volatile pcnt_un_conf2_reg_t u2_conf2;
volatile pcnt_u2_conf3_reg_t u2_conf3;
volatile pcnt_un_conf0_reg_t u3_conf0;
volatile pcnt_un_conf1_reg_t u3_conf1;
volatile pcnt_un_conf2_reg_t u3_conf2;
volatile pcnt_u3_conf3_reg_t u3_conf3;
volatile pcnt_un_cnt_reg_t un_cnt[4];
typedef struct pcnt_dev_t {
volatile struct {
pcnt_un_conf0_reg_t conf0;
pcnt_un_conf1_reg_t conf1;
pcnt_un_conf2_reg_t conf2;
pcnt_un_conf3_reg_t conf3;
} conf_unit[4];
volatile pcnt_un_cnt_reg_t cnt_unit[4];
volatile pcnt_int_raw_reg_t int_raw;
volatile pcnt_int_st_reg_t int_st;
volatile pcnt_int_ena_reg_t int_ena;
volatile pcnt_int_clr_reg_t int_clr;
volatile pcnt_un_status_reg_t un_status[4];
volatile pcnt_un_status_reg_t status_unit[4];
volatile pcnt_ctrl_reg_t ctrl;
uint32_t reserved_074[34];
volatile pcnt_date_reg_t date;

View File

@@ -1151,22 +1151,6 @@ config SOC_MPU_REGION_WO_SUPPORTED
bool
default n
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 4
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
bool
default y

View File

@@ -160,6 +160,7 @@ typedef enum {
SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL, RC_FAST, or LP_PLL by configuring soc_rtc_fast_clk_src_t */
SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or RC32K by configuring soc_rtc_slow_clk_src_t */
// For digital domain: peripherals
SOC_MOD_CLK_APB, /*!< APB_CLK is highly dependent on the CPU_CLK source */
SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + default divider 24), its default frequency is 20MHz */
SOC_MOD_CLK_PLL_F25M, /*!< PLL_F25M_CLK is derived from MPLL (clock gating + configurable divider), it will have a frequency of 25MHz */
SOC_MOD_CLK_PLL_F50M, /*!< PLL_F50M_CLK is derived from MPLL (clock gating + configurable divider 10), it will have a frequency of 50MHz */
@@ -256,6 +257,21 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< RMT source clock default choice is PLL_F80M */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
} soc_periph_pcnt_clk_src_t;
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
/**

View File

@@ -420,10 +420,6 @@
#define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS 1U
#define SOC_PCNT_UNITS_PER_GROUP 4
#define SOC_PCNT_CHANNELS_PER_UNIT 2
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
#define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1 /*!< Support clear signal input */

View File

@@ -24,6 +24,12 @@
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 8 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 4 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit
/*--------------------------- ETM (Event Task Matrix) ----------------------------*/
#define _SOC_CAPS_ETM_INST_NUM 1 // Number of ETM instances
#define _SOC_CAPS_ETM_CHANS_PER_INST 50 // Number of channels in each ETM instance

View File

@@ -8,64 +8,62 @@
#include "soc/gpio_sig_map.h"
#include "soc/pcnt_reg.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.irq = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_PAD_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_PAD_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_PAD_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_PAD_IN0_IDX
}
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_PAD_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_PAD_IN0_IDX
},
.clear_sig = PCNT_RST_PAD_IN0_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_PAD_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_PAD_IN0_IDX
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_PAD_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_PAD_IN1_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_PAD_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_PAD_IN1_IDX
}
.clear_sig_id_matrix = PCNT_RST_PAD_IN0_IDX
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_PAD_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_PAD_IN1_IDX,
},
.clear_sig = PCNT_RST_PAD_IN1_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_PAD_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_PAD_IN1_IDX
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_PAD_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_PAD_IN2_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_PAD_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_PAD_IN2_IDX
}
.clear_sig_id_matrix = PCNT_RST_PAD_IN1_IDX
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_PAD_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_PAD_IN2_IDX,
},
.clear_sig = PCNT_RST_PAD_IN2_IDX
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_PAD_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_PAD_IN2_IDX
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_PAD_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_PAD_IN3_IDX,
},
[1] = {
.control_sig = PCNT_CTRL_CH1_PAD_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_PAD_IN3_IDX
}
.clear_sig_id_matrix = PCNT_RST_PAD_IN2_IDX
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_PAD_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_PAD_IN3_IDX,
},
.clear_sig = PCNT_RST_PAD_IN3_IDX
}
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_PAD_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_PAD_IN3_IDX
}
},
.clear_sig_id_matrix = PCNT_RST_PAD_IN3_IDX
}
}
}

View File

@@ -583,22 +583,6 @@ config SOC_MPU_REGION_WO_SUPPORTED
bool
default n
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 4
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_RMT_GROUPS
int
default 1

View File

@@ -214,6 +214,21 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_APB, /*!< RMT source clock default choice is APB */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
} soc_periph_pcnt_clk_src_t;
//////////////////////////////////////////////////Temp Sensor///////////////////////////////////////////////////////////
/**

View File

@@ -257,12 +257,6 @@
#define SOC_MPU_REGION_RO_SUPPORTED 0
#define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS (1U)
#define SOC_PCNT_UNITS_PER_GROUP (4)
#define SOC_PCNT_CHANNELS_PER_UNIT (2)
#define SOC_PCNT_THRES_POINT_PER_UNIT (2)
/*-------------------------- RMT CAPS ----------------------------------------*/
#define SOC_RMT_GROUPS 1U /*!< One RMT group */
#define SOC_RMT_TX_CANDIDATES_PER_GROUP 4 /*!< Number of channels that capable of Transmit in each group */

View File

@@ -23,3 +23,9 @@
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 8 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 4 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,58 +7,56 @@
#include "soc/pcnt_periph.h"
#include "soc/gpio_sig_map.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.irq = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_IN0_IDX
}
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN0_IDX
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_IN1_IDX
}
}
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN1_IDX
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_IN2_IDX
}
}
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN2_IDX
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_IN3_IDX
}
}
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN3_IDX
}
}
}

View File

@@ -703,22 +703,6 @@ config SOC_MPU_REGION_WO_SUPPORTED
bool
default n
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 4
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_RMT_GROUPS
int
default 1

View File

@@ -233,6 +233,21 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_APB, /*!< RMT source clock default choice is APB */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////PCNT//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PCNT
*/
#define SOC_PCNT_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of PCNT clock source
*/
typedef enum {
PCNT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
PCNT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
} soc_periph_pcnt_clk_src_t;
//////////////////////////////////////////////////Temp Sensor///////////////////////////////////////////////////////////
/**

View File

@@ -280,12 +280,6 @@
#define SOC_MPU_REGION_RO_SUPPORTED 0
#define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS (1U)
#define SOC_PCNT_UNITS_PER_GROUP (4)
#define SOC_PCNT_CHANNELS_PER_UNIT (2)
#define SOC_PCNT_THRES_POINT_PER_UNIT (2)
/*-------------------------- RMT CAPS ----------------------------------------*/
#define SOC_RMT_GROUPS 1U /*!< One RMT group */
#define SOC_RMT_TX_CANDIDATES_PER_GROUP 4 /*!< Number of channels that capable of Transmit in each group */

View File

@@ -23,3 +23,9 @@
/*--------------------------- SDM (Sigma-Delta Modulator) ------------------------*/
#define _SOC_CAPS_SDM_INST_NUM 1 // Number of SDM instances
#define _SOC_CAPS_SDM_CHANS_PER_INST 8 // Number of channels in each SDM instance
/*--------------------------- PCNT (Pulse Counter) ------------------------*/
#define _SOC_CAPS_PCNT_INST_NUM 1 // Number of PCNT instances
#define _SOC_CAPS_PCNT_UNITS_PER_INST 4 // Number of units in each PCNT instance
#define _SOC_CAPS_PCNT_CHANS_PER_UNIT 2 // Number of channels in each PCNT unit
#define _SOC_CAPS_PCNT_THRES_POINT_PER_UNIT 2 // Number of threshold points in each PCNT unit

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,58 +7,56 @@
#include "soc/pcnt_periph.h"
#include "soc/gpio_sig_map.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.irq = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_IN0_IDX
}
const soc_pcnt_signal_desc_t soc_pcnt_signals[1] = {
[0] = {
.irq_id = ETS_PCNT_INTR_SOURCE,
.module_name = "pcnt0",
.units = {
[0] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN0_IDX
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_IN1_IDX
}
}
},
[1] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN1_IDX
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_IN2_IDX
}
}
},
[2] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN2_IDX
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_IN3_IDX
}
}
},
[3] = {
.channels = {
[0] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.ctl_sig_id_matrix = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig_id_matrix = PCNT_SIG_CH1_IN3_IDX
}
}
}

View File

@@ -7,32 +7,34 @@
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#include "soc/periph_defs.h"
#include <stddef.h>
#include "soc/soc_caps_full.h"
#include "soc/interrupts.h"
// helper macros to access module attributes
#define SOC_PCNT_ATTR(_attr) SOC_MODULE_ATTR(PCNT, _attr)
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_PCNT_SUPPORTED
#if SOC_HAS(PCNT)
typedef struct {
const char *module_name; // module name
struct {
const char *module_name;
struct {
struct {
const uint32_t pulse_sig;
const uint32_t control_sig;
} channels[SOC_PCNT_CHANNELS_PER_UNIT];
const uint32_t clear_sig;
} units[SOC_PCNT_UNITS_PER_GROUP];
const uint32_t irq;
} groups[SOC_PCNT_GROUPS];
} pcnt_signal_conn_t;
const int pulse_sig_id_matrix; // pulse signal ID in the GPIO matrix
const int ctl_sig_id_matrix; // control signal ID in the GPIO matrix
} channels[SOC_PCNT_ATTR(CHANS_PER_UNIT)];
const int clear_sig_id_matrix; // clear signal ID in the GPIO matrix
} units[SOC_PCNT_ATTR(UNITS_PER_INST)];
const int irq_id; // interrupt source ID
} soc_pcnt_signal_desc_t;
extern const pcnt_signal_conn_t pcnt_periph_signals;
extern const soc_pcnt_signal_desc_t soc_pcnt_signals[SOC_PCNT_ATTR(INST_NUM)];
#endif // SOC_PCNT_SUPPORTED
#endif // SOC_HAS(PCNT)
#ifdef __cplusplus
}

View File

@@ -179,7 +179,6 @@ api-reference/peripherals/lcd/dsi_lcd.rst
api-reference/peripherals/lcd/spi_lcd.rst
api-reference/peripherals/lcd/rgb_lcd.rst
api-reference/peripherals/lcd/parl_lcd.rst
api-reference/peripherals/pcnt.rst
api-reference/peripherals/ppa.rst
api-reference/peripherals/ldo_regulator.rst
api-reference/peripherals/ledc.rst

View File

@@ -60,7 +60,7 @@ To install a PCNT unit, there is a configuration structure that needs to be give
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.
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. The total number of available PCNT units is recorded by :c:macro:`SOC_PCNT_UNITS_PER_GROUP` for reference.
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.
If a previously created PCNT unit is no longer needed, it is recommended to recycle the resource by calling :cpp:func:`pcnt_del_unit`. Which in return allows the underlying unit hardware to be used for other purposes. Before deleting a PCNT unit, one should ensure the following prerequisites:
@@ -88,7 +88,7 @@ To install a PCNT channel, you must initialize a :cpp:type:`pcnt_chan_config_t`
- :cpp:member:`pcnt_chan_config_t::virt_edge_io_level` and :cpp:member:`pcnt_chan_config_t::virt_level_io_level` specify the virtual IO level for **edge** and **level** input signal, to ensure a deterministic state for such control signal. Please note, they are only valid when either :cpp:member:`pcnt_chan_config_t::edge_gpio_num` or :cpp:member:`pcnt_chan_config_t::level_gpio_num` is assigned to ``-1``.
- :cpp:member:`pcnt_chan_config_t::invert_edge_input` and :cpp:member:`pcnt_chan_config_t::invert_level_input` are used to decide whether to invert the input signals before they going into PCNT hardware. The invert is done by GPIO matrix instead of PCNT hardware.
Channel allocating and initialization is done by calling a function :cpp:func:`pcnt_new_channel` with the above :cpp:type:`pcnt_chan_config_t` as an input parameter plus a PCNT unit handle returned from :cpp:func:`pcnt_new_unit`. This function will return a PCNT channel handle if it runs correctly. Specifically, when there are no more free PCNT channel within the unit (i.e., channel resources have been used up), then this function will return :c:macro:`ESP_ERR_NOT_FOUND` error. The total number of available PCNT channels within the unit is recorded by :c:macro:`SOC_PCNT_CHANNELS_PER_UNIT` for reference. Note that, when install a PCNT channel for a specific unit, one should ensure the unit is in the init state, otherwise this function will return :c:macro:`ESP_ERR_INVALID_STATE` error.
Channel allocating and initialization is done by calling a function :cpp:func:`pcnt_new_channel` with the above :cpp:type:`pcnt_chan_config_t` as an input parameter plus a PCNT unit handle returned from :cpp:func:`pcnt_new_unit`. This function will return a PCNT channel handle if it runs correctly. Specifically, when there are no more free PCNT channel within the unit (i.e., channel resources have been used up), then this function will return :c:macro:`ESP_ERR_NOT_FOUND` error. Note that, when install a PCNT channel for a specific unit, one should ensure the unit is in the init state, otherwise this function will return :c:macro:`ESP_ERR_INVALID_STATE` error.
If a previously created PCNT channel is no longer needed, it is recommended to recycle the resources by calling :cpp:func:`pcnt_del_channel`. Which in return allows the underlying channel hardware to be used for other purposes.

View File

@@ -60,7 +60,7 @@ PCNT 单元和通道分别用 :cpp:type:`pcnt_unit_handle_t` 与 :cpp:type:`pcnt
由于所有 PCNT 单元共享一个中断源,安装多个 PCNT 单元时请确保每个单元的中断优先级 :cpp:member:`pcnt_unit_config_t::intr_priority` 一致。
调用函数 :cpp:func:`pcnt_new_unit` 并将 :cpp:type:`pcnt_unit_config_t` 作为其输入值,可对 PCNT 单元进行分配和初始化。该函数正常运行时,会返回一个 PCNT 单元句柄。没有可用的 PCNT 单元时(即 PCNT 单元全部被占用),该函数会返回错误 :c:macro:`ESP_ERR_NOT_FOUND`可用的 PCNT 单元总数记录在 :c:macro:`SOC_PCNT_UNITS_PER_GROUP` 中,以供参考。
调用函数 :cpp:func:`pcnt_new_unit` 并将 :cpp:type:`pcnt_unit_config_t` 作为其输入值,可对 PCNT 单元进行分配和初始化。该函数正常运行时,会返回一个 PCNT 单元句柄。没有可用的 PCNT 单元时(即 PCNT 单元全部被占用),该函数会返回错误 :c:macro:`ESP_ERR_NOT_FOUND`
如果不再需要之前创建的某个 PCNT 单元,建议通过调用 :cpp:func:`pcnt_del_unit` 来回收该单元,从而该单元可用于其他用途。删除某个 PCNT 单元之前,需要满足以下条件:
@@ -88,7 +88,7 @@ PCNT 单元和通道分别用 :cpp:type:`pcnt_unit_handle_t` 与 :cpp:type:`pcnt
- :cpp:member:`pcnt_chan_config_t::virt_edge_io_level`:cpp:member:`pcnt_chan_config_t::virt_level_io_level` 用于指定 **边沿** 信号和 **电平** 信号的虚拟 IO 电平,以保证这些控制信号处于确定状态。请注意,只有在 :cpp:member:`pcnt_chan_config_t::edge_gpio_num`:cpp:member:`pcnt_chan_config_t::level_gpio_num` 设置为 `-1` 时,这两个参数才有效。
- :cpp:member:`pcnt_chan_config_t::invert_edge_input`:cpp:member:`pcnt_chan_config_t::invert_level_input` 用于确定信号在输入 PCNT 之前是否需要被翻转,信号翻转由 GPIO 矩阵(不是 PCNT 单元)执行。
调用函数 :cpp:func:`pcnt_new_channel`,将 :cpp:type:`pcnt_chan_config_t` 作为输入值并调用 :cpp:func:`pcnt_new_unit` 返回的 PCNT 单元句柄,可对 PCNT 通道进行分配和初始化。如果该函数正常运行,会返回一个 PCNT 通道句柄。如果没有可用的 PCNT 通道PCNT 通道资源全部被占用),该函数会返回错误 :c:macro:`ESP_ERR_NOT_FOUND`可用的 PCNT 通道总数记录在 :c:macro:`SOC_PCNT_CHANNELS_PER_UNIT`,以供参考。注意,为某个单元安装 PCNT 通道时,应确保该单元处于初始状态,否则函数 :cpp:func:`pcnt_new_channel` 会返回错误 :c:macro:`ESP_ERR_INVALID_STATE`
调用函数 :cpp:func:`pcnt_new_channel`,将 :cpp:type:`pcnt_chan_config_t` 作为输入值并调用 :cpp:func:`pcnt_new_unit` 返回的 PCNT 单元句柄,可对 PCNT 通道进行分配和初始化。如果该函数正常运行,会返回一个 PCNT 通道句柄。如果没有可用的 PCNT 通道PCNT 通道资源全部被占用),该函数会返回错误 :c:macro:`ESP_ERR_NOT_FOUND`。注意,为某个单元安装 PCNT 通道时,应确保该单元处于初始状态,否则函数 :cpp:func:`pcnt_new_channel` 会返回错误 :c:macro:`ESP_ERR_INVALID_STATE`
如果不再需要之前创建的某个 PCNT 通道,建议通过调用 :cpp:func:`pcnt_del_channel` 回收该通道,从而该通道可用于其他用途。

View File

@@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
# Rotary Encoder Example