bugfix:rotary encoder example isr service install

Fix the issue mentioned when using two or more encoders. Modify PCNT_CTRL_GND_IO
to avoid the affect of USB JTAG(origin pin 19 is used for USB D-). Update esp32c3.
peripherals.ld and docs for esp32s3.

Closes https://github.com/espressif/esp-idf/issues/6889
This commit is contained in:
bizhuangyang 2021-06-23 15:42:35 +08:00
parent bf48a789ac
commit 1829783886
4 changed files with 23 additions and 10 deletions

View File

@ -34,7 +34,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

View File

@ -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 );

View File

@ -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:

View File

@ -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);