From 1c1198cf4a1ffaecbeddc806ac15f42b5ff3c6d3 Mon Sep 17 00:00:00 2001 From: morris Date: Sat, 12 Oct 2024 16:29:45 +0800 Subject: [PATCH] feat(dedic_gpio): enable pad input for the input signal previously, we asked the user to enable the gpio direction before initialize the dedicated GPIO. Now the dedicated GPIO driver will help enable the input/output path according to the in_en and out_en flags. --- components/esp_driver_gpio/src/dedic_gpio.c | 12 ++ .../main/test_dedicated_gpio.c | 26 +---- .../api-reference/peripherals/dedic_gpio.rst | 33 ++---- .../api-reference/peripherals/dedic_gpio.rst | 29 ++--- .../generic_gpio/main/gpio_example_main.c | 12 +- .../gpio/matrix_keyboard/README.md | 10 +- .../matrix_keyboard/include/matrix_keyboard.h | 18 +-- .../matrix_keyboard/src/matrix_keyboard.c | 107 ++++++------------ .../main/matrix_keyboard_example_main.c | 12 +- tools/ci/check_copyright_ignore.txt | 3 - 10 files changed, 89 insertions(+), 173 deletions(-) diff --git a/components/esp_driver_gpio/src/dedic_gpio.c b/components/esp_driver_gpio/src/dedic_gpio.c index bbc66995b2..3faf0d9de7 100644 --- a/components/esp_driver_gpio/src/dedic_gpio.c +++ b/components/esp_driver_gpio/src/dedic_gpio.c @@ -269,6 +269,7 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_ if (config->flags.in_en) { for (size_t i = 0; i < config->array_size; i++) { gpio_func_sel(config->gpio_array[i], PIN_FUNC_GPIO); + gpio_input_enable(config->gpio_array[i]); esp_rom_gpio_connect_in_signal(config->gpio_array[i], dedic_gpio_periph_signals.cores[core_id].in_sig_per_channel[in_offset + i], config->flags.in_invert); } } @@ -325,6 +326,17 @@ esp_err_t dedic_gpio_del_bundle(dedic_gpio_bundle_handle_t bundle) } portEXIT_CRITICAL(&s_platform[core_id]->spinlock); + if (bundle->in_mask > 0) { + for (size_t i = 0; i < bundle->nr_gpio; i++) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, dedic_gpio_periph_signals.cores[core_id].in_sig_per_channel[bundle->in_offset + i], 0); + } + } + if (bundle->out_mask > 0) { + for (size_t i = 0; i < bundle->nr_gpio; i++) { + gpio_output_disable(bundle->gpio_array[i]); + } + } + free(bundle); if (recycle_all) { diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_dedicated_gpio.c b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_dedicated_gpio.c index fb306b523e..9b3f73635e 100644 --- a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_dedicated_gpio.c +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_dedicated_gpio.c @@ -70,16 +70,8 @@ static void test_dedic_gpio_on_specific_core(void *args) uint32_t value = 0; dedic_gpio_cpu_ll_write_all(0x0); // clear all out channels - // configure a group of GPIOs, output only - const int bundleA_gpios[] = {ctx->gpios[0], ctx->gpios[1]}; - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - }; - for (int i = 0; i < sizeof(bundleA_gpios) / sizeof(bundleA_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundleA_gpios[i]; - gpio_config(&io_conf); - } // Create bundleA, output only + const int bundleA_gpios[] = {ctx->gpios[0], ctx->gpios[1]}; dedic_gpio_bundle_handle_t bundleA = NULL; dedic_gpio_bundle_config_t bundleA_config = { .gpio_array = bundleA_gpios, @@ -90,15 +82,8 @@ static void test_dedic_gpio_on_specific_core(void *args) }; TEST_ESP_OK(dedic_gpio_new_bundle(&bundleA_config, &bundleA)); - // configure another group of GPIOs, input and output - const int bundleB_gpios[] = {ctx->gpios[2], ctx->gpios[3]}; - io_conf.mode = GPIO_MODE_INPUT_OUTPUT; - for (int i = 0; i < sizeof(bundleB_gpios) / sizeof(bundleB_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundleB_gpios[i]; - gpio_config(&io_conf); - } - // GPIO bundleB, input and output + const int bundleB_gpios[] = {ctx->gpios[2], ctx->gpios[3]}; dedic_gpio_bundle_handle_t bundleB = NULL; dedic_gpio_bundle_config_t bundleB_config = { .gpio_array = bundleB_gpios, @@ -192,13 +177,6 @@ TEST_CASE("Dedicated_GPIO_interrupt_and_callback", "[dedic_gpio]") #else const int bundle_gpios[] = {0, 1}; #endif - gpio_config_t io_conf = { - .mode = GPIO_MODE_INPUT_OUTPUT, - }; - for (int i = 0; i < sizeof(bundle_gpios) / sizeof(bundle_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundle_gpios[i]; - gpio_config(&io_conf); - } dedic_gpio_bundle_handle_t bundle = NULL; dedic_gpio_bundle_config_t bundle_config = { .gpio_array = bundle_gpios, diff --git a/docs/en/api-reference/peripherals/dedic_gpio.rst b/docs/en/api-reference/peripherals/dedic_gpio.rst index 319586f4f6..108abd73e1 100644 --- a/docs/en/api-reference/peripherals/dedic_gpio.rst +++ b/docs/en/api-reference/peripherals/dedic_gpio.rst @@ -16,32 +16,21 @@ A GPIO bundle is a group of GPIOs, which can be manipulated at the same time in .. note:: - Dedicated GPIO is more of a CPU peripheral, so it has a strong relationship with CPU core. It's highly recommended to install and operate GPIO bundle in a pin-to-core task. For example, if GPIOA is connected to CPU0, and the dedicated GPIO instruction is issued from CPU1, then it's impossible to control GPIOA. + Dedicated GPIO is more like a CPU peripheral, it has a strong relationship with CPU core. It's highly recommended to install and operate GPIO bundle in the same task, and the task should be pined to a CPU core. For example, if GPIO_A is connected to CPU_0, but the dedicated GPIO instruction is issued from CPU_1, then it's impossible to control GPIO_A. To install a GPIO bundle, one needs to call :cpp:func:`dedic_gpio_new_bundle` to allocate the software resources and connect the dedicated channels to user selected GPIOs. Configurations for a GPIO bundle are covered in :cpp:type:`dedic_gpio_bundle_config_t` structure: -- :cpp:member:`gpio_array`: An array that contains GPIO number. -- :cpp:member:`array_size`: Element number of :cpp:member:`gpio_array`. -- :cpp:member:`flags`: Extra flags to control the behavior of GPIO Bundle. +- :cpp:member:`dedic_gpio_bundle_config_t::gpio_array`: An array that contains GPIO number. +- :cpp:member:`dedic_gpio_bundle_config_t::array_size`: Element number of :cpp:member:`dedic_gpio_bundle_config_t::gpio_array`. +- :cpp:member:`dedic_gpio_bundle_config_t::in_en` and :cpp:member:`dedic_gpio_bundle_config_t::out_en` are used to configure whether to enable the input and output ability of the GPIO(s). +- :cpp:member:`dedic_gpio_bundle_config_t::in_invert` and :cpp:member:`dedic_gpio_bundle_config_t::out_invert` are used to configure whether to invert the GPIO signal. - - :cpp:member:`in_en` and :cpp:member:`out_en` are used to select whether to enable the input and output function (note, they can be enabled together). - - :cpp:member:`in_invert` and :cpp:member:`out_invert` are used to select whether to invert the GPIO signal. - -The following code shows how to install a output only GPIO bundle: +The following code shows how to install an output only GPIO bundle: .. highlight:: c :: - // configure GPIO - const int bundleA_gpios[] = {0, 1}; - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - }; - for (int i = 0; i < sizeof(bundleA_gpios) / sizeof(bundleA_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundleA_gpios[i]; - gpio_config(&io_conf); - } // Create bundleA, output only dedic_gpio_bundle_handle_t bundleA = NULL; dedic_gpio_bundle_config_t bundleA_config = { @@ -53,11 +42,7 @@ The following code shows how to install a output only GPIO bundle: }; ESP_ERROR_CHECK(dedic_gpio_new_bundle(&bundleA_config, &bundleA)); -To uninstall the GPIO bundle, one needs to call :cpp:func:`dedic_gpio_del_bundle`. - -.. note:: - - :cpp:func:`dedic_gpio_new_bundle` doesn't cover any GPIO pad configuration (e.g., pull up/down, drive ability, output/input enable), so before installing a dedicated GPIO bundle, you have to configure the GPIO separately using GPIO driver API (e.g., :cpp:func:`gpio_config`). For more information about GPIO driver, please refer to :doc:`GPIO API Reference `. +To uninstall the GPIO bundle, you should call :cpp:func:`dedic_gpio_del_bundle`. GPIO Bundle Operations @@ -92,13 +77,13 @@ For advanced users, they can always manipulate the GPIOs by writing assembly cod 3. Call CPU LL apis (e.g., `dedic_gpio_cpu_ll_write_mask`) or write assembly code with that mask 4. The fastest way of toggling IO is to use the dedicated "set/clear" instructions: - .. only:: esp32s2 or esp32s3 + .. only:: CONFIG_IDF_TARGET_ARCH_XTENSA - Set bits of GPIO: ``set_bit_gpio_out imm[7:0]`` - Clear bits of GPIO: ``clr_bit_gpio_out imm[7:0]`` - Note: Immediate value width depends on the number of dedicated GPIO channels - .. only:: esp32c2 or esp32c3 or esp32c6 or esp32h2 + .. only:: CONFIG_IDF_TARGET_ARCH_RISCV - Set bits of GPIO: ``csrrsi rd, csr, imm[4:0]`` - Clear bits of GPIO: ``csrrci rd, csr, imm[4:0]`` diff --git a/docs/zh_CN/api-reference/peripherals/dedic_gpio.rst b/docs/zh_CN/api-reference/peripherals/dedic_gpio.rst index 68d58211db..37f4979bf9 100644 --- a/docs/zh_CN/api-reference/peripherals/dedic_gpio.rst +++ b/docs/zh_CN/api-reference/peripherals/dedic_gpio.rst @@ -16,16 +16,14 @@ GPIO 捆绑包是一组 GPIO,该组 GPIO 可以在一个 CPU 周期内同时 .. note:: - 专用 GPIO 更像是 CPU 外设,因此与 CPU 内核关系密切。强烈建议在 pin-to-core 任务中安装和操作 GPIO 捆绑包。例如,如果 GPIOA 连接到了 CPU0,而专用的 GPIO 指令却是从 CPU1 发出的,那么就无法控制 GPIOA。 + 专用 GPIO 更像是 CPU 外设,因此与 CPU 内核关系密切。强烈建议在 pin-to-core 任务中安装和操作 GPIO 捆绑包。例如,如果 GPIO_A 连接到了 CPU_0,而专用的 GPIO 指令却是从 CPU_1 发出的,那么就无法控制 GPIO_A。 安装 GPIO 捆绑包需要调用 :cpp:func:`dedic_gpio_new_bundle` 来分配软件资源并将专用通道连接到用户选择的 GPIO。GPIO 捆绑包的配置在 :cpp:type:`dedic_gpio_bundle_config_t` 结构体中: -- :cpp:member:`gpio_array`:包含 GPIO 编号的数组。 -- :cpp:member:`array_size`::cpp:member:`gpio_array` 的元素个数。 -- :cpp:member:`flags`:用于控制 GPIO 捆绑包行为的标志。 - - - :cpp:member:`in_en` 和 :cpp:member:`out_en` 用于选择是否开启输入输出功能(这两个功能可以同时开启)。 - - :cpp:member:`in_invert` 和 :cpp:member:`out_invert` 用于选择是否反转 GPIO 信号。 +- :cpp:member:`dedic_gpio_bundle_config_t::gpio_array`:包含 GPIO 编号的数组。 +- :cpp:member:`dedic_gpio_bundle_config_t::array_size`: :cpp:member:`dedic_gpio_bundle_config_t::gpio_array` 的元素个数。 +- :cpp:member:`dedic_gpio_bundle_config_t::in_en` 和 :cpp:member:`dedic_gpio_bundle_config_t::out_en` 用于选择是否开启输入输出功能(这两个功能可以同时开启)。 +- :cpp:member:`dedic_gpio_bundle_config_t::in_invert` 和 :cpp:member:`dedic_gpio_bundle_config_t::out_invert` 用于选择是否反转 GPIO 信号。 以下代码展示了如何安装只有输出功能的 GPIO 捆绑包: @@ -33,15 +31,6 @@ GPIO 捆绑包是一组 GPIO,该组 GPIO 可以在一个 CPU 周期内同时 :: - // 配置 GPIO - const int bundleA_gpios[] = {0, 1}; - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - }; - for (int i = 0; i < sizeof(bundleA_gpios) / sizeof(bundleA_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundleA_gpios[i]; - gpio_config(&io_conf); - } // 创建 bundleA,仅输出 dedic_gpio_bundle_handle_t bundleA = NULL; dedic_gpio_bundle_config_t bundleA_config = { @@ -55,10 +44,6 @@ GPIO 捆绑包是一组 GPIO,该组 GPIO 可以在一个 CPU 周期内同时 如需卸载 GPIO 捆绑包,可调用 :cpp:func:`dedic_gpio_del_bundle`。 -.. note:: - - :cpp:func:`dedic_gpio_new_bundle` 不包含任何 GPIO pad 配置(例如上拉/下拉、驱动能力、输出/输入使能)。因此,在安装专用 GPIO 捆绑包之前,必须使用 GPIO 驱动程序 API(如 :cpp:func:`gpio_config`)单独配置 GPIO。更多关于 GPIO 驱动的信息,请参考 :doc:`GPIO API 参考 `。 - GPIO 捆绑包操作 ---------------------- @@ -92,13 +77,13 @@ GPIO 捆绑包操作 3. 调用 CPU LL apis(如 `cpu_ll_write_dedic_gpio_mask`)或使用该掩码编写汇编代码 4. 切换 IO 的最快捷方式是使用专用的“设置/清除”指令: - .. only:: esp32s2 or esp32s3 + .. only:: CONFIG_IDF_TARGET_ARCH_XTENSA - 设置 GPIO 位:``set_bit_gpio_out imm[7:0]`` - 清除 GPIO 位:``clr_bit_gpio_out imm[7:0]`` - 注意:立即数宽度取决于专用 GPIO 通道的数量 - .. only:: esp32c2 or esp32c3 or esp32c6 or esp32h2 + .. only:: CONFIG_IDF_TARGET_ARCH_RISCV - 设置 GPIO 位:``csrrsi rd, csr, imm[4:0]`` - 清除 GPIO 位:``csrrci rd, csr, imm[4:0]`` diff --git a/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c b/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c index 27b22cdaa4..89b7bbc88a 100644 --- a/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c +++ b/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c @@ -1,11 +1,9 @@ -/* GPIO Example +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ #include #include #include diff --git a/examples/peripherals/gpio/matrix_keyboard/README.md b/examples/peripherals/gpio/matrix_keyboard/README.md index 31cd207e55..76d095e417 100644 --- a/examples/peripherals/gpio/matrix_keyboard/README.md +++ b/examples/peripherals/gpio/matrix_keyboard/README.md @@ -23,7 +23,7 @@ This matrix keyboard driver is interrupt-driven, supports a configurable debounc This example can run on any target that has the dedicated feature (e.g. ESP32-S2). It's not necessary for your matrix board to have pull-up resisters on row/column lines. The driver has enabled internal pull-up resister by default. A typical matrix board should look as follows: -``` +```text row_0 +--------+-------------------+------------------------------+-----------------+ | | | | + | + | + @@ -51,7 +51,7 @@ row_n +--------+-------------------+------------------------------+----------- Build the project and flash it to the board, then run monitor tool to view serial output: -``` +```text idf.py -p PORT flash monitor ``` @@ -63,7 +63,7 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output -``` +```text I (2883) example: press event, key code = 0002 I (3003) example: release event, key code = 0002 I (5053) example: press event, key code = 0001 @@ -77,3 +77,7 @@ I (8923) example: release event, key code = 0103 I (9543) example: press event, key code = 0203 I (9683) example: release event, key code = 0203 ``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h index 825ae31469..f4598c74cb 100644 --- a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h +++ b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c index daf1b6a341..48b7a23506 100644 --- a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c +++ b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,24 +7,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/timers.h" -#include "esp_compiler.h" #include "esp_log.h" +#include "esp_check.h" #include "driver/dedic_gpio.h" #include "driver/gpio.h" +#include "esp_private/gpio.h" #include "matrix_keyboard.h" -#include "esp_rom_sys.h" static const char *TAG = "mkbd"; -#define MKBD_CHECK(a, msg, tag, ret, ...) \ - do { \ - if (unlikely(!(a))) { \ - ESP_LOGE(TAG, "%s(%d): " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret_code = ret; \ - goto tag; \ - } \ - } while (0) - typedef struct matrix_kbd_t matrix_kbd_t; struct matrix_kbd_t { @@ -91,45 +82,36 @@ static void matrix_kbd_debounce_timer_callback(TimerHandle_t xTimer) esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handle_t *mkbd_handle) { - esp_err_t ret_code = ESP_OK; + esp_err_t ret = ESP_OK; matrix_kbd_t *mkbd = NULL; - MKBD_CHECK(config, "matrix keyboard configuration can't be null", err, ESP_ERR_INVALID_ARG); - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(config && mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); mkbd = calloc(1, sizeof(matrix_kbd_t) + (config->nr_row_gpios) * sizeof(uint32_t)); - MKBD_CHECK(mkbd, "allocate matrix keyboard context failed", err, ESP_ERR_NO_MEM); + ESP_RETURN_ON_FALSE(mkbd, ESP_ERR_NO_MEM, TAG, "no mem for matrix keyboard context"); + + // Create a ont-shot os timer, used for key debounce + mkbd->debounce_timer = xTimerCreate("kb_debounce", pdMS_TO_TICKS(config->debounce_ms), pdFALSE, mkbd, matrix_kbd_debounce_timer_callback); + ESP_GOTO_ON_FALSE(mkbd->debounce_timer, ESP_FAIL, err, TAG, "create debounce timer failed"); mkbd->nr_col_gpios = config->nr_col_gpios; mkbd->nr_row_gpios = config->nr_row_gpios; - // GPIO pad configuration - // Each GPIO used in matrix key board should be able to input and output - // In case the keyboard doesn't design a resister to pull up row/col line - // We enable the internal pull up resister, enable Open Drain as well - gpio_config_t io_conf = { - .mode = GPIO_MODE_INPUT_OUTPUT_OD, - .pull_up_en = 1 - }; - - for (int i = 0; i < config->nr_row_gpios; i++) { - io_conf.pin_bit_mask = 1ULL << config->row_gpios[i]; - gpio_config(&io_conf); - } - dedic_gpio_bundle_config_t bundle_row_config = { .gpio_array = config->row_gpios, .array_size = config->nr_row_gpios, + // Each GPIO used in matrix key board should be able to input and output .flags = { .in_en = 1, .out_en = 1, }, }; - MKBD_CHECK(dedic_gpio_new_bundle(&bundle_row_config, &mkbd->row_bundle) == ESP_OK, - "create row bundle failed", err, ESP_FAIL); + ESP_GOTO_ON_ERROR(dedic_gpio_new_bundle(&bundle_row_config, &mkbd->row_bundle), err, TAG, "create row bundle failed"); - for (int i = 0; i < config->nr_col_gpios; i++) { - io_conf.pin_bit_mask = 1ULL << config->col_gpios[i]; - gpio_config(&io_conf); + // In case the keyboard doesn't design a resister to pull up row/col line + // We enable the internal pull up resister, enable Open Drain as well + for (int i = 0; i < config->nr_row_gpios; i++) { + gpio_pullup_en(config->row_gpios[i]); + gpio_od_enable(config->row_gpios[i]); } dedic_gpio_bundle_config_t bundle_col_config = { @@ -140,8 +122,12 @@ esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handl .out_en = 1, }, }; - MKBD_CHECK(dedic_gpio_new_bundle(&bundle_col_config, &mkbd->col_bundle) == ESP_OK, - "create col bundle failed", err, ESP_FAIL); + ESP_GOTO_ON_ERROR(dedic_gpio_new_bundle(&bundle_col_config, &mkbd->col_bundle), err, TAG, "create col bundle failed"); + + for (int i = 0; i < config->nr_col_gpios; i++) { + gpio_pullup_en(config->col_gpios[i]); + gpio_od_enable(config->col_gpios[i]); + } // Disable interrupt dedic_gpio_bundle_set_interrupt_and_callback(mkbd->row_bundle, (1 << config->nr_row_gpios) - 1, @@ -149,45 +135,35 @@ esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handl dedic_gpio_bundle_set_interrupt_and_callback(mkbd->col_bundle, (1 << config->nr_col_gpios) - 1, DEDIC_GPIO_INTR_NONE, NULL, NULL); - // Create a ont-shot os timer, used for key debounce - mkbd->debounce_timer = xTimerCreate("kb_debounce", pdMS_TO_TICKS(config->debounce_ms), pdFALSE, mkbd, matrix_kbd_debounce_timer_callback); - MKBD_CHECK(mkbd->debounce_timer, "create debounce timer failed", err, ESP_FAIL); - * mkbd_handle = mkbd; return ESP_OK; err: - if (mkbd) { - if (mkbd->debounce_timer) { - xTimerDelete(mkbd->debounce_timer, 0); - } - if (mkbd->col_bundle) { - dedic_gpio_del_bundle(mkbd->col_bundle); - } - if (mkbd->row_bundle) { - dedic_gpio_del_bundle(mkbd->row_bundle); - } - free(mkbd); + if (mkbd->debounce_timer) { + xTimerDelete(mkbd->debounce_timer, 0); } - return ret_code; + if (mkbd->col_bundle) { + dedic_gpio_del_bundle(mkbd->col_bundle); + } + if (mkbd->row_bundle) { + dedic_gpio_del_bundle(mkbd->row_bundle); + } + free(mkbd); + return ret; } esp_err_t matrix_kbd_uninstall(matrix_kbd_handle_t mkbd_handle) { - esp_err_t ret_code = ESP_OK; - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); xTimerDelete(mkbd_handle->debounce_timer, 0); dedic_gpio_del_bundle(mkbd_handle->col_bundle); dedic_gpio_del_bundle(mkbd_handle->row_bundle); free(mkbd_handle); return ESP_OK; -err: - return ret_code; } esp_err_t matrix_kbd_start(matrix_kbd_handle_t mkbd_handle) { - esp_err_t ret_code = ESP_OK; - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); // row lines set to high level dedic_gpio_bundle_write(mkbd_handle->row_bundle, (1 << mkbd_handle->nr_row_gpios) - 1, (1 << mkbd_handle->nr_row_gpios) - 1); @@ -203,15 +179,11 @@ esp_err_t matrix_kbd_start(matrix_kbd_handle_t mkbd_handle) DEDIC_GPIO_INTR_BOTH_EDGE, matrix_kbd_row_isr_callback, mkbd_handle); return ESP_OK; -err: - return ret_code; } esp_err_t matrix_kbd_stop(matrix_kbd_handle_t mkbd_handle) { - esp_err_t ret_code = ESP_OK; - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); - + ESP_RETURN_ON_FALSE(mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); xTimerStop(mkbd_handle->debounce_timer, 0); // Disable interrupt @@ -221,17 +193,12 @@ esp_err_t matrix_kbd_stop(matrix_kbd_handle_t mkbd_handle) DEDIC_GPIO_INTR_NONE, NULL, NULL); return ESP_OK; -err: - return ret_code; } esp_err_t matrix_kbd_register_event_handler(matrix_kbd_handle_t mkbd_handle, matrix_kbd_event_handler handler, void *args) { - esp_err_t ret_code = ESP_OK; - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); mkbd_handle->event_handler = handler; mkbd_handle->event_handler_args = args; return ESP_OK; -err: - return ret_code; } diff --git a/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c b/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c index fd1008e90b..657d24136a 100644 --- a/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c +++ b/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c @@ -1,11 +1,9 @@ -/* Matrix Keyboard (based on dedicated GPIO) example +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ #include #include "esp_log.h" #include "matrix_keyboard.h" diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 681279a268..8fc70c2ab7 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -876,9 +876,6 @@ examples/mesh/manual_networking/main/mesh_main.c examples/network/simple_sniffer/main/cmd_sniffer.c examples/network/simple_sniffer/main/cmd_sniffer.h examples/network/simple_sniffer/main/simple_sniffer_example_main.c -examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c -examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h -examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c examples/peripherals/ledc/ledc_basic/main/ledc_basic_example_main.c examples/peripherals/ledc/ledc_fade/main/ledc_fade_example_main.c examples/peripherals/sdio/host/main/app_main.c