From 15b498fd6bf6548bfd20a03a584f11f598ba3b42 Mon Sep 17 00:00:00 2001 From: Alexey Zholtikov Date: Sun, 4 Oct 2026 22:24:57 +0300 Subject: [PATCH] perf: updated error checks --- README.md | 9 ---- include/zh_inclinometer.h | 18 ++++--- zh_inclinometer.c | 109 +++++++++++++++++++++----------------- 3 files changed, 70 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 8348bda..20b98dc 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,6 @@ 6. PCNT glitch filter for noise rejection (1000ns). 7. Multiple inclinometer instances support. -## Note - -Enable the following settings in menuconfig: - -```text -PCNT_CTRL_FUNC_IN_IRAM -PCNT_ISR_IRAM_SAF -``` - ## Using In an existing project, run the following command to install the components: diff --git a/include/zh_inclinometer.h b/include/zh_inclinometer.h index 2c35f3e..7da81a9 100644 --- a/include/zh_inclinometer.h +++ b/include/zh_inclinometer.h @@ -20,11 +20,14 @@ #pragma once +#include "stdbool.h" +#include "stdint.h" #include "esp_log.h" #include "driver/gpio.h" #include "driver/pulse_cnt.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp_heap_caps.h" #define ZH_INCLINOMETER_INIT_CONFIG_DEFAULT() \ { \ @@ -63,11 +66,11 @@ extern "C" */ typedef struct { - uint8_t a_gpio_number; /*!< Encoder A channel GPIO number */ - uint8_t b_gpio_number; /*!< Encoder B channel GPIO number */ - bool pullup; /*!< GPIO pull-up resistor enable (true) or disable (false) */ - bool rotation; /*!< Rotation direction: true - positive for CW, false - positive for CCW */ - uint16_t encoder_pulses; /*!< Number of encoder pulses per one full rotation */ + gpio_num_t a_gpio_number; /*!< Encoder A channel GPIO number */ + gpio_num_t b_gpio_number; /*!< Encoder B channel GPIO number */ + bool pullup; /*!< GPIO pull-up resistor enable (true) or disable (false) */ + bool rotation; /*!< Rotation direction: true - positive for CW, false - positive for CCW */ + uint16_t encoder_pulses; /*!< Number of encoder pulses per one full rotation */ } zh_inclinometer_init_config_t; /** @@ -78,7 +81,7 @@ extern "C" * and starts the pulse counter. * * @param[in] config Pointer to the inclinometer initialization configuration - * structure. Can point to a temporary variable (must not be NULL) + * structure (can point to a temporary variable, must not be NULL) * @param[out] handle Pointer to the unique inclinometer handle (must be NULL) * * @return ESP_OK on success @@ -96,14 +99,13 @@ extern "C" * PCNT unit, frees the inclinometer handle memory, and sets the handle to * NULL. * - * @param[in, out] handle Pointer to the unique inclinometer handle (must not be NULL) + * @param[in,out] handle Pointer to the unique inclinometer handle (must not be NULL) * * @note After deinitialization, the handle is invalidated and must not be * used. Call zh_inclinometer_init() again to reinitialize. * * @return ESP_OK on success * @return ESP_ERR_INVALID_ARG if handle or *handle is NULL - * @return ESP_FAIL if PCNT stop, disable, or deletion failed */ esp_err_t zh_inclinometer_deinit(zh_inclinometer_handle_t **handle); diff --git a/zh_inclinometer.c b/zh_inclinometer.c index 925a433..15a9f90 100644 --- a/zh_inclinometer.c +++ b/zh_inclinometer.c @@ -1,6 +1,6 @@ #include "zh_inclinometer.h" -#define TAG "zh_inclinometer" +static const char *TAG = "zh_inclinometer"; #define ZH_LOGI(msg, ...) ESP_LOGI(TAG, msg, ##__VA_ARGS__) #define ZH_LOGE(msg, err, ...) ESP_LOGE(TAG, "[%s:%d:%s] " msg, __FILE__, __LINE__, esp_err_to_name(err), ##__VA_ARGS__) @@ -13,6 +13,13 @@ return err; \ } +#define ZH_ERROR_CHECK_CONT(cond, cleanup, msg, ...) \ + if (!(cond)) \ + { \ + ZH_LOGE(msg, ESP_FAIL, ##__VA_ARGS__); \ + cleanup; \ + } + /** * @brief Internal structure holding the inclinometer instance state. * @@ -34,10 +41,10 @@ struct _zh_inclinometer_handle_t * * Checks that all required configuration parameters are within valid ranges. * - * @param config Pointer to the initialization configuration structure. + * @param config Pointer to the initialization configuration structure * * @return ESP_OK if the configuration is valid - * @return ESP_ERR_INVALID_ARG if encoder_pulses is zero or negative + * @return ESP_ERR_INVALID_ARG if encoder_pulses is zero or out of range */ static esp_err_t _zh_inclinometer_validate_config(const zh_inclinometer_init_config_t *config); @@ -65,7 +72,7 @@ esp_err_t zh_inclinometer_init(const zh_inclinometer_init_config_t *config, zh_i *handle = heap_caps_calloc(1, sizeof(zh_inclinometer_handle_t), MALLOC_CAP_8BIT); ZH_ERROR_CHECK(*handle != NULL, ESP_ERR_NO_MEM, NULL, "Inclinometer initialization failed. Failed to allocate inclinometer handle."); ZH_ERROR_CHECK(_zh_inclinometer_pcnt_init(config, *handle) == ESP_OK, ESP_FAIL, heap_caps_free(*handle); *handle = NULL, "Inclinometer initialization failed. PCNT initialization failed."); - (*handle)->degrees_per_pulse = 360.0 / config->encoder_pulses; + (*handle)->degrees_per_pulse = 360.0 / (4 * config->encoder_pulses); (*handle)->rotation = config->rotation; ZH_LOGI("Inclinometer initialization completed successfully."); return ESP_OK; @@ -75,11 +82,11 @@ esp_err_t zh_inclinometer_deinit(zh_inclinometer_handle_t **handle) { ZH_LOGI("Inclinometer deinitialization started."); ZH_ERROR_CHECK(handle != NULL && *handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Inclinometer deinitialization failed. Invalid argument."); - ZH_ERROR_CHECK(pcnt_unit_stop((*handle)->pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "Inclinometer deinitialization failed. PCNT unit stop fail."); - ZH_ERROR_CHECK(pcnt_unit_disable((*handle)->pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "Inclinometer deinitialization failed. PCNT unit disable fail."); - ZH_ERROR_CHECK(pcnt_del_channel((*handle)->pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "Inclinometer deinitialization failed. PCNT delete channel fail."); - ZH_ERROR_CHECK(pcnt_del_channel((*handle)->pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, NULL, "Inclinometer deinitialization failed. PCNT delete channel fail."); - ZH_ERROR_CHECK(pcnt_del_unit((*handle)->pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "Inclinometer deinitialization failed. PCNT delete unit fail."); + ZH_ERROR_CHECK_CONT(pcnt_unit_stop((*handle)->pcnt_unit_handle) == ESP_OK, NULL, "Inclinometer deinitialization failed. PCNT unit stop fail."); + ZH_ERROR_CHECK_CONT(pcnt_unit_disable((*handle)->pcnt_unit_handle) == ESP_OK, NULL, "Inclinometer deinitialization failed. PCNT unit disable fail."); + ZH_ERROR_CHECK_CONT(pcnt_del_channel((*handle)->pcnt_channel_a_handle) == ESP_OK, NULL, "Inclinometer deinitialization failed. PCNT delete channel fail."); + ZH_ERROR_CHECK_CONT(pcnt_del_channel((*handle)->pcnt_channel_b_handle) == ESP_OK, NULL, "Inclinometer deinitialization failed. PCNT delete channel fail."); + ZH_ERROR_CHECK_CONT(pcnt_del_unit((*handle)->pcnt_unit_handle) == ESP_OK, NULL, "Inclinometer deinitialization failed. PCNT delete unit fail."); heap_caps_free(*handle); *handle = NULL; ZH_LOGI("Inclinometer deinitialization completed successfully."); @@ -93,7 +100,8 @@ esp_err_t zh_inclinometer_get(zh_inclinometer_handle_t **handle, float *angle) int pcnt_count = 0; ZH_ERROR_CHECK(pcnt_unit_get_count((*handle)->pcnt_unit_handle, &pcnt_count) == ESP_OK, ESP_FAIL, NULL, "Inclinometer get position failed. PCNT unit get count fail."); float angle_temp = pcnt_count * (*handle)->degrees_per_pulse; - *angle = ((*handle)->rotation == true) ? angle_temp : ((angle_temp == 0) ? angle_temp : -angle_temp); + *angle = (*handle)->rotation == true ? angle_temp : -angle_temp; + *angle += 0.0f; ZH_LOGI("Inclinometer get position completed successfully."); return ESP_OK; } @@ -109,7 +117,7 @@ esp_err_t zh_inclinometer_reset(zh_inclinometer_handle_t **handle) static esp_err_t _zh_inclinometer_validate_config(const zh_inclinometer_init_config_t *config) { - ZH_ERROR_CHECK(config->encoder_pulses > 0, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder pulses."); + ZH_ERROR_CHECK(config->encoder_pulses > 0 && 4 * config->encoder_pulses <= 32767, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder pulses."); return ESP_OK; } @@ -117,9 +125,17 @@ static esp_err_t _zh_inclinometer_pcnt_init(const zh_inclinometer_init_config_t { ZH_ERROR_CHECK(config->a_gpio_number < GPIO_NUM_MAX && config->b_gpio_number < GPIO_NUM_MAX, ESP_ERR_INVALID_ARG, NULL, "Invalid GPIO number.") ZH_ERROR_CHECK(config->a_gpio_number != config->b_gpio_number, ESP_ERR_INVALID_ARG, NULL, "Encoder A and B GPIO is same.") + gpio_config_t io_config = { + .pin_bit_mask = (1ULL << config->a_gpio_number) | (1ULL << config->b_gpio_number), + .mode = GPIO_MODE_INPUT, + .pull_up_en = config->pullup == true ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + ZH_ERROR_CHECK(gpio_config(&io_config) == ESP_OK, ESP_FAIL, NULL, "GPIO initialization failed."); pcnt_unit_config_t pcnt_unit_config = { - .high_limit = config->encoder_pulses, - .low_limit = -config->encoder_pulses, + .high_limit = 4 * config->encoder_pulses, + .low_limit = -4 * config->encoder_pulses, }; pcnt_unit_handle_t pcnt_unit_handle = NULL; ZH_ERROR_CHECK(pcnt_new_unit(&pcnt_unit_config, &pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT initialization failed."); @@ -127,57 +143,52 @@ static esp_err_t _zh_inclinometer_pcnt_init(const zh_inclinometer_init_config_t .max_glitch_ns = 1000, }; ZH_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit_handle, &pcnt_glitch_filter_config) == ESP_OK, ESP_FAIL, - ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail."), "PCNT initialization failed."); + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); pcnt_chan_config_t pcnt_chan_a_config = { .edge_gpio_num = config->a_gpio_number, .level_gpio_num = config->b_gpio_number, }; pcnt_channel_handle_t pcnt_channel_a_handle = NULL; ZH_ERROR_CHECK(pcnt_new_channel(pcnt_unit_handle, &pcnt_chan_a_config, &pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, - ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail."), "PCNT initialization failed."); + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); pcnt_chan_config_t pcnt_chan_b_config = { .edge_gpio_num = config->b_gpio_number, .level_gpio_num = config->a_gpio_number, }; pcnt_channel_handle_t pcnt_channel_b_handle = NULL; ZH_ERROR_CHECK(pcnt_new_channel(pcnt_unit_handle, &pcnt_chan_b_config, &pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); - ZH_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_channel_a_handle, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD) == ESP_OK, ESP_FAIL, - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); - ZH_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_channel_a_handle, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_HOLD) == ESP_OK, ESP_FAIL, - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); - ZH_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_channel_b_handle, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD) == ESP_OK, ESP_FAIL, - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); - ZH_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_channel_b_handle, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_HOLD) == ESP_OK, ESP_FAIL, - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); + ZH_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_channel_a_handle, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_INCREASE) == ESP_OK, ESP_FAIL, + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); + ZH_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_channel_a_handle, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE) == ESP_OK, ESP_FAIL, + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); + ZH_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_channel_b_handle, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_DECREASE) == ESP_OK, ESP_FAIL, + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); + ZH_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_channel_b_handle, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE) == ESP_OK, ESP_FAIL, + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); ZH_ERROR_CHECK(pcnt_unit_enable(pcnt_unit_handle) == ESP_OK, ESP_FAIL, - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); ZH_ERROR_CHECK(pcnt_unit_clear_count(pcnt_unit_handle) == ESP_OK, ESP_FAIL, - {ZH_ERROR_CHECK(pcnt_unit_disable(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT unit disable fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); + {ZH_ERROR_CHECK_CONT(pcnt_unit_disable(pcnt_unit_handle) == ESP_OK, NULL, "PCNT unit disable fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); ZH_ERROR_CHECK(pcnt_unit_start(pcnt_unit_handle) == ESP_OK, ESP_FAIL, - {ZH_ERROR_CHECK(pcnt_unit_disable(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT unit disable fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete channel fail.")}; - {ZH_ERROR_CHECK(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, ESP_FAIL, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); - if (config->pullup == false) - { - ZH_ERROR_CHECK(gpio_pullup_dis((gpio_num_t)config->a_gpio_number) == ESP_OK, ESP_FAIL, NULL, "GPIO pullup disable fail."); - ZH_ERROR_CHECK(gpio_pullup_dis((gpio_num_t)config->b_gpio_number) == ESP_OK, ESP_FAIL, NULL, "GPIO pullup disable fail."); - } + {ZH_ERROR_CHECK_CONT(pcnt_unit_disable(pcnt_unit_handle) == ESP_OK, NULL, "PCNT unit disable fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_a_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_channel(pcnt_channel_b_handle) == ESP_OK, NULL, "PCNT delete channel fail.")}; + {ZH_ERROR_CHECK_CONT(pcnt_del_unit(pcnt_unit_handle) == ESP_OK, NULL, "PCNT delete unit fail.")}, "PCNT initialization failed."); handle->pcnt_unit_handle = pcnt_unit_handle; handle->pcnt_channel_a_handle = pcnt_channel_a_handle; handle->pcnt_channel_b_handle = pcnt_channel_b_handle;