mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
feat(zigbee): upgrade zigbee example to v2.0
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
include($ENV{IDF_PATH}/tools/cmake/version.cmake)
|
||||
|
||||
set(public_requires "freertos")
|
||||
|
||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
|
||||
list(APPEND public_requires "esp_driver_gpio")
|
||||
else()
|
||||
list(APPEND public_requires "driver")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRC_DIRS "src"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES ${public_requires})
|
||||
@@ -0,0 +1,27 @@
|
||||
menu "ESP Zigbee DevKit GPIO Configuration"
|
||||
config GPIO_BOOT_ON_DEVKIT
|
||||
int "BOOT GPIO on devkit"
|
||||
default 9 if IDF_TARGET_ESP32H2
|
||||
default 9 if IDF_TARGET_ESP32C6
|
||||
default 28 if IDF_TARGET_ESP32C5
|
||||
default 9
|
||||
|
||||
help
|
||||
The GPIO connected to the BOOT button on the devkits
|
||||
|
||||
config GPIO_EXT1_WAKEUP_SOURCE
|
||||
int "External wakeup GPIO"
|
||||
default 9 if IDF_TARGET_ESP32H2
|
||||
default 7 if IDF_TARGET_ESP32C6
|
||||
default 7 if IDF_TARGET_ESP32S31
|
||||
default 6 if IDF_TARGET_ESP32C5
|
||||
range 7 14 if IDF_TARGET_ESP32H2
|
||||
range 0 7 if IDF_TARGET_ESP32C6
|
||||
range 0 7 if IDF_TARGET_ESP32S31
|
||||
range 0 6 if IDF_TARGET_ESP32C5
|
||||
default 9
|
||||
|
||||
help
|
||||
The GPIO can be used as external wake up source for sleep device
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* Zigbee switch driver
|
||||
*
|
||||
* This driver reads a physical GPIO switch/button (e.g. BOOT button on devkit),
|
||||
* uses GPIO interrupt and a queue to report press/release events to the application
|
||||
* via a callback. Typical use: Zigbee HA On/Off Switch sending commands on button press.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Opaque handle for the switch driver instance.
|
||||
*/
|
||||
typedef void* switch_driver_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Invalid handle value.
|
||||
*/
|
||||
#define SWITCH_INV_HANDLE NULL
|
||||
|
||||
/**
|
||||
* @brief Callback invoked from GPIO ISR (low-level) when the switch level changes.
|
||||
*
|
||||
* Runs in interrupt context: keep it minimal (e.g. set a flag or post to a queue).
|
||||
* Do not block or call blocking / non-ISR-safe APIs.
|
||||
*
|
||||
* @param user_ctx User context passed at init
|
||||
*/
|
||||
typedef void (*switch_event_cb_t)(switch_driver_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Switch driver configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_num_t gpio_num; /*!< GPIO number used as switch input (e.g. BOOT button) */
|
||||
switch_event_cb_t event_cb; /*!< Callback on level change (invoked from ISR); may be NULL if only polling */
|
||||
} switch_driver_config_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the switch driver.
|
||||
*
|
||||
* Configures the GPIO in switch_driver_init() as input with pull-up enabled,
|
||||
* installs the GPIO ISR, and hooks the callback. The callback is triggered in low-level
|
||||
* (GPIO ISR) context on level change.
|
||||
*
|
||||
* @param config Driver configuration (gpio_num required; event_cb optional)
|
||||
* @return Handle
|
||||
*/
|
||||
switch_driver_handle_t switch_driver_init(const switch_driver_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the switch driver.
|
||||
*
|
||||
* Removes ISR handler and resets GPIO.
|
||||
*
|
||||
* @param handle Handle from switch_driver_init; may be NULL
|
||||
*/
|
||||
void switch_driver_deinit(switch_driver_handle_t handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* Zigbee switch driver
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "switch_driver.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static QueueHandle_t gpio_event_queue = NULL;
|
||||
|
||||
static void switch_driver_gpio_intr_enabled(gpio_num_t gpio_num, bool enabled)
|
||||
{
|
||||
if (enabled) {
|
||||
gpio_intr_enable(gpio_num);
|
||||
} else {
|
||||
gpio_intr_disable(gpio_num);
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR gpio_isr_handler(void *arg)
|
||||
{
|
||||
switch_driver_config_t *config = (switch_driver_config_t *)arg;
|
||||
switch_driver_gpio_intr_enabled(config->gpio_num, false);
|
||||
xQueueSendFromISR(gpio_event_queue, &config, NULL);
|
||||
}
|
||||
|
||||
static void switch_driver_button_detected(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
switch_driver_config_t *config = NULL;
|
||||
while (1) {
|
||||
if (xQueueReceive(gpio_event_queue, &config, portMAX_DELAY) == pdTRUE) {
|
||||
if (config) {
|
||||
if (config->event_cb) {
|
||||
config->event_cb(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
switch_driver_gpio_intr_enabled(config->gpio_num, true);
|
||||
}
|
||||
}
|
||||
switch_driver_handle_t switch_driver_init(const switch_driver_config_t *config)
|
||||
{
|
||||
if (config == NULL || config->gpio_num < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch_driver_config_t *handle = (switch_driver_config_t *)malloc(sizeof(switch_driver_config_t));
|
||||
if (handle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(handle, (void *)config, sizeof(switch_driver_config_t));
|
||||
|
||||
/* Configure GPIO in init: input, pull-up, and negative-edge interrupt */
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << config->gpio_num),
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_LOW_LEVEL,
|
||||
};
|
||||
esp_err_t ret = gpio_config(&io_conf);
|
||||
if (ret != ESP_OK) {
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
gpio_event_queue = xQueueCreate(10, sizeof(switch_driver_config_t *));
|
||||
if (gpio_event_queue == 0) {
|
||||
gpio_reset_pin(config->gpio_num);
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xTaskCreate(switch_driver_button_detected, "button_detected", 4096, NULL, 10, NULL);
|
||||
ret = gpio_install_isr_service(0);
|
||||
if (ret != ESP_OK) {
|
||||
gpio_reset_pin(config->gpio_num);
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = gpio_isr_handler_add(config->gpio_num, gpio_isr_handler, (void *)handle);
|
||||
if (ret != ESP_OK) {
|
||||
gpio_reset_pin(config->gpio_num);
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void switch_driver_deinit(switch_driver_handle_t handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return;
|
||||
}
|
||||
switch_driver_config_t *config = (switch_driver_config_t *)handle;
|
||||
gpio_isr_handler_remove(config->gpio_num);
|
||||
gpio_reset_pin(config->gpio_num);
|
||||
free(config);
|
||||
}
|
||||
Reference in New Issue
Block a user