diff --git a/components/driver/test/test_pcnt.c b/components/driver/test/test_pcnt.c index 28f9087fde..a7b33d2940 100644 --- a/components/driver/test/test_pcnt.c +++ b/components/driver/test/test_pcnt.c @@ -29,7 +29,7 @@ #define PULSE_IO 21 #define PCNT_INPUT_IO 4 #define PCNT_CTRL_VCC_IO 5 -#define PCNT_CTRL_GND_IO 19 +#define PCNT_CTRL_GND_IO 2 #define HIGHEST_LIMIT 10 #define LOWEST_LIMIT 0 #define MAX_THRESHOLD 5 diff --git a/components/esp32c3/ld/esp32c3.peripherals.ld b/components/esp32c3/ld/esp32c3.peripherals.ld index b23ca368ac..5446f28d9b 100644 --- a/components/esp32c3/ld/esp32c3.peripherals.ld +++ b/components/esp32c3/ld/esp32c3.peripherals.ld @@ -14,7 +14,6 @@ PROVIDE ( UHCI1 = 0x6000c000 ); PROVIDE ( HOST = 0x60015000 ); PROVIDE ( RMT = 0x60016000 ); PROVIDE ( RMTMEM = 0x60016400 ); -PROVIDE ( PCNT = 0x60017000 ); PROVIDE ( SLC = 0x60018000 ); PROVIDE ( LEDC = 0x60019000 ); PROVIDE ( TIMERG0 = 0x6001F000 ); diff --git a/docs/en/api-reference/peripherals/pcnt.rst b/docs/en/api-reference/peripherals/pcnt.rst index 723c5e268e..22433e8358 100644 --- a/docs/en/api-reference/peripherals/pcnt.rst +++ b/docs/en/api-reference/peripherals/pcnt.rst @@ -1,6 +1,9 @@ Pulse Counter ============= +{IDF_TARGET_PCNT_UNIT_NUM:default="8", esp32s2="4"} +{IDF_TARGET_PCNT_MAX_UNIT_NUM:default="7", esp32s2="3"} + Introduction ------------ @@ -22,13 +25,8 @@ Description of functionality of this API has been broken down into four sections Configuration ------------- -.. only:: esp32 - The PCNT module has eight independent counting "units" numbered from 0 to 7. In the API they are referred to using :cpp:type:`pcnt_unit_t`. Each unit has two independent channels numbered as 0 and 1 and specified with :cpp:type:`pcnt_channel_t`. - -.. only:: esp32s2 - - The PCNT module has four independent counting "units" numbered from 0 to 3. In the API they are referred to using :cpp:type:`pcnt_unit_t`. Each unit has two independent channels numbered as 0 and 1 and specified with :cpp:type:`pcnt_channel_t`. +The PCNT module has {IDF_TARGET_PCNT_UNIT_NUM} independent counting "units" numbered from 0 to {IDF_TARGET_PCNT_MAX_UNIT_NUM}. In the API they are referred to using :cpp:type:`pcnt_unit_t`. Each unit has two independent channels numbered as 0 and 1 and specified with :cpp:type:`pcnt_channel_t`. The configuration is provided separately per unit's channel using :cpp:type:`pcnt_config_t` and covers: diff --git a/examples/peripherals/pcnt/rotary_encoder/components/rotary_encoder/src/rotary_encoder_pcnt_ec11.c b/examples/peripherals/pcnt/rotary_encoder/components/rotary_encoder/src/rotary_encoder_pcnt_ec11.c index afaec8e35f..d771ceafd3 100644 --- a/examples/peripherals/pcnt/rotary_encoder/components/rotary_encoder/src/rotary_encoder_pcnt_ec11.c +++ b/examples/peripherals/pcnt/rotary_encoder/components/rotary_encoder/src/rotary_encoder_pcnt_ec11.c @@ -17,6 +17,7 @@ #include "esp_compiler.h" #include "esp_log.h" #include "driver/pcnt.h" +#include "sys/lock.h" #include "hal/pcnt_hal.h" #include "rotary_encoder.h" @@ -34,6 +35,13 @@ static const char *TAG = "rotary_encoder"; #define EC11_PCNT_DEFAULT_HIGH_LIMIT (100) #define EC11_PCNT_DEFAULT_LOW_LIMIT (-100) +// A flag to identify if pcnt isr service has been installed. +static bool is_pcnt_isr_service_installed = false; +// A lock to avoid pcnt isr service being installed twice in multiple threads. +static _lock_t isr_service_install_lock; +#define LOCK_ACQUIRE() _lock_acquire(&isr_service_install_lock) +#define LOCK_RELEASE() _lock_release(&isr_service_install_lock) + typedef struct { int accumu_count; rotary_encoder_t parent; @@ -141,8 +149,16 @@ esp_err_t rotary_encoder_new_ec11(const rotary_encoder_config_t *config, rotary_ pcnt_counter_pause(ec11->pcnt_unit); pcnt_counter_clear(ec11->pcnt_unit); - // register interrupt handler - ROTARY_CHECK(pcnt_isr_service_install(0) == ESP_OK, "install isr service failed", err, ESP_FAIL); + + // register interrupt handler in a thread-safe way + LOCK_ACQUIRE(); + if (!is_pcnt_isr_service_installed) { + ROTARY_CHECK(pcnt_isr_service_install(0) == ESP_OK, "install isr service failed", err, ESP_FAIL); + // make sure pcnt isr service won't be installed more than one time + is_pcnt_isr_service_installed = true; + } + LOCK_RELEASE(); + pcnt_isr_handler_add(ec11->pcnt_unit, ec11_pcnt_overflow_handler, ec11); pcnt_event_enable(ec11->pcnt_unit, PCNT_EVT_H_LIM);