diff --git a/.gitignore b/.gitignore index 0ea1dabc..66ccd05f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ __pycache__/ # build /build* +/samples/**/build* /twister-out* # docs diff --git a/samples/light_bulb/CMakeLists.txt b/samples/light_bulb/CMakeLists.txt index e9a1acd7..174010c4 100644 --- a/samples/light_bulb/CMakeLists.txt +++ b/samples/light_bulb/CMakeLists.txt @@ -18,7 +18,10 @@ project("Zigbee + Matter Light Bulb with FOTA") if(CONFIG_CHIP) # Enable GNU STD support for Matter include(${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/app/enable-gnu-std.cmake) - + + # Include all source files that are located in the Matter common directory. + include(${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/cmake/source_common.cmake) + # Include Data Model utils (simplified for Zigbee coexistence) include(${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/cmake/data_model.cmake) @@ -35,8 +38,10 @@ if(CONFIG_CHIP) # NORDIC SDK APP START target_sources(app PRIVATE - src/main_matter.c - src/matter_init.cpp + src/main.cpp + src/app_task_zigbee.cpp + src/app_task_matter.cpp + ${CHIP_ROOT}/src/app/persistence/DeferredAttributePersistenceProvider.cpp ) ncs_configure_data_model() @@ -44,7 +49,8 @@ if(CONFIG_CHIP) else() # Zigbee-only build target_sources(app PRIVATE - src/main.c + src/main.cpp + src/app_task_zigbee.cpp ) target_include_directories(app PRIVATE include) diff --git a/samples/light_bulb/CMakeLists_matter.txt b/samples/light_bulb/CMakeLists_matter.txt deleted file mode 100644 index e78466f6..00000000 --- a/samples/light_bulb/CMakeLists_matter.txt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright (c) 2026 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -cmake_minimum_required(VERSION 3.20.0) - -# PoC: Force linker to allow duplicate symbols (Zigbee vs OpenThread radio callbacks) -# This build is for memory estimation only - not functionally viable at runtime -add_link_options(-Wl,--allow-multiple-definition) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) - -project("Zigbee + Matter Light Bulb with FOTA") - -# Check if Matter is enabled -if(CONFIG_CHIP) - # Enable GNU STD support for Matter - include(${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/app/enable-gnu-std.cmake) - - # Include Data Model utils (simplified for Zigbee coexistence) - include(${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/cmake/data_model.cmake) - - include(${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/cmake/zap_helpers.cmake) - ncs_get_zap_parent_dir(ZAP_PARENT_DIR) - - target_include_directories(app PRIVATE - src - include - ${ZAP_PARENT_DIR} - ) - - target_compile_options(app PRIVATE -Wno-deprecated-declarations) - - # NORDIC SDK APP START - target_sources(app PRIVATE - src/main_matter.c - src/matter_init.cpp - ) - - ncs_configure_data_model() - # NORDIC SDK APP END -else() - # Zigbee-only build - target_sources(app PRIVATE - src/main.c - ) - - target_include_directories(app PRIVATE include) -endif() diff --git a/samples/light_bulb/Kconfig b/samples/light_bulb/Kconfig index 3cac7bde..a1d4db95 100644 --- a/samples/light_bulb/Kconfig +++ b/samples/light_bulb/Kconfig @@ -4,7 +4,26 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -source "Kconfig.zephyr" +# Sample configuration used for Thread networking +if OPENTHREAD + +choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION + default OPENTHREAD_NORDIC_LIBRARY_FTD +endchoice + +choice OPENTHREAD_DEVICE_TYPE + default OPENTHREAD_FTD +endchoice + +endif # OPENTHREAD -# Include Matter common sample Kconfig if Matter is enabled -rsource "$(ZEPHYR_NRF_MODULE_DIR)/samples/matter/common/src/Kconfig" +config MPSL_THREAD_COOP_PRIO + default 8 + +if CHIP +source "$(ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR)/config/nrfconnect/chip-module/Kconfig.features" +source "$(ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR)/config/nrfconnect/chip-module/Kconfig.defaults" +source "$(ZEPHYR_NRF_MODULE_DIR)/samples/matter/common/src/Kconfig" +endif + +source "Kconfig.zephyr" diff --git a/samples/light_bulb/Kconfig_sysbuild_matter_fota b/samples/light_bulb/Kconfig_sysbuild_matter_fota index 70fa7969..82cc3aca 100644 --- a/samples/light_bulb/Kconfig_sysbuild_matter_fota +++ b/samples/light_bulb/Kconfig_sysbuild_matter_fota @@ -69,7 +69,3 @@ config DFU_MULTI_IMAGE_PACKAGE_NET endif # SOC_SERIES_NRF53X endif # BOOTLOADER_MCUBOOT - -#### Enable generating Matter factory data -config MATTER_FACTORY_DATA_GENERATE - default y diff --git a/samples/light_bulb/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/light_bulb/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 41dd5b05..e4dd03f4 100644 --- a/samples/light_bulb/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay +++ b/samples/light_bulb/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -6,7 +6,13 @@ / { chosen { - ncs,zigbee-timer = &timer24; + ncs,zigbee-timer = &timer23; + ncs,zboss-trace-uart = &uart20; + }; + + aliases { + /* Configure PWM module for led1 (LED2 on the board) */ + pwm-led1 = &pwm_led3; }; pwmleds { @@ -17,16 +23,6 @@ }; }; -// restore full RRAM and SRAM space - by default some parts are dedicated to FLRP -&cpuapp_rram { - reg = <0x0 DT_SIZE_K(2036)>; -}; - -&cpuapp_sram { - reg = <0x20000000 DT_SIZE_K(512)>; - ranges = <0x0 0x20000000 DT_SIZE_K(512)>; -}; - &pwm20 { status = "okay"; pinctrl-0 = <&pwm_default>; @@ -48,6 +44,6 @@ }; }; -&timer24 { +&timer23 { status = "okay"; }; diff --git a/samples/light_bulb/include/app_task_matter.h b/samples/light_bulb/include/app_task_matter.h new file mode 100644 index 00000000..104fade1 --- /dev/null +++ b/samples/light_bulb/include/app_task_matter.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#pragma once + +#include "board/board.h" +#include "pwm/pwm_device.h" + +#include + +struct k_timer; +struct Identify; + +enum class LightingActor : uint8_t { Remote, Button }; + +struct LightingEvent { + uint8_t Action; + LightingActor Actor; +}; + +class AppTask { +public: + static AppTask &Instance() { + static AppTask sAppTask; + return sAppTask; + }; + + CHIP_ERROR StartApp(); + + void UpdateClusterState(); + void InitPWMDDevice(); + Nrf::PWMDevice &GetPWMDevice() { return mPWMDevice; } + +private: + CHIP_ERROR Init(); + + static void LightingActionEventHandler(const LightingEvent &event); + static void ButtonEventHandler(Nrf::ButtonState state, + Nrf::ButtonMask hasChanged); + + static void ActionInitiated(Nrf::PWMDevice::Action_t action, int32_t actor); + static void ActionCompleted(Nrf::PWMDevice::Action_t action, int32_t actor); + + Nrf::PWMDevice mPWMDevice; +}; diff --git a/samples/light_bulb/include/app_task_zigbee.h b/samples/light_bulb/include/app_task_zigbee.h new file mode 100644 index 00000000..18cd366b --- /dev/null +++ b/samples/light_bulb/include/app_task_zigbee.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef APP_TASK_ZIGBEE_H +#define APP_TASK_ZIGBEE_H 1 + +void ZigbeeStart(void); + +#endif /* APP_TASK_ZIGBEE_H */ diff --git a/samples/light_bulb/src/chip_project_config.h b/samples/light_bulb/include/chip_project_config.h similarity index 100% rename from samples/light_bulb/src/chip_project_config.h rename to samples/light_bulb/include/chip_project_config.h diff --git a/samples/light_bulb/prj_matter_fota.conf b/samples/light_bulb/prj_matter_fota.conf index 296efe05..25d7d9ee 100644 --- a/samples/light_bulb/prj_matter_fota.conf +++ b/samples/light_bulb/prj_matter_fota.conf @@ -18,7 +18,7 @@ CONFIG_PWM=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_HEAP_MEM_POOL_SIZE=4096 +# CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_MAIN_THREAD_PRIORITY=7 ####################### @@ -27,6 +27,8 @@ CONFIG_MAIN_THREAD_PRIORITY=7 CONFIG_ZIGBEE_ADD_ON=y CONFIG_ZIGBEE_APP_UTILS=y +# Show Zigbee init/recovery logs (Device first start, network steering recovery). +CONFIG_ZIGBEE_APP_UTILS_LOG_LEVEL_INF=y CONFIG_ZIGBEE_ROLE_ROUTER=y # Scene extension @@ -38,13 +40,7 @@ CONFIG_DK_LIBRARY=y # This example requires more workqueue stack CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 -# OpenThread/Thread support for Matter w/o Zephyr L2 -CONFIG_NET_L2_OPENTHREAD=n -CONFIG_CHIP_USE_ZEPHYR_NETWORKING=n -CONFIG_OPENTHREAD=y -CONFIG_OPENTHREAD_NORDIC_LIBRARY_FTD=y -CONFIG_OPENTHREAD_SLAAC=y -CONFIG_OPENTHREAD_MANUAL_START=y +CONFIG_ZBOSS_OSIF_LOG_LEVEL_INF=y ####################### # Zigbee FOTA Configuration @@ -74,7 +70,8 @@ CONFIG_OPENTHREAD_MANUAL_START=y # Enable CHIP (Matter) CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="src/chip_project_config.h" +CONFIG_CHIP_PROJECT_CONFIG="include/chip_project_config.h" +CONFIG_CHIP_DEVICE_PRODUCT_NAME="Matter Zigbee Light Bulb" # Configure ZAP file CONFIG_NCS_SAMPLE_MATTER_ZAP_FILE_PATH="${APPLICATION_CONFIG_DIR}/src/matter_zap/light_bulb.zap" @@ -90,16 +87,7 @@ CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y CONFIG_CHIP_BLE_EXT_ADVERTISING=y CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 -# Bluetooth Low Energy configuration -CONFIG_BT=y -CONFIG_BT_PERIPHERAL=y -CONFIG_BT_DEVICE_NAME="MatterZigbeeLight" -CONFIG_BT_DEVICE_APPEARANCE=0 -CONFIG_BT_MAX_CONN=1 -CONFIG_BT_L2CAP_TX_MTU=247 -CONFIG_BT_BUF_ACL_RX_SIZE=251 -CONFIG_BT_BUF_ACL_TX_SIZE=251 -CONFIG_BT_RX_STACK_SIZE=2048 +CONFIG_BT_DEVICE_NAME="MatterZigbee" # Other settings CONFIG_THREAD_NAME=y @@ -110,12 +98,7 @@ CONFIG_RESET_ON_FATAL_ERROR=n CONFIG_USE_SEGGER_RTT=n # FIXME: Disabled Factory Data feature for initial development -# CONFIG_CHIP_FACTORY_DATA=y -# CONFIG_CHIP_FACTORY_DATA_BUILD=y - -# Matter commissioning -CONFIG_CHIP_COMMISSIONABLE_DEVICE_TYPE=y -CONFIG_CHIP_DEVICE_TYPE=256 +CONFIG_CHIP_FACTORY_DATA_NONE=y # FIXME: Disabled Matter OTA for initial development CONFIG_CHIP_OTA_REQUESTOR=n @@ -123,12 +106,7 @@ CONFIG_CHIP_BOOTLOADER_MCUBOOT=n CONFIG_CHIP_BOOTLOADER_NONE=y # Increase system workqueue stack for combined protocols (with Thread) -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 - -# Memory settings for Zigbee + Matter + Thread (PoC) -CONFIG_MAIN_STACK_SIZE=6144 -CONFIG_CHIP_MALLOC_SYS_HEAP=y -CONFIG_CHIP_MALLOC_SYS_HEAP_SIZE=32768 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=6144 # Libc malloc arena required for Zigbee + Matter coexistence. # - 0: no libc heap -> Matter init fails (malloc/calloc used during init). @@ -137,57 +115,7 @@ CONFIG_CHIP_MALLOC_SYS_HEAP_SIZE=32768 # - Positive value: static BSS heap of that size -> valid heap, no fault. # Matter uses CHIP_MALLOC_SYS_HEAP for its own allocations; this arena # covers libc malloc() used elsewhere (init, Zephyr, Zigbee, etc.). -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=32768 - -# Thread stack sizes -CONFIG_NET_TX_STACK_SIZE=1200 -CONFIG_NET_RX_STACK_SIZE=1500 - -# Crypto - PSA Crypto Backend -CONFIG_NORDIC_SECURITY_BACKEND=y -CONFIG_CHIP_CRYPTO_PSA=y -CONFIG_CHIP_CRYPTO_PSA_AEAD_SINGLE_PART=y -CONFIG_CHIP_CRYPTO_PSA_MIGRATE_DAC_PRIV_KEY=y -CONFIG_CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU=y -CONFIG_CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_SLOT_ID=176 -CONFIG_CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_ENCRYPTED=y -CONFIG_PSA_WANT_ALG_SPAKE2P_MATTER=y - -# Storage - use ZMS for nRF54L (NVS not supported) -CONFIG_ZMS=y -CONFIG_SETTINGS=y -CONFIG_SETTINGS_ZMS=y -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y -CONFIG_MPU_ALLOW_FLASH_WRITE=y - -# FIXME: Larger settings partition for Matter, to removed once pm_static is fixed -CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000 - -# Trusted storage backend for Matter PSA crypto keys -CONFIG_TRUSTED_STORAGE=y -CONFIG_TRUSTED_STORAGE_BACKEND_AEAD=y -CONFIG_TRUSTED_STORAGE_STORAGE_BACKEND_SETTINGS=y - -# Additional platform requirements for Matter -CONFIG_HWINFO=y -CONFIG_REBOOT=y -CONFIG_ENTROPY_GENERATOR=y - -# Matter thread requirements -CONFIG_SCHED_CPU_MASK=y - -# Watchdog -CONFIG_TASK_WDT=y - -# Matter common infrastructure configs (needed even without Thread) - -# Enable BT GATT for Matter BLE commissioning -CONFIG_BT_GATT_DYNAMIC_DB=y -CONFIG_BT_GATT_SERVICE_CHANGED=y -CONFIG_BT_GATT_CACHING=y -CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n - +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 ## PoC Configuration ## # Note: This configuration links all three stacks (Zigbee, Thread, Matter) for memory estimation @@ -197,3 +125,28 @@ CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n # Keep Matter shell disabled to avoid getopt conflicts CONFIG_CHIP_LIB_SHELL=n CONFIG_NCS_SAMPLE_MATTER_TEST_SHELL=n + +# Larger settings partition for Zigbee + Matter +CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000 + +# Enable for OpenThread logging +# UNCOMENT TO SEE LOGS FROM OPENTHREAD +# CONFIG_LOG_MODE_DEFERRED=y +# CONFIG_OPENTHREAD_DEBUG=y +# CONFIG_OPENTHREAD_LOG_LEVEL_DEBG=y +# CONFIG_LOG_BUFFER_SIZE=81920 +# CONFIG_SHELL=y +# CONFIG_OPENTHREAD_SHELL=y + +# Dispatcher +CONFIG_NRF_802154_CALLBACKS_DISPATCHER=y +CONFIG_NRF_802154_DRV_REINIT_ENABLED=y + +# We need it to disable ZBOSS thread +CONFIG_ZIGBEE_DEBUG_FUNCTIONS=y + +# Must be a preemptible priority (0–15), not cooperative (-1). With -1, ZBOSS is +# coop priority -1 and is outranked by MPSL Work (prio -8), so it never runs. +# State 128 = _THREAD_QUEUED (runnable); ZBOSS stays queued and never gets CPU. +CONFIG_ZBOSS_DEFAULT_THREAD_PRIORITY=1 +CONFIG_ZBOSS_DEFAULT_THREAD_STACK_SIZE=6144 diff --git a/samples/light_bulb/prj_matter_fota_release.conf b/samples/light_bulb/prj_matter_fota_release.conf index 0ba6dadb..f4902eac 100644 --- a/samples/light_bulb/prj_matter_fota_release.conf +++ b/samples/light_bulb/prj_matter_fota_release.conf @@ -3,16 +3,22 @@ # # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -# Release configuration for combined Zigbee + Matter + Thread (PoC) -# Optimized for minimum memory footprint +# Debug configuration for combined Zigbee + Matter + Thread (PoC) +# Includes logging, console, and debug features # Base sample configs CONFIG_NCS_SAMPLES_DEFAULTS=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_SERIAL=y CONFIG_GPIO=y CONFIG_PWM=y -CONFIG_HEAP_MEM_POOL_SIZE=4096 +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_MAIN_THREAD_PRIORITY=7 ####################### @@ -21,6 +27,8 @@ CONFIG_MAIN_THREAD_PRIORITY=7 CONFIG_ZIGBEE_ADD_ON=y CONFIG_ZIGBEE_APP_UTILS=y +# Show Zigbee init/recovery logs (Device first start, network steering recovery). +CONFIG_ZIGBEE_APP_UTILS_LOG_LEVEL_INF=y CONFIG_ZIGBEE_ROLE_ROUTER=y # Scene extension @@ -32,40 +40,29 @@ CONFIG_DK_LIBRARY=y # This example requires more workqueue stack CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 -# Networking -CONFIG_NETWORKING=y -CONFIG_NET_IPV6=y -CONFIG_NET_IP_ADDR_CHECK=y -CONFIG_NET_UDP=y -CONFIG_NET_TCP=y -CONFIG_NET_SOCKETS=y - -# OpenThread/Thread support for Matter (PoC - not functional with Zigbee) -CONFIG_NET_L2_OPENTHREAD=y -CONFIG_OPENTHREAD_NORDIC_LIBRARY_FTD=y -CONFIG_OPENTHREAD_SLAAC=y -CONFIG_OPENTHREAD_MANUAL_START=y +CONFIG_ZBOSS_OSIF_LOG_LEVEL_INF=y ####################### # Zigbee FOTA Configuration ####################### -# Enable Zigbee FOTA library -CONFIG_ZIGBEE_FOTA=y -CONFIG_ZIGBEE_FOTA_HW_VERSION=52 -CONFIG_ZIGBEE_FOTA_ENDPOINT=5 -CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="1.0.0" -CONFIG_ZIGBEE_FOTA_COMMENT="light_bulb_matter" +# FIXME: Disabled Zigbee FOTA for initial development +# # Enable Zigbee FOTA library +# CONFIG_ZIGBEE_FOTA=y +# CONFIG_ZIGBEE_FOTA_HW_VERSION=52 +# CONFIG_ZIGBEE_FOTA_ENDPOINT=5 +# CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="1.0.0" +# CONFIG_ZIGBEE_FOTA_COMMENT="light_bulb_matter" -# Ensure an MCUboot-compatible binary is generated. -CONFIG_IMG_MANAGER=y -CONFIG_STREAM_FLASH=y -CONFIG_DFU_TARGET_MCUBOOT=y -CONFIG_IMG_ERASE_PROGRESSIVELY=y -CONFIG_ZIGBEE_FOTA_PROGRESS_EVT=y +# # Ensure an MCUboot-compatible binary is generated. +# CONFIG_IMG_MANAGER=y +# CONFIG_STREAM_FLASH=y +# CONFIG_DFU_TARGET_MCUBOOT=y +# CONFIG_IMG_ERASE_PROGRESSIVELY=y +# CONFIG_ZIGBEE_FOTA_PROGRESS_EVT=y -# Increase the number of RX buffers for FOTA -CONFIG_NRF_802154_RX_BUFFERS=32 +# # Increase the number of RX buffers for FOTA +# CONFIG_NRF_802154_RX_BUFFERS=32 ####################### # Matter Configuration @@ -73,7 +70,8 @@ CONFIG_NRF_802154_RX_BUFFERS=32 # Enable CHIP (Matter) CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="src/chip_project_config.h" +CONFIG_CHIP_PROJECT_CONFIG="include/chip_project_config.h" +CONFIG_CHIP_DEVICE_PRODUCT_NAME="Matter Zigbee Light Bulb" # Configure ZAP file CONFIG_NCS_SAMPLE_MATTER_ZAP_FILE_PATH="${APPLICATION_CONFIG_DIR}/src/matter_zap/light_bulb.zap" @@ -89,90 +87,66 @@ CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y CONFIG_CHIP_BLE_EXT_ADVERTISING=y CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 -# Bluetooth Low Energy configuration -CONFIG_BT=y -CONFIG_BT_PERIPHERAL=y -CONFIG_BT_DEVICE_NAME="MatterZigbeeLight" -CONFIG_BT_DEVICE_APPEARANCE=0 -CONFIG_BT_MAX_CONN=1 -CONFIG_BT_L2CAP_TX_MTU=247 -CONFIG_BT_BUF_ACL_RX_SIZE=251 -CONFIG_BT_BUF_ACL_TX_SIZE=251 -CONFIG_BT_RX_STACK_SIZE=1200 +CONFIG_BT_DEVICE_NAME="MatterZigbee" # Other settings -CONFIG_THREAD_NAME=n +CONFIG_THREAD_NAME=y CONFIG_MPU_STACK_GUARD=y -CONFIG_RESET_ON_FATAL_ERROR=y +CONFIG_RESET_ON_FATAL_ERROR=n -# Enable Factory Data feature -CONFIG_CHIP_FACTORY_DATA=y -CONFIG_CHIP_FACTORY_DATA_BUILD=y +# Reduce application size +CONFIG_USE_SEGGER_RTT=n -# Matter commissioning -CONFIG_CHIP_COMMISSIONABLE_DEVICE_TYPE=y -CONFIG_CHIP_DEVICE_TYPE=256 +# FIXME: Disabled Factory Data feature for initial development +CONFIG_CHIP_FACTORY_DATA_NONE=y -# Enable Matter OTA (aligned with Zigbee FOTA) -CONFIG_CHIP_OTA_REQUESTOR=y +# FIXME: Disabled Matter OTA for initial development +CONFIG_CHIP_OTA_REQUESTOR=n +CONFIG_CHIP_BOOTLOADER_MCUBOOT=n +CONFIG_CHIP_BOOTLOADER_NONE=y # Increase system workqueue stack for combined protocols (with Thread) -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 - -# Memory settings for Zigbee + Matter + Thread (PoC) -CONFIG_MAIN_STACK_SIZE=4096 -CONFIG_CHIP_MALLOC_SYS_HEAP=y -CONFIG_CHIP_MALLOC_SYS_HEAP_SIZE=32768 - -# Thread stack sizes -CONFIG_NET_TX_STACK_SIZE=1200 -CONFIG_NET_RX_STACK_SIZE=1500 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=6144 -# Crypto - PSA Crypto Backend -CONFIG_NORDIC_SECURITY_BACKEND=y -CONFIG_CHIP_CRYPTO_PSA=y +# Libc malloc arena required for Zigbee + Matter coexistence. +# - 0: no libc heap -> Matter init fails (malloc/calloc used during init). +# - -1: "all remaining RAM" -> on this build the computed heap extends past +# valid RAM and triggers a precise data bus fault in sys_heap_init(). +# - Positive value: static BSS heap of that size -> valid heap, no fault. +# Matter uses CHIP_MALLOC_SYS_HEAP for its own allocations; this arena +# covers libc malloc() used elsewhere (init, Zephyr, Zigbee, etc.). +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 -# Enable legacy mbedTLS crypto for Matter SPAKE2+ (requires mbedtls_ecp_muladd) -CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y -CONFIG_MBEDTLS_ECP_C=y - -# Storage - use ZMS for nRF54L (NVS not supported) -CONFIG_ZMS=y -CONFIG_SETTINGS=y -CONFIG_SETTINGS_ZMS=y -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y -CONFIG_MPU_ALLOW_FLASH_WRITE=y - -# Trusted storage backend for Matter PSA crypto keys -CONFIG_TRUSTED_STORAGE=y -CONFIG_TRUSTED_STORAGE_BACKEND_AEAD=y -CONFIG_TRUSTED_STORAGE_STORAGE_BACKEND_SETTINGS=y - -# Additional platform requirements for Matter -CONFIG_HWINFO=y -CONFIG_REBOOT=y -CONFIG_ENTROPY_GENERATOR=y +## PoC Configuration ## +# Note: This configuration links all three stacks (Zigbee, Thread, Matter) for memory estimation +# It will have runtime conflicts as Zigbee and Thread cannot share 802.15.4 radio simultaneously +# This is intentional - goal is to measure maximum memory footprint -# Matter thread requirements -CONFIG_SCHED_CPU_MASK=y +# Keep Matter shell disabled to avoid getopt conflicts +CONFIG_CHIP_LIB_SHELL=n +CONFIG_NCS_SAMPLE_MATTER_TEST_SHELL=n -# Watchdog -CONFIG_TASK_WDT=y +# Larger settings partition for Zigbee + Matter +CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000 -# Matter common infrastructure configs (needed even without Thread) +# Enable for OpenThread logging +# UNCOMENT TO SEE LOGS FROM OPENTHREAD +# CONFIG_LOG_MODE_DEFERRED=y +# CONFIG_OPENTHREAD_DEBUG=y +# CONFIG_OPENTHREAD_LOG_LEVEL_DEBG=y +# CONFIG_LOG_BUFFER_SIZE=81920 -# Enable BT GATT for Matter BLE commissioning -CONFIG_BT_GATT_DYNAMIC_DB=y -CONFIG_BT_GATT_SERVICE_CHANGED=y -CONFIG_BT_GATT_CACHING=y -CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n +# Dispatcher +CONFIG_NRF_802154_CALLBACKS_DISPATCHER=y +CONFIG_NRF_802154_DRV_REINIT_ENABLED=y +CONFIG_ZIGBEE_DEBUG_FUNCTIONS=y -## PoC Configuration ## -# Note: This configuration links all three stacks (Zigbee, Thread, Matter) for memory estimation -# It will have runtime conflicts as Zigbee and Thread cannot share 802.15.4 radio simultaneously -# This is intentional - goal is to measure maximum memory footprint +# Must be a preemptible priority (0–15), not cooperative (-1). With -1, ZBOSS is +# coop priority -1 and is outranked by MPSL Work (prio -8), so it never runs. +# State 128 = _THREAD_QUEUED (runnable); ZBOSS stays queued and never gets CPU. +CONFIG_ZBOSS_DEFAULT_THREAD_PRIORITY=1 +CONFIG_ZBOSS_DEFAULT_THREAD_STACK_SIZE=6144 # Keep Matter shell disabled to avoid getopt conflicts CONFIG_CHIP_LIB_SHELL=n diff --git a/samples/light_bulb/sample.yaml b/samples/light_bulb/sample.yaml index b1d593f2..6ca8a8f8 100644 --- a/samples/light_bulb/sample.yaml +++ b/samples/light_bulb/sample.yaml @@ -2,6 +2,20 @@ sample: description: Zigbee Light control - light bulb sample name: Zigbee Light control tests: + sample.zigbee.light_bulb.matter: + sysbuild: true + build_only: true + extra_args: + - FILE_SUFFIX=matter_fota + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + tags: + - ci_build + - smoke + - sysbuild + - ci_samples_zigbee sample.zigbee.light_bulb: sysbuild: true build_only: true diff --git a/samples/light_bulb/src/app_task_matter.cpp b/samples/light_bulb/src/app_task_matter.cpp new file mode 100644 index 00000000..cd67b805 --- /dev/null +++ b/samples/light_bulb/src/app_task_matter.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "app_task_matter.h" + +#include "app/matter_init.h" +#include "app/task_executor.h" + +#if defined(CONFIG_PWM) +#include "pwm/pwm_device.h" +#endif + +#include "clusters/identify.h" + +#include +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); + +using namespace ::chip; +using namespace ::chip::app; +using namespace ::chip::DeviceLayer; + +namespace { +constexpr EndpointId kLightEndpointId = 1; +constexpr uint8_t kDefaultMinLevel = 0; +constexpr uint8_t kDefaultMaxLevel = 254; + +Nrf::Matter::IdentifyCluster sIdentifyCluster(kLightEndpointId, true, []() { + Nrf::PostTask( + [] { Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).Set(false); }); +#if defined(CONFIG_PWM) + Nrf::PostTask([] { AppTask::Instance().GetPWMDevice().ApplyLevel(); }); +#endif +}); + +#if defined(CONFIG_PWM) +const struct pwm_dt_spec sLightPwmDevice = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led1)); +#endif + +/* Define a custom attribute persister which makes actual write of the + * CurrentLevel attribute value to the non-volatile storage only when it has + * remained constant for 5 seconds. This is to reduce the flash wearout when the + * attribute changes frequently as a result of MoveToLevel command. + * DeferredAttribute object describes a deferred attribute, but also holds a + * buffer with a value to be written, so it must live so long as the + * DeferredAttributePersistenceProvider object. + */ +DeferredAttribute gCurrentLevelPersister(ConcreteAttributePath( + kLightEndpointId, Clusters::LevelControl::Id, + Clusters::LevelControl::Attributes::CurrentLevel::Id)); + +/* Deferred persistence will be auto-initialized as soon as the default + * persistence is initialized */ +DefaultAttributePersistenceProvider gSimpleAttributePersistence; +DeferredAttributePersistenceProvider gDeferredAttributePersister( + gSimpleAttributePersistence, + Span(&gCurrentLevelPersister, 1), + System::Clock::Milliseconds32(5000)); + +#define APPLICATION_BUTTON_MASK DK_BTN2_MSK +} /* namespace */ + +void AppTask::LightingActionEventHandler(const LightingEvent &event) { +#if defined(CONFIG_PWM) + Nrf::PWMDevice::Action_t action = Nrf::PWMDevice::INVALID_ACTION; + int32_t actor = 0; + if (event.Actor == LightingActor::Button) { + action = Instance().mPWMDevice.IsTurnedOn() ? Nrf::PWMDevice::OFF_ACTION + : Nrf::PWMDevice::ON_ACTION; + actor = static_cast(event.Actor); + } + + if (action == Nrf::PWMDevice::INVALID_ACTION || + !Instance().mPWMDevice.InitiateAction(action, actor, NULL)) { + LOG_INF("An action could not be initiated."); + } +#else + Nrf::GetBoard() + .GetLED(Nrf::DeviceLeds::LED2) + .Set(!Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).GetState()); +#endif +} + +void AppTask::ButtonEventHandler(Nrf::ButtonState state, + Nrf::ButtonMask hasChanged) { + if ((APPLICATION_BUTTON_MASK & hasChanged) & state) { + Nrf::PostTask([] { + LightingEvent event; + event.Actor = LightingActor::Button; + LightingActionEventHandler(event); + }); + } +} + +#if defined(CONFIG_PWM) +void AppTask::ActionInitiated(Nrf::PWMDevice::Action_t action, int32_t actor) { + if (action == Nrf::PWMDevice::ON_ACTION) { + LOG_INF("Turn On Action has been initiated"); + } else if (action == Nrf::PWMDevice::OFF_ACTION) { + LOG_INF("Turn Off Action has been initiated"); + } else if (action == Nrf::PWMDevice::LEVEL_ACTION) { + LOG_INF("Level Action has been initiated"); + } +} + +void AppTask::ActionCompleted(Nrf::PWMDevice::Action_t action, int32_t actor) { + if (action == Nrf::PWMDevice::ON_ACTION) { + LOG_INF("Turn On Action has been completed"); + } else if (action == Nrf::PWMDevice::OFF_ACTION) { + LOG_INF("Turn Off Action has been completed"); + } else if (action == Nrf::PWMDevice::LEVEL_ACTION) { + LOG_INF("Level Action has been completed"); + } + + if (actor == static_cast(LightingActor::Button)) { + Instance().UpdateClusterState(); + } +} +#endif /* CONFIG_PWM */ + +void AppTask::UpdateClusterState() { + SystemLayer().ScheduleLambda([this] { +#if defined(CONFIG_PWM) + /* write the new on/off value */ + Protocols::InteractionModel::Status status = + Clusters::OnOff::Attributes::OnOff::Set(kLightEndpointId, + mPWMDevice.IsTurnedOn()); +#else + Protocols::InteractionModel::Status status = + Clusters::OnOff::Attributes::OnOff::Set( + kLightEndpointId, + Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).GetState()); +#endif + if (status != Protocols::InteractionModel::Status::Success) { + LOG_ERR("Updating on/off cluster failed: %x", to_underlying(status)); + } + +#if defined(CONFIG_PWM) + /* write the current level */ + status = Clusters::LevelControl::Attributes::CurrentLevel::Set( + kLightEndpointId, mPWMDevice.GetLevel()); +#else + /* write the current level */ + if (Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).GetState()) { + status = Clusters::LevelControl::Attributes::CurrentLevel::Set( + kLightEndpointId, 100); + } else { + status = Clusters::LevelControl::Attributes::CurrentLevel::Set( + kLightEndpointId, 0); + } +#endif + + if (status != Protocols::InteractionModel::Status::Success) { + LOG_ERR("Updating level cluster failed: %x", to_underlying(status)); + } + }); +} + +void AppTask::InitPWMDDevice() { +#if defined(CONFIG_PWM) + /* Initialize lighting device (PWM) */ + uint8_t minLightLevel = kDefaultMinLevel; + Clusters::LevelControl::Attributes::MinLevel::Get(kLightEndpointId, + &minLightLevel); + + uint8_t maxLightLevel = kDefaultMaxLevel; + Clusters::LevelControl::Attributes::MaxLevel::Get(kLightEndpointId, + &maxLightLevel); + + Clusters::LevelControl::Attributes::CurrentLevel::TypeInfo::Type currentLevel; + Clusters::LevelControl::Attributes::CurrentLevel::Get(kLightEndpointId, + currentLevel); + + int ret = mPWMDevice.Init(&sLightPwmDevice, minLightLevel, maxLightLevel, + currentLevel.ValueOr(kDefaultMaxLevel)); + if (ret != 0) { + LOG_ERR("Failed to initialize PWD device."); + } + + mPWMDevice.SetCallbacks(ActionInitiated, ActionCompleted); +#endif +} + +CHIP_ERROR AppTask::Init() { + /* Initialize Matter stack */ + ReturnErrorOnFailure(Nrf::Matter::PrepareServer( + Nrf::Matter::InitData{.mPostServerInitClbk = []() { + app::SetAttributePersistenceProvider(&gDeferredAttributePersister); + gSimpleAttributePersistence.Init( + Nrf::Matter::GetPersistentStorageDelegate()); + return CHIP_NO_ERROR; + }})); + + if (!Nrf::GetBoard().Init(ButtonEventHandler)) { + LOG_ERR("User interface initialization failed."); + return CHIP_ERROR_INCORRECT_STATE; + } + + /* Register Matter event handler that controls the connectivity status LED + * based on the captured Matter network state. */ + ReturnErrorOnFailure(Nrf::Matter::RegisterEventHandler( + Nrf::Board::DefaultMatterEventHandler, 0)); + + ReturnErrorOnFailure(sIdentifyCluster.Init()); + + return Nrf::Matter::StartServer(); +} + +CHIP_ERROR AppTask::StartApp() { + ReturnErrorOnFailure(Init()); + + while (true) { + Nrf::DispatchNextTask(); + } + + return CHIP_NO_ERROR; +} diff --git a/samples/light_bulb/src/app_task_zigbee.cpp b/samples/light_bulb/src/app_task_zigbee.cpp new file mode 100644 index 00000000..a232ae52 --- /dev/null +++ b/samples/light_bulb/src/app_task_zigbee.cpp @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/** @file + * + * @brief Simple Zigbee light bulb implementation. + */ + +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "zb_dimmable_light.h" +#include +#include +#include +#include +#include +#include +#include +#include +} + +#define RUN_STATUS_LED DK_LED1 +#define RUN_LED_BLINK_INTERVAL 1000 + +/* Device endpoint, used to receive light controlling commands. */ +#define DIMMABLE_LIGHT_ENDPOINT 10 + +/* Version of the application software (1 byte). */ +#define BULB_INIT_BASIC_APP_VERSION 01 + +/* Version of the implementation of the Zigbee stack (1 byte). */ +#define BULB_INIT_BASIC_STACK_VERSION 10 + +/* Version of the hardware of the device (1 byte). */ +#define BULB_INIT_BASIC_HW_VERSION 11 + +/* Manufacturer name (32 bytes). */ +#define BULB_INIT_BASIC_MANUF_NAME "Nordic" + +/* Model number assigned by manufacturer (32-bytes long string). */ +#define BULB_INIT_BASIC_MODEL_ID "Dimable_Light_v0.1" + +/* First 8 bytes specify the date of manufacturer of the device + * in ISO 8601 format (YYYYMMDD). The rest (8 bytes) are manufacturer specific. + */ +#define BULB_INIT_BASIC_DATE_CODE "20200329" + +/* Type of power sources available for the device. + * For possible values see section 3.2.2.2.8 of ZCL specification. + */ +#define BULB_INIT_BASIC_POWER_SOURCE ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE + +/* Describes the physical location of the device (16 bytes). + * May be modified during commissioning process. + */ +#define BULB_INIT_BASIC_LOCATION_DESC "Office desk" + +/* Describes the type of physical environment. + * For possible values see section 3.2.2.2.10 of ZCL specification. + */ +#define BULB_INIT_BASIC_PH_ENV ZB_ZCL_BASIC_ENV_UNSPECIFIED + +/* LED indicating that light switch successfully joind Zigbee network. */ +#define ZIGBEE_NETWORK_STATE_LED DK_LED3 + +/* LED immitaing dimmable light bulb - define for informational + * purposes only. + */ +#define BULB_LED DK_LED4 + +/* Button used to enter the Bulb into the Identify mode. */ +#define IDENTIFY_MODE_BUTTON DK_BTN4_MSK + +/* Use onboard led4 to act as a light bulb. + * The app.overlay file has this at node label "pwm_led3" in /pwmleds. + */ +#define PWM_DK_LED_NODE DT_NODELABEL(pwm_led3) + +#if DT_NODE_HAS_STATUS(PWM_DK_LED_NODE, okay) +static const struct pwm_dt_spec led_pwm = PWM_DT_SPEC_GET(PWM_DK_LED_NODE); +#else +#error "Choose supported PWM driver" +#endif + +/* Led PWM period, calculated for 100 Hz signal - in microseconds. */ +#define LED_PWM_PERIOD_US (USEC_PER_SEC / 100U) + +#ifndef ZB_ROUTER_ROLE +#error Define ZB_ROUTER_ROLE to compile router source code. +#endif + +/* Button to start Factory Reset */ +#define FACTORY_RESET_BUTTON IDENTIFY_MODE_BUTTON + +LOG_MODULE_REGISTER(app, LOG_LEVEL_INF); + +/* Main application customizable context. + * Stores all settings and static values. + */ +typedef struct { + zb_zcl_basic_attrs_ext_t basic_attr; + zb_zcl_identify_attrs_t identify_attr; + zb_zcl_scenes_attrs_t scenes_attr; + zb_zcl_groups_attrs_t groups_attr; + zb_zcl_on_off_attrs_t on_off_attr; + zb_zcl_level_control_attrs_t level_control_attr; +} bulb_device_ctx_t; + +/* Zigbee device application context storage. */ +static bulb_device_ctx_t dev_ctx; + +ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(identify_attr_list, + &dev_ctx.identify_attr.identify_time); + +ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(groups_attr_list, + &dev_ctx.groups_attr.name_support); + +ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST(scenes_attr_list, + &dev_ctx.scenes_attr.scene_count, + &dev_ctx.scenes_attr.current_scene, + &dev_ctx.scenes_attr.current_group, + &dev_ctx.scenes_attr.scene_valid, + &dev_ctx.scenes_attr.name_support); + +ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT( + basic_attr_list, &dev_ctx.basic_attr.zcl_version, + &dev_ctx.basic_attr.app_version, &dev_ctx.basic_attr.stack_version, + &dev_ctx.basic_attr.hw_version, dev_ctx.basic_attr.mf_name, + dev_ctx.basic_attr.model_id, dev_ctx.basic_attr.date_code, + &dev_ctx.basic_attr.power_source, dev_ctx.basic_attr.location_id, + &dev_ctx.basic_attr.ph_env, dev_ctx.basic_attr.sw_ver); + +/* On/Off cluster attributes additions data */ +ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST(on_off_attr_list, + &dev_ctx.on_off_attr.on_off); + +ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST( + level_control_attr_list, &dev_ctx.level_control_attr.current_level, + &dev_ctx.level_control_attr.remaining_time); + +ZB_DECLARE_DIMMABLE_LIGHT_CLUSTER_LIST(dimmable_light_clusters, basic_attr_list, + identify_attr_list, groups_attr_list, + scenes_attr_list, on_off_attr_list, + level_control_attr_list); + +ZB_DECLARE_DIMMABLE_LIGHT_EP(dimmable_light_ep, DIMMABLE_LIGHT_ENDPOINT, + dimmable_light_clusters); + +ZBOSS_DECLARE_DEVICE_CTX_1_EP(dimmable_light_ctx, dimmable_light_ep); + +/**@brief Starts identifying the device. + * + * @param bufid Unused parameter, required by ZBOSS scheduler API. + */ +static void start_identifying(zb_bufid_t bufid) { + ZVUNUSED(bufid); + + if (ZB_JOINED()) { + /* Check if endpoint is in identifying mode, + * if not, put desired endpoint in identifying mode. + */ + if (dev_ctx.identify_attr.identify_time == + ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE) { + + zb_ret_t zb_err_code = + zb_bdb_finding_binding_target(DIMMABLE_LIGHT_ENDPOINT); + + if (zb_err_code == RET_OK) { + LOG_INF("Enter identify mode"); + } else if (zb_err_code == RET_INVALID_STATE) { + LOG_WRN("RET_INVALID_STATE - Cannot enter identify mode"); + } else { + ZB_ERROR_CHECK(zb_err_code); + } + } else { + LOG_INF("Cancel identify mode"); + zb_bdb_finding_binding_target_cancel(); + } + } else { + LOG_WRN("Device not in a network - cannot enter identify mode"); + } +} + +#ifndef CONFIG_CHIP +/**@brief Callback for button events. + * + * @param[in] button_state Bitmask containing the state of the buttons. + * @param[in] has_changed Bitmask containing buttons that have changed their + * state. + */ +static void button_changed(uint32_t button_state, uint32_t has_changed) { + if (IDENTIFY_MODE_BUTTON & has_changed) { + if (IDENTIFY_MODE_BUTTON & button_state) { + /* Button changed its state to pressed */ + } else { + /* Button changed its state to released */ + if (was_factory_reset_done()) { + /* The long press was for Factory Reset */ + LOG_DBG("After Factory Reset - ignore button release"); + } else { + /* Button released before Factory Reset */ + + /* Start identification mode */ + ZB_SCHEDULE_APP_CALLBACK(start_identifying, 0); + } + } + } + + check_factory_reset_button(button_state, has_changed); +} + +/**@brief Function for initializing additional PWM leds. */ +static void pwm_led_init(void) { + if (!device_is_ready(led_pwm.dev)) { + LOG_ERR("Error: PWM device %s is not ready", led_pwm.dev->name); + } +} + +/**@brief Function for initializing LEDs and Buttons. */ +static void configure_gpio(void) { + int err; + + err = dk_buttons_init(button_changed); + if (err) { + LOG_ERR("Cannot init buttons (err: %d)", err); + } + + err = dk_leds_init(); + if (err) { + LOG_ERR("Cannot init LEDs (err: %d)", err); + } + + pwm_led_init(); +} +#endif /* CONFIG_CHIP */ + +/**@brief Sets brightness of bulb luminous executive element + * + * @param[in] brightness_level Brightness level, allowed values 0 ... 255, + * 0 - turn off, 255 - full brightness. + */ +static void light_bulb_set_brightness(zb_uint8_t brightness_level) { + uint32_t pulse = brightness_level * LED_PWM_PERIOD_US / 255U; + + if (pwm_set_dt(&led_pwm, PWM_USEC(LED_PWM_PERIOD_US), PWM_USEC(pulse))) { + LOG_ERR("Pwm led 4 set fails:\n"); + return; + } +} + +/**@brief Function for setting the light bulb brightness. + * + * @param[in] new_level Light bulb brightness value. + */ +static void level_control_set_value(zb_uint16_t new_level) { + LOG_INF("Set level value: %i", new_level); + + ZB_ZCL_SET_ATTRIBUTE(DIMMABLE_LIGHT_ENDPOINT, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, + ZB_ZCL_CLUSTER_SERVER_ROLE, + ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, + (zb_uint8_t *)&new_level, ZB_FALSE); + + light_bulb_set_brightness(new_level); +} + +/**@brief Function for turning ON/OFF the light bulb. + * + * @param[in] on Boolean light bulb state. + */ +static void on_off_set_value(zb_bool_t on) { + LOG_INF("Set ON/OFF value: %i", on); + + ZB_ZCL_SET_ATTRIBUTE(DIMMABLE_LIGHT_ENDPOINT, ZB_ZCL_CLUSTER_ID_ON_OFF, + ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, + (zb_uint8_t *)&on, ZB_FALSE); + + if (on) { + light_bulb_set_brightness(dev_ctx.level_control_attr.current_level); + } else { + light_bulb_set_brightness(0U); + } +} + +/**@brief Function to toggle the identify LED - BULB_LED is used for this. + * + * @param bufid Unused parameter, required by ZBOSS scheduler API. + */ +static void toggle_identify_led(zb_bufid_t bufid) { + static int blink_status; + + light_bulb_set_brightness(((++blink_status) % 2) ? (255U) : (0U)); + ZB_SCHEDULE_APP_ALARM(toggle_identify_led, bufid, + ZB_MILLISECONDS_TO_BEACON_INTERVAL(100)); +} + +/**@brief Function to handle identify notification events on the first endpoint. + * + * @param bufid Unused parameter, required by ZBOSS scheduler API. + */ +static void identify_cb(zb_bufid_t bufid) { + zb_ret_t zb_err_code; + + if (bufid) { + /* Schedule a self-scheduling function that will toggle the LED. */ + ZB_SCHEDULE_APP_CALLBACK(toggle_identify_led, bufid); + } else { + /* Cancel the toggling function alarm and restore current Zigbee LED state. + */ + zb_err_code = + ZB_SCHEDULE_APP_ALARM_CANCEL(toggle_identify_led, ZB_ALARM_ANY_PARAM); + ZVUNUSED(zb_err_code); + + if (dev_ctx.on_off_attr.on_off) { + light_bulb_set_brightness(dev_ctx.level_control_attr.current_level); + } else { + light_bulb_set_brightness(0U); + } + } +} + +/**@brief Function for initializing all clusters attributes. + */ +static void bulb_clusters_attr_init(void) { + /* Basic cluster attributes data */ + dev_ctx.basic_attr.zcl_version = ZB_ZCL_VERSION; + dev_ctx.basic_attr.app_version = BULB_INIT_BASIC_APP_VERSION; + dev_ctx.basic_attr.stack_version = BULB_INIT_BASIC_STACK_VERSION; + dev_ctx.basic_attr.hw_version = BULB_INIT_BASIC_HW_VERSION; + + /* Use ZB_ZCL_SET_STRING_VAL to set strings, because the first byte + * should contain string length without trailing zero. + * + * For example "test" string will be encoded as: + * [(0x4), 't', 'e', 's', 't'] + */ + ZB_ZCL_SET_STRING_VAL(dev_ctx.basic_attr.mf_name, BULB_INIT_BASIC_MANUF_NAME, + ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MANUF_NAME)); + + ZB_ZCL_SET_STRING_VAL(dev_ctx.basic_attr.model_id, BULB_INIT_BASIC_MODEL_ID, + ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MODEL_ID)); + + ZB_ZCL_SET_STRING_VAL(dev_ctx.basic_attr.date_code, BULB_INIT_BASIC_DATE_CODE, + ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_DATE_CODE)); + + dev_ctx.basic_attr.power_source = BULB_INIT_BASIC_POWER_SOURCE; + + ZB_ZCL_SET_STRING_VAL( + dev_ctx.basic_attr.location_id, BULB_INIT_BASIC_LOCATION_DESC, + ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_LOCATION_DESC)); + + dev_ctx.basic_attr.ph_env = BULB_INIT_BASIC_PH_ENV; + + /* Identify cluster attributes data. */ + dev_ctx.identify_attr.identify_time = + ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE; + + /* On/Off cluster attributes data. */ + dev_ctx.on_off_attr.on_off = (zb_bool_t)ZB_ZCL_ON_OFF_IS_ON; + + dev_ctx.level_control_attr.current_level = + ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE; + dev_ctx.level_control_attr.remaining_time = + ZB_ZCL_LEVEL_CONTROL_REMAINING_TIME_DEFAULT_VALUE; + + ZB_ZCL_SET_ATTRIBUTE(DIMMABLE_LIGHT_ENDPOINT, ZB_ZCL_CLUSTER_ID_ON_OFF, + ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, + (zb_uint8_t *)&dev_ctx.on_off_attr.on_off, ZB_FALSE); + + ZB_ZCL_SET_ATTRIBUTE( + DIMMABLE_LIGHT_ENDPOINT, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, + ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, + (zb_uint8_t *)&dev_ctx.level_control_attr.current_level, ZB_FALSE); +} + +/**@brief Callback function for handling ZCL commands. + * + * @param[in] bufid Reference to Zigbee stack buffer + * used to pass received data. + */ +static void zcl_device_cb(zb_bufid_t bufid) { + zb_uint8_t cluster_id; + zb_uint8_t attr_id; + zb_zcl_device_callback_param_t *device_cb_param = + ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t); + + LOG_INF("%s id %hd", __func__, device_cb_param->device_cb_id); + + /* Set default response value. */ + device_cb_param->status = RET_OK; + + switch (device_cb_param->device_cb_id) { + case ZB_ZCL_LEVEL_CONTROL_SET_VALUE_CB_ID: + LOG_INF("Level control setting to %d", + device_cb_param->cb_param.level_control_set_value_param.new_value); + level_control_set_value( + device_cb_param->cb_param.level_control_set_value_param.new_value); + break; + + case ZB_ZCL_SET_ATTR_VALUE_CB_ID: + cluster_id = device_cb_param->cb_param.set_attr_value_param.cluster_id; + attr_id = device_cb_param->cb_param.set_attr_value_param.attr_id; + + if (cluster_id == ZB_ZCL_CLUSTER_ID_ON_OFF) { + uint8_t value = + device_cb_param->cb_param.set_attr_value_param.values.data8; + + LOG_INF("on/off attribute setting to %hd", value); + if (attr_id == ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID) { + on_off_set_value((zb_bool_t)value); + } + } else if (cluster_id == ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { + uint16_t value = + device_cb_param->cb_param.set_attr_value_param.values.data16; + + LOG_INF("level control attribute setting to %hd", value); + if (attr_id == ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID) { + level_control_set_value(value); + } + } else { + /* Other clusters can be processed here */ + LOG_INF("Unhandled cluster attribute id: %d", cluster_id); + device_cb_param->status = RET_NOT_IMPLEMENTED; + } + break; + + default: + if (zcl_scenes_cb(bufid) == ZB_FALSE) { + device_cb_param->status = RET_NOT_IMPLEMENTED; + } + break; + } + + LOG_INF("%s status: %hd", __func__, device_cb_param->status); +} + +/**@brief Zigbee stack event handler. + * + * @param[in] bufid Reference to the Zigbee stack buffer + * used to pass signal. + */ +void zboss_signal_handler(zb_bufid_t bufid) { + /* Update network status LED. */ + zigbee_led_status_update(bufid, ZIGBEE_NETWORK_STATE_LED); + + /* No application-specific behavior is required. + * Call default signal handler. + */ + ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid)); + + /* All callbacks should either reuse or free passed buffers. + * If bufid == 0, the buffer is invalid (not passed). + */ + if (bufid) { + zb_buf_free(bufid); + } +} + +int ZigbeeStart(void) { + int blink_status = 0; + int err; + + LOG_INF("Starting Zigbee R23 Light Bulb example"); + + /* Initialize Buttons and Leds only if not using Matter */ +#ifndef CONFIG_CHIP + configure_gpio(); + err = settings_subsys_init(); + if (err) { + LOG_ERR("settings initialization failed"); + } + register_factory_reset_button(FACTORY_RESET_BUTTON); + +#endif /* CONFIG_CHIP */ + + /* Register callback for handling ZCL commands. */ + ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb); + + /* Register dimmer switch device context (endpoints). */ + ZB_AF_REGISTER_DEVICE_CTX(&dimmable_light_ctx); + + bulb_clusters_attr_init(); + level_control_set_value(dev_ctx.level_control_attr.current_level); + + /* Register handler to identify notifications. */ + ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(DIMMABLE_LIGHT_ENDPOINT, identify_cb); + + /* Initialize ZCL scene table */ + zcl_scenes_init(); + + /* Settings should be loaded after zcl_scenes_init */ + err = settings_load(); + if (err) { + LOG_ERR("settings loading failed"); + } + + /* Start Zigbee default thread */ + zigbee_enable(); + + LOG_INF("Zigbee R23 Light Bulb example started"); + + while (1) { + dk_set_led(RUN_STATUS_LED, (++blink_status) % 2); + k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL)); + } +} diff --git a/samples/light_bulb/src/main.c b/samples/light_bulb/src/main.c deleted file mode 100644 index 8de72e6e..00000000 --- a/samples/light_bulb/src/main.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/** @file - * - * @brief Simple Zigbee light bulb implementation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "zb_dimmable_light.h" - -#define RUN_STATUS_LED DK_LED1 -#define RUN_LED_BLINK_INTERVAL 1000 - -/* Device endpoint, used to receive light controlling commands. */ -#define DIMMABLE_LIGHT_ENDPOINT 10 - -/* Version of the application software (1 byte). */ -#define BULB_INIT_BASIC_APP_VERSION 01 - -/* Version of the implementation of the Zigbee stack (1 byte). */ -#define BULB_INIT_BASIC_STACK_VERSION 10 - -/* Version of the hardware of the device (1 byte). */ -#define BULB_INIT_BASIC_HW_VERSION 11 - -/* Manufacturer name (32 bytes). */ -#define BULB_INIT_BASIC_MANUF_NAME "Nordic" - -/* Model number assigned by manufacturer (32-bytes long string). */ -#define BULB_INIT_BASIC_MODEL_ID "Dimable_Light_v0.1" - -/* First 8 bytes specify the date of manufacturer of the device - * in ISO 8601 format (YYYYMMDD). The rest (8 bytes) are manufacturer specific. - */ -#define BULB_INIT_BASIC_DATE_CODE "20200329" - -/* Type of power sources available for the device. - * For possible values see section 3.2.2.2.8 of ZCL specification. - */ -#define BULB_INIT_BASIC_POWER_SOURCE ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE - -/* Describes the physical location of the device (16 bytes). - * May be modified during commissioning process. - */ -#define BULB_INIT_BASIC_LOCATION_DESC "Office desk" - -/* Describes the type of physical environment. - * For possible values see section 3.2.2.2.10 of ZCL specification. - */ -#define BULB_INIT_BASIC_PH_ENV ZB_ZCL_BASIC_ENV_UNSPECIFIED - -/* LED indicating that light switch successfully joind Zigbee network. */ -#define ZIGBEE_NETWORK_STATE_LED DK_LED3 - -/* LED immitaing dimmable light bulb - define for informational - * purposes only. - */ -#define BULB_LED DK_LED4 - -/* Button used to enter the Bulb into the Identify mode. */ -#define IDENTIFY_MODE_BUTTON DK_BTN4_MSK - -/* Use onboard led4 to act as a light bulb. - * The app.overlay file has this at node label "pwm_led3" in /pwmleds. - */ -#define PWM_DK_LED_NODE DT_NODELABEL(pwm_led3) - -#if DT_NODE_HAS_STATUS(PWM_DK_LED_NODE, okay) -static const struct pwm_dt_spec led_pwm = PWM_DT_SPEC_GET(PWM_DK_LED_NODE); -#else -#error "Choose supported PWM driver" -#endif - -/* Led PWM period, calculated for 100 Hz signal - in microseconds. */ -#define LED_PWM_PERIOD_US (USEC_PER_SEC / 100U) - -#ifndef ZB_ROUTER_ROLE -#error Define ZB_ROUTER_ROLE to compile router source code. -#endif - -/* Button to start Factory Reset */ -#define FACTORY_RESET_BUTTON IDENTIFY_MODE_BUTTON - -LOG_MODULE_REGISTER(app, LOG_LEVEL_INF); - -/* Main application customizable context. - * Stores all settings and static values. - */ -typedef struct { - zb_zcl_basic_attrs_ext_t basic_attr; - zb_zcl_identify_attrs_t identify_attr; - zb_zcl_scenes_attrs_t scenes_attr; - zb_zcl_groups_attrs_t groups_attr; - zb_zcl_on_off_attrs_t on_off_attr; - zb_zcl_level_control_attrs_t level_control_attr; -} bulb_device_ctx_t; - -/* Zigbee device application context storage. */ -static bulb_device_ctx_t dev_ctx; - -ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST( - identify_attr_list, - &dev_ctx.identify_attr.identify_time); - -ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST( - groups_attr_list, - &dev_ctx.groups_attr.name_support); - -ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST( - scenes_attr_list, - &dev_ctx.scenes_attr.scene_count, - &dev_ctx.scenes_attr.current_scene, - &dev_ctx.scenes_attr.current_group, - &dev_ctx.scenes_attr.scene_valid, - &dev_ctx.scenes_attr.name_support); - -ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT( - basic_attr_list, - &dev_ctx.basic_attr.zcl_version, - &dev_ctx.basic_attr.app_version, - &dev_ctx.basic_attr.stack_version, - &dev_ctx.basic_attr.hw_version, - dev_ctx.basic_attr.mf_name, - dev_ctx.basic_attr.model_id, - dev_ctx.basic_attr.date_code, - &dev_ctx.basic_attr.power_source, - dev_ctx.basic_attr.location_id, - &dev_ctx.basic_attr.ph_env, - dev_ctx.basic_attr.sw_ver); - -/* On/Off cluster attributes additions data */ -ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST( - on_off_attr_list, - &dev_ctx.on_off_attr.on_off); - -ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST( - level_control_attr_list, - &dev_ctx.level_control_attr.current_level, - &dev_ctx.level_control_attr.remaining_time); - -ZB_DECLARE_DIMMABLE_LIGHT_CLUSTER_LIST( - dimmable_light_clusters, - basic_attr_list, - identify_attr_list, - groups_attr_list, - scenes_attr_list, - on_off_attr_list, - level_control_attr_list); - - -ZB_DECLARE_DIMMABLE_LIGHT_EP( - dimmable_light_ep, - DIMMABLE_LIGHT_ENDPOINT, - dimmable_light_clusters); - -ZBOSS_DECLARE_DEVICE_CTX_1_EP( - dimmable_light_ctx, - dimmable_light_ep); - -/**@brief Starts identifying the device. - * - * @param bufid Unused parameter, required by ZBOSS scheduler API. - */ -static void start_identifying(zb_bufid_t bufid) -{ - ZVUNUSED(bufid); - - if (ZB_JOINED()) { - /* Check if endpoint is in identifying mode, - * if not, put desired endpoint in identifying mode. - */ - if (dev_ctx.identify_attr.identify_time == - ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE) { - - zb_ret_t zb_err_code = zb_bdb_finding_binding_target( - DIMMABLE_LIGHT_ENDPOINT); - - if (zb_err_code == RET_OK) { - LOG_INF("Enter identify mode"); - } else if (zb_err_code == RET_INVALID_STATE) { - LOG_WRN("RET_INVALID_STATE - Cannot enter identify mode"); - } else { - ZB_ERROR_CHECK(zb_err_code); - } - } else { - LOG_INF("Cancel identify mode"); - zb_bdb_finding_binding_target_cancel(); - } - } else { - LOG_WRN("Device not in a network - cannot enter identify mode"); - } -} - -/**@brief Callback for button events. - * - * @param[in] button_state Bitmask containing the state of the buttons. - * @param[in] has_changed Bitmask containing buttons that have changed their state. - */ -static void button_changed(uint32_t button_state, uint32_t has_changed) -{ - if (IDENTIFY_MODE_BUTTON & has_changed) { - if (IDENTIFY_MODE_BUTTON & button_state) { - /* Button changed its state to pressed */ - } else { - /* Button changed its state to released */ - if (was_factory_reset_done()) { - /* The long press was for Factory Reset */ - LOG_DBG("After Factory Reset - ignore button release"); - } else { - /* Button released before Factory Reset */ - - /* Start identification mode */ - ZB_SCHEDULE_APP_CALLBACK(start_identifying, 0); - } - } - } - - check_factory_reset_button(button_state, has_changed); -} - -/**@brief Function for initializing additional PWM leds. */ -static void pwm_led_init(void) -{ - if (!device_is_ready(led_pwm.dev)) { - LOG_ERR("Error: PWM device %s is not ready", - led_pwm.dev->name); - } -} - -/**@brief Function for initializing LEDs and Buttons. */ -static void configure_gpio(void) -{ - int err; - - err = dk_buttons_init(button_changed); - if (err) { - LOG_ERR("Cannot init buttons (err: %d)", err); - } - - err = dk_leds_init(); - if (err) { - LOG_ERR("Cannot init LEDs (err: %d)", err); - } - - pwm_led_init(); -} - -/**@brief Sets brightness of bulb luminous executive element - * - * @param[in] brightness_level Brightness level, allowed values 0 ... 255, - * 0 - turn off, 255 - full brightness. - */ -static void light_bulb_set_brightness(zb_uint8_t brightness_level) -{ - uint32_t pulse = brightness_level * LED_PWM_PERIOD_US / 255U; - - if (pwm_set_dt(&led_pwm, PWM_USEC(LED_PWM_PERIOD_US), PWM_USEC(pulse))) { - LOG_ERR("Pwm led 4 set fails:\n"); - return; - } -} - -/**@brief Function for setting the light bulb brightness. - * - * @param[in] new_level Light bulb brightness value. - */ -static void level_control_set_value(zb_uint16_t new_level) -{ - LOG_INF("Set level value: %i", new_level); - - ZB_ZCL_SET_ATTRIBUTE( - DIMMABLE_LIGHT_ENDPOINT, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, - (zb_uint8_t *)&new_level, - ZB_FALSE); - - light_bulb_set_brightness(new_level); -} - -/**@brief Function for turning ON/OFF the light bulb. - * - * @param[in] on Boolean light bulb state. - */ -static void on_off_set_value(zb_bool_t on) -{ - LOG_INF("Set ON/OFF value: %i", on); - - ZB_ZCL_SET_ATTRIBUTE( - DIMMABLE_LIGHT_ENDPOINT, - ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, - (zb_uint8_t *)&on, - ZB_FALSE); - - if (on) { - light_bulb_set_brightness(dev_ctx.level_control_attr.current_level); - } else { - light_bulb_set_brightness(0U); - } -} - -/**@brief Function to toggle the identify LED - BULB_LED is used for this. - * - * @param bufid Unused parameter, required by ZBOSS scheduler API. - */ -static void toggle_identify_led(zb_bufid_t bufid) -{ - static int blink_status; - - light_bulb_set_brightness(((++blink_status) % 2) ? (255U) : (0U)); - ZB_SCHEDULE_APP_ALARM(toggle_identify_led, bufid, ZB_MILLISECONDS_TO_BEACON_INTERVAL(100)); -} - -/**@brief Function to handle identify notification events on the first endpoint. - * - * @param bufid Unused parameter, required by ZBOSS scheduler API. - */ -static void identify_cb(zb_bufid_t bufid) -{ - zb_ret_t zb_err_code; - - if (bufid) { - /* Schedule a self-scheduling function that will toggle the LED. */ - ZB_SCHEDULE_APP_CALLBACK(toggle_identify_led, bufid); - } else { - /* Cancel the toggling function alarm and restore current Zigbee LED state. */ - zb_err_code = ZB_SCHEDULE_APP_ALARM_CANCEL(toggle_identify_led, ZB_ALARM_ANY_PARAM); - ZVUNUSED(zb_err_code); - - if (dev_ctx.on_off_attr.on_off) { - light_bulb_set_brightness(dev_ctx.level_control_attr.current_level); - } else { - light_bulb_set_brightness(0U); - } - } -} - -/**@brief Function for initializing all clusters attributes. - */ -static void bulb_clusters_attr_init(void) -{ - /* Basic cluster attributes data */ - dev_ctx.basic_attr.zcl_version = ZB_ZCL_VERSION; - dev_ctx.basic_attr.app_version = BULB_INIT_BASIC_APP_VERSION; - dev_ctx.basic_attr.stack_version = BULB_INIT_BASIC_STACK_VERSION; - dev_ctx.basic_attr.hw_version = BULB_INIT_BASIC_HW_VERSION; - - /* Use ZB_ZCL_SET_STRING_VAL to set strings, because the first byte - * should contain string length without trailing zero. - * - * For example "test" string will be encoded as: - * [(0x4), 't', 'e', 's', 't'] - */ - ZB_ZCL_SET_STRING_VAL( - dev_ctx.basic_attr.mf_name, - BULB_INIT_BASIC_MANUF_NAME, - ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MANUF_NAME)); - - ZB_ZCL_SET_STRING_VAL( - dev_ctx.basic_attr.model_id, - BULB_INIT_BASIC_MODEL_ID, - ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MODEL_ID)); - - ZB_ZCL_SET_STRING_VAL( - dev_ctx.basic_attr.date_code, - BULB_INIT_BASIC_DATE_CODE, - ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_DATE_CODE)); - - dev_ctx.basic_attr.power_source = BULB_INIT_BASIC_POWER_SOURCE; - - ZB_ZCL_SET_STRING_VAL( - dev_ctx.basic_attr.location_id, - BULB_INIT_BASIC_LOCATION_DESC, - ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_LOCATION_DESC)); - - dev_ctx.basic_attr.ph_env = BULB_INIT_BASIC_PH_ENV; - - /* Identify cluster attributes data. */ - dev_ctx.identify_attr.identify_time = - ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE; - - /* On/Off cluster attributes data. */ - dev_ctx.on_off_attr.on_off = (zb_bool_t)ZB_ZCL_ON_OFF_IS_ON; - - dev_ctx.level_control_attr.current_level = - ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE; - dev_ctx.level_control_attr.remaining_time = - ZB_ZCL_LEVEL_CONTROL_REMAINING_TIME_DEFAULT_VALUE; - - ZB_ZCL_SET_ATTRIBUTE( - DIMMABLE_LIGHT_ENDPOINT, - ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, - (zb_uint8_t *)&dev_ctx.on_off_attr.on_off, - ZB_FALSE); - - ZB_ZCL_SET_ATTRIBUTE( - DIMMABLE_LIGHT_ENDPOINT, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, - (zb_uint8_t *)&dev_ctx.level_control_attr.current_level, - ZB_FALSE); -} - -/**@brief Callback function for handling ZCL commands. - * - * @param[in] bufid Reference to Zigbee stack buffer - * used to pass received data. - */ -static void zcl_device_cb(zb_bufid_t bufid) -{ - zb_uint8_t cluster_id; - zb_uint8_t attr_id; - zb_zcl_device_callback_param_t *device_cb_param = - ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t); - - LOG_INF("%s id %hd", __func__, device_cb_param->device_cb_id); - - /* Set default response value. */ - device_cb_param->status = RET_OK; - - switch (device_cb_param->device_cb_id) { - case ZB_ZCL_LEVEL_CONTROL_SET_VALUE_CB_ID: - LOG_INF("Level control setting to %d", - device_cb_param->cb_param.level_control_set_value_param - .new_value); - level_control_set_value( - device_cb_param->cb_param.level_control_set_value_param - .new_value); - break; - - case ZB_ZCL_SET_ATTR_VALUE_CB_ID: - cluster_id = device_cb_param->cb_param. - set_attr_value_param.cluster_id; - attr_id = device_cb_param->cb_param. - set_attr_value_param.attr_id; - - if (cluster_id == ZB_ZCL_CLUSTER_ID_ON_OFF) { - uint8_t value = - device_cb_param->cb_param.set_attr_value_param - .values.data8; - - LOG_INF("on/off attribute setting to %hd", value); - if (attr_id == ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID) { - on_off_set_value((zb_bool_t)value); - } - } else if (cluster_id == ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { - uint16_t value = device_cb_param->cb_param. - set_attr_value_param.values.data16; - - LOG_INF("level control attribute setting to %hd", - value); - if (attr_id == - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID) { - level_control_set_value(value); - } - } else { - /* Other clusters can be processed here */ - LOG_INF("Unhandled cluster attribute id: %d", - cluster_id); - device_cb_param->status = RET_NOT_IMPLEMENTED; - } - break; - - default: - if (zcl_scenes_cb(bufid) == ZB_FALSE) { - device_cb_param->status = RET_NOT_IMPLEMENTED; - } - break; - } - - LOG_INF("%s status: %hd", __func__, device_cb_param->status); -} - -/**@brief Zigbee stack event handler. - * - * @param[in] bufid Reference to the Zigbee stack buffer - * used to pass signal. - */ -void zboss_signal_handler(zb_bufid_t bufid) -{ - /* Update network status LED. */ - zigbee_led_status_update(bufid, ZIGBEE_NETWORK_STATE_LED); - - /* No application-specific behavior is required. - * Call default signal handler. - */ - ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid)); - - /* All callbacks should either reuse or free passed buffers. - * If bufid == 0, the buffer is invalid (not passed). - */ - if (bufid) { - zb_buf_free(bufid); - } -} - -int main(void) -{ - int blink_status = 0; - int err; - - LOG_INF("Starting Zigbee R23 Light Bulb example"); - - /* Initialize */ - configure_gpio(); - err = settings_subsys_init(); - if (err) { - LOG_ERR("settings initialization failed"); - } - register_factory_reset_button(FACTORY_RESET_BUTTON); - - /* Register callback for handling ZCL commands. */ - ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb); - - /* Register dimmer switch device context (endpoints). */ - ZB_AF_REGISTER_DEVICE_CTX(&dimmable_light_ctx); - - bulb_clusters_attr_init(); - level_control_set_value(dev_ctx.level_control_attr.current_level); - - /* Register handler to identify notifications. */ - ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(DIMMABLE_LIGHT_ENDPOINT, identify_cb); - - /* Initialize ZCL scene table */ - zcl_scenes_init(); - - /* Settings should be loaded after zcl_scenes_init */ - err = settings_load(); - if (err) { - LOG_ERR("settings loading failed"); - } - - /* Start Zigbee default thread */ - zigbee_enable(); - - LOG_INF("Zigbee R23 Light Bulb example started"); - - while (1) { - dk_set_led(RUN_STATUS_LED, (++blink_status) % 2); - k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL)); - } -} diff --git a/samples/light_bulb/src/main.cpp b/samples/light_bulb/src/main.cpp new file mode 100644 index 00000000..df8b577c --- /dev/null +++ b/samples/light_bulb/src/main.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024-2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/** @file + * + * @brief Simple Matter + Zigbee light bulb implementation. + */ + +#include "app_task_zigbee.h" + +#ifdef CONFIG_CHIP + +#include "app_task_matter.h" +#include +#include +#include + +extern "C" { +#include +} + +#include + +LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL); + +/* Zephyr thread stack size and priority */ +#define ZIGBEE_THREAD_STACK_SIZE 2048 +#define ZIGBEE_THREAD_PRIORITY 3 +#define MATTER_THREAD_STACK_SIZE 3072 +#define MATTER_THREAD_PRIORITY 3 + +namespace +{ + +void zigbee_thread_fn() +{ + int ret = nrf_802154_callbacks_dispatcher_switch("zigbee"); + + __ASSERT(ret == 0, "Failed to switch 802.15.4 radio to Zigbee: %d", ret); + + ZigbeeStart(); +} +void matter_thread_fn() +{ + AppTask::Instance().StartApp(); +} + +K_THREAD_DEFINE(zigbee_thread_id, ZIGBEE_THREAD_STACK_SIZE, zigbee_thread_fn, + NULL, NULL, NULL, ZIGBEE_THREAD_PRIORITY, 0, 0); + +K_THREAD_DEFINE(matter_thread_id, MATTER_THREAD_STACK_SIZE, matter_thread_fn, + NULL, NULL, NULL, MATTER_THREAD_PRIORITY, 0, 0); + +void switch_to_thread_radio(void) +{ + k_thread_abort(zigbee_thread_id); + zigbee_deinit(); + int ret = nrf_802154_callbacks_dispatcher_switch("openthread"); + + __ASSERT(ret == 0, "Failed to switch 802.15.4 radio to Thread: %d", ret); +} + +void matter_zigbee_event_handler( + const chip::DeviceLayer::ChipDeviceEvent *event, intptr_t arg) +{ + switch (event->Type) { + case chip::DeviceLayer::DeviceEventType::kSecureSessionEstablished: + /* Switch to Thread Radio and disable Zigbee Stack*/ + if (!chip::DeviceLayer::ThreadStackMgr().IsThreadAttached()) { + switch_to_thread_radio(); + } + break; + case chip::DeviceLayer::DeviceEventType::kFactoryReset: + /* Remove also the zigbee stack data */ + zigbee_pibcache_pan_id_clear(); +#ifdef ZB_USE_NVRAM + zb_nvram_erase(); +#endif + break; + default: + break; + } +} +} // namespace + +#endif /* CONFIG_CHIP */ + +int main(void) +{ + +#ifdef CONFIG_CHIP + + Nrf::Matter::RegisterEventHandler(matter_zigbee_event_handler, 0); + + k_thread_start(zigbee_thread_id); + k_thread_start(matter_thread_id); + +#else + + ZigbeeStart(); + +#endif + + return 0; +} diff --git a/samples/light_bulb/src/main_matter.c b/samples/light_bulb/src/main_matter.c deleted file mode 100644 index 6973d723..00000000 --- a/samples/light_bulb/src/main_matter.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Copyright (c) 2026 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/** @file - * - * @brief Combined Zigbee + Matter light bulb implementation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "zb_dimmable_light.h" - -#ifdef CONFIG_CHIP -#include "matter_init.h" -#endif - -#define RUN_STATUS_LED DK_LED1 -#define RUN_LED_BLINK_INTERVAL 1000 - -/* Device endpoint, used to receive light controlling commands. */ -#define DIMMABLE_LIGHT_ENDPOINT 10 - -/* Version of the application software (1 byte). */ -#define BULB_INIT_BASIC_APP_VERSION 01 - -/* Version of the implementation of the Zigbee stack (1 byte). */ -#define BULB_INIT_BASIC_STACK_VERSION 10 - -/* Version of the hardware of the device (1 byte). */ -#define BULB_INIT_BASIC_HW_VERSION 11 - -/* Manufacturer name (32 bytes). */ -#define BULB_INIT_BASIC_MANUF_NAME "Nordic" - -/* Model number assigned by manufacturer (32-bytes long string). */ -#define BULB_INIT_BASIC_MODEL_ID "Zigbee_Matter_Light" - -/* First 8 bytes specify the date of manufacturer of the device - * in ISO 8601 format (YYYYMMDD). The rest (8 bytes) are manufacturer specific. - */ -#define BULB_INIT_BASIC_DATE_CODE "20240101" - -/* Type of power sources available for the device. - * For possible values see section 3.2.2.2.8 of ZCL specification. - */ -#define BULB_INIT_BASIC_POWER_SOURCE ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE - -/* Describes the physical location of the device (16 bytes). - * May be modified during commissioning process. - */ -#define BULB_INIT_BASIC_LOCATION_DESC "Office desk" - -/* Describes the type of physical environment. - * For possible values see section 3.2.2.2.10 of ZCL specification. - */ -#define BULB_INIT_BASIC_PH_ENV ZB_ZCL_BASIC_ENV_UNSPECIFIED - -/* LED indicating that light switch successfully joind Zigbee network. */ -#define ZIGBEE_NETWORK_STATE_LED DK_LED3 - -/* LED immitaing dimmable light bulb - define for informational - * purposes only. - */ -#define BULB_LED DK_LED4 - -/* Button used to enter the Bulb into the Identify mode. */ -#define IDENTIFY_MODE_BUTTON DK_BTN4_MSK - -/* Use onboard led4 to act as a light bulb. - * The app.overlay file has this at node label "pwm_led3" in /pwmleds. - */ -#define PWM_DK_LED_NODE DT_NODELABEL(pwm_led3) - -#if DT_NODE_HAS_STATUS(PWM_DK_LED_NODE, okay) -static const struct pwm_dt_spec led_pwm = PWM_DT_SPEC_GET(PWM_DK_LED_NODE); -#else -#error "Choose supported PWM driver" -#endif - -/* Led PWM period, calculated for 100 Hz signal - in microseconds. */ -#define LED_PWM_PERIOD_US (USEC_PER_SEC / 100U) - -#ifndef ZB_ROUTER_ROLE -#error Define ZB_ROUTER_ROLE to compile router source code. -#endif - -/* Button to start Factory Reset */ -#define FACTORY_RESET_BUTTON IDENTIFY_MODE_BUTTON - -LOG_MODULE_REGISTER(app, LOG_LEVEL_INF); - -/* Main application customizable context. - * Stores all settings and static values. - */ -typedef struct { - zb_zcl_basic_attrs_ext_t basic_attr; - zb_zcl_identify_attrs_t identify_attr; - zb_zcl_scenes_attrs_t scenes_attr; - zb_zcl_groups_attrs_t groups_attr; - zb_zcl_on_off_attrs_t on_off_attr; - zb_zcl_level_control_attrs_t level_control_attr; -} bulb_device_ctx_t; - -/* Zigbee device application context storage. */ -static bulb_device_ctx_t dev_ctx; - -ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST( - identify_attr_list, - &dev_ctx.identify_attr.identify_time); - -ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST( - groups_attr_list, - &dev_ctx.groups_attr.name_support); - -ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST( - scenes_attr_list, - &dev_ctx.scenes_attr.scene_count, - &dev_ctx.scenes_attr.current_scene, - &dev_ctx.scenes_attr.current_group, - &dev_ctx.scenes_attr.scene_valid, - &dev_ctx.scenes_attr.name_support); - -ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT( - basic_attr_list, - &dev_ctx.basic_attr.zcl_version, - &dev_ctx.basic_attr.app_version, - &dev_ctx.basic_attr.stack_version, - &dev_ctx.basic_attr.hw_version, - dev_ctx.basic_attr.mf_name, - dev_ctx.basic_attr.model_id, - dev_ctx.basic_attr.date_code, - &dev_ctx.basic_attr.power_source, - dev_ctx.basic_attr.location_id, - &dev_ctx.basic_attr.ph_env, - dev_ctx.basic_attr.sw_ver); - -/* On/Off cluster attributes additions data */ -ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST( - on_off_attr_list, - &dev_ctx.on_off_attr.on_off); - -ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST( - level_control_attr_list, - &dev_ctx.level_control_attr.current_level, - &dev_ctx.level_control_attr.remaining_time); - -ZB_DECLARE_DIMMABLE_LIGHT_CLUSTER_LIST( - dimmable_light_clusters, - basic_attr_list, - identify_attr_list, - groups_attr_list, - scenes_attr_list, - on_off_attr_list, - level_control_attr_list); - - -ZB_DECLARE_DIMMABLE_LIGHT_EP( - dimmable_light_ep, - DIMMABLE_LIGHT_ENDPOINT, - dimmable_light_clusters); - -ZBOSS_DECLARE_DEVICE_CTX_1_EP( - dimmable_light_ctx, - dimmable_light_ep); - -/**@brief Starts identifying the device. - * - * @param bufid Unused parameter, required by ZBOSS scheduler API. - */ -static void start_identifying(zb_bufid_t bufid) -{ - ZVUNUSED(bufid); - - if (ZB_JOINED()) { - /* Check if endpoint is in identifying mode, - * if not, put desired endpoint in identifying mode. - */ - if (dev_ctx.identify_attr.identify_time == - ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE) { - - zb_ret_t zb_err_code = zb_bdb_finding_binding_target( - DIMMABLE_LIGHT_ENDPOINT); - - if (zb_err_code == RET_OK) { - LOG_INF("Enter identify mode"); - } else if (zb_err_code == RET_INVALID_STATE) { - LOG_WRN("RET_INVALID_STATE - Cannot enter identify mode"); - } else { - ZB_ERROR_CHECK(zb_err_code); - } - } else { - LOG_INF("Cancel identify mode"); - zb_bdb_finding_binding_target_cancel(); - } - } else { - LOG_WRN("Device not in a network - cannot enter identify mode"); - } -} - -/**@brief Callback for button events. - * - * @param[in] button_state Bitmask containing the state of the buttons. - * @param[in] has_changed Bitmask containing buttons that have changed their state. - */ -static void button_changed(uint32_t button_state, uint32_t has_changed) -{ - if (IDENTIFY_MODE_BUTTON & has_changed) { - if (IDENTIFY_MODE_BUTTON & button_state) { - /* Button changed its state to pressed */ - } else { - /* Button changed its state to released */ - if (was_factory_reset_done()) { - /* The long press was for Factory Reset */ - LOG_DBG("After Factory Reset - ignore button release"); - } else { - /* Button released before Factory Reset */ - - /* Start identification mode */ - ZB_SCHEDULE_APP_CALLBACK(start_identifying, 0); - } - } - } - - check_factory_reset_button(button_state, has_changed); -} - -/**@brief Function for initializing additional PWM leds. */ -static void pwm_led_init(void) -{ - if (!device_is_ready(led_pwm.dev)) { - LOG_ERR("Error: PWM device %s is not ready", - led_pwm.dev->name); - } -} - -/**@brief Function for initializing LEDs and Buttons. */ -static void configure_gpio(void) -{ - int err; - - err = dk_buttons_init(button_changed); - if (err) { - LOG_ERR("Cannot init buttons (err: %d)", err); - } - - err = dk_leds_init(); - if (err) { - LOG_ERR("Cannot init LEDs (err: %d)", err); - } - - pwm_led_init(); -} - -/**@brief Sets brightness of bulb luminous executive element - * - * @param[in] brightness_level Brightness level, allowed values 0 ... 255, - * 0 - turn off, 255 - full brightness. - */ -static void light_bulb_set_brightness(zb_uint8_t brightness_level) -{ - uint32_t pulse = brightness_level * LED_PWM_PERIOD_US / 255U; - - if (pwm_set_dt(&led_pwm, PWM_USEC(LED_PWM_PERIOD_US), PWM_USEC(pulse))) { - LOG_ERR("Pwm led 4 set fails:\n"); - return; - } -} - -/**@brief Function for setting the light bulb brightness. - * - * @param[in] new_level Light bulb brightness value. - */ -static void level_control_set_value(zb_uint16_t new_level) -{ - LOG_INF("Set level value: %i", new_level); - - ZB_ZCL_SET_ATTRIBUTE( - DIMMABLE_LIGHT_ENDPOINT, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, - (zb_uint8_t *)&new_level, - ZB_FALSE); - - light_bulb_set_brightness(new_level); - -#ifdef CONFIG_CHIP - /* Synchronize with Matter */ - matter_update_level((uint8_t)new_level); -#endif -} - -/**@brief Function for turning ON/OFF the light bulb. - * - * @param[in] on Boolean light bulb state. - */ -static void on_off_set_value(zb_bool_t on) -{ - LOG_INF("Set ON/OFF value: %i", on); - - ZB_ZCL_SET_ATTRIBUTE( - DIMMABLE_LIGHT_ENDPOINT, - ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, - (zb_uint8_t *)&on, - ZB_FALSE); - - if (on) { - light_bulb_set_brightness(dev_ctx.level_control_attr.current_level); - } else { - light_bulb_set_brightness(0U); - } - -#ifdef CONFIG_CHIP - /* Synchronize with Matter */ - matter_update_onoff((bool)on); -#endif -} - -/**@brief Function to toggle the identify LED - BULB_LED is used for this. - * - * @param bufid Unused parameter, required by ZBOSS scheduler API. - */ -static void toggle_identify_led(zb_bufid_t bufid) -{ - static int blink_status; - - light_bulb_set_brightness(((++blink_status) % 2) ? (255U) : (0U)); - ZB_SCHEDULE_APP_ALARM(toggle_identify_led, bufid, ZB_MILLISECONDS_TO_BEACON_INTERVAL(100)); -} - -/**@brief Function to handle identify notification events on the first endpoint. - * - * @param bufid Unused parameter, required by ZBOSS scheduler API. - */ -static void identify_cb(zb_bufid_t bufid) -{ - zb_ret_t zb_err_code; - - if (bufid) { - /* Schedule a self-scheduling function that will toggle the LED. */ - ZB_SCHEDULE_APP_CALLBACK(toggle_identify_led, bufid); - } else { - /* Cancel the toggling function alarm and restore current Zigbee LED state. */ - zb_err_code = ZB_SCHEDULE_APP_ALARM_CANCEL(toggle_identify_led, ZB_ALARM_ANY_PARAM); - ZVUNUSED(zb_err_code); - - if (dev_ctx.on_off_attr.on_off) { - light_bulb_set_brightness(dev_ctx.level_control_attr.current_level); - } else { - light_bulb_set_brightness(0U); - } - } -} - -/**@brief Function for initializing all clusters attributes. - */ -static void bulb_clusters_attr_init(void) -{ - /* Basic cluster attributes data */ - dev_ctx.basic_attr.zcl_version = ZB_ZCL_VERSION; - dev_ctx.basic_attr.app_version = BULB_INIT_BASIC_APP_VERSION; - dev_ctx.basic_attr.stack_version = BULB_INIT_BASIC_STACK_VERSION; - dev_ctx.basic_attr.hw_version = BULB_INIT_BASIC_HW_VERSION; - - /* Use ZB_ZCL_SET_STRING_VAL to set strings, because the first byte - * should contain string length without trailing zero. - * - * For example "test" string will be encoded as: - * [(0x4), 't', 'e', 's', 't'] - */ - ZB_ZCL_SET_STRING_VAL( - dev_ctx.basic_attr.mf_name, - BULB_INIT_BASIC_MANUF_NAME, - ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MANUF_NAME)); - - ZB_ZCL_SET_STRING_VAL( - dev_ctx.basic_attr.model_id, - BULB_INIT_BASIC_MODEL_ID, - ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MODEL_ID)); - - ZB_ZCL_SET_STRING_VAL( - dev_ctx.basic_attr.date_code, - BULB_INIT_BASIC_DATE_CODE, - ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_DATE_CODE)); - - dev_ctx.basic_attr.power_source = BULB_INIT_BASIC_POWER_SOURCE; - - ZB_ZCL_SET_STRING_VAL( - dev_ctx.basic_attr.location_id, - BULB_INIT_BASIC_LOCATION_DESC, - ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_LOCATION_DESC)); - - dev_ctx.basic_attr.ph_env = BULB_INIT_BASIC_PH_ENV; - - /* Identify cluster attributes data. */ - dev_ctx.identify_attr.identify_time = - ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE; - - /* On/Off cluster attributes data. */ - dev_ctx.on_off_attr.on_off = (zb_bool_t)ZB_ZCL_ON_OFF_IS_ON; - - dev_ctx.level_control_attr.current_level = - ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE; - dev_ctx.level_control_attr.remaining_time = - ZB_ZCL_LEVEL_CONTROL_REMAINING_TIME_DEFAULT_VALUE; - - ZB_ZCL_SET_ATTRIBUTE( - DIMMABLE_LIGHT_ENDPOINT, - ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, - (zb_uint8_t *)&dev_ctx.on_off_attr.on_off, - ZB_FALSE); - - ZB_ZCL_SET_ATTRIBUTE( - DIMMABLE_LIGHT_ENDPOINT, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, - (zb_uint8_t *)&dev_ctx.level_control_attr.current_level, - ZB_FALSE); -} - -/**@brief Callback function for handling ZCL commands. - * - * @param[in] bufid Reference to Zigbee stack buffer - * used to pass received data. - */ -static void zcl_device_cb(zb_bufid_t bufid) -{ - zb_uint8_t cluster_id; - zb_uint8_t attr_id; - zb_zcl_device_callback_param_t *device_cb_param = - ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t); - - LOG_INF("%s id %hd", __func__, device_cb_param->device_cb_id); - - /* Set default response value. */ - device_cb_param->status = RET_OK; - - switch (device_cb_param->device_cb_id) { - case ZB_ZCL_LEVEL_CONTROL_SET_VALUE_CB_ID: - LOG_INF("Level control setting to %d", - device_cb_param->cb_param.level_control_set_value_param - .new_value); - level_control_set_value( - device_cb_param->cb_param.level_control_set_value_param - .new_value); - break; - - case ZB_ZCL_SET_ATTR_VALUE_CB_ID: - cluster_id = device_cb_param->cb_param. - set_attr_value_param.cluster_id; - attr_id = device_cb_param->cb_param. - set_attr_value_param.attr_id; - - if (cluster_id == ZB_ZCL_CLUSTER_ID_ON_OFF) { - uint8_t value = - device_cb_param->cb_param.set_attr_value_param - .values.data8; - - LOG_INF("on/off attribute setting to %hd", value); - if (attr_id == ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID) { - on_off_set_value((zb_bool_t)value); - } - } else if (cluster_id == ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { - uint16_t value = device_cb_param->cb_param. - set_attr_value_param.values.data16; - - LOG_INF("level control attribute setting to %hd", - value); - if (attr_id == - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID) { - level_control_set_value(value); - } - } else { - /* Other clusters can be processed here */ - LOG_INF("Unhandled cluster attribute id: %d", - cluster_id); - device_cb_param->status = RET_NOT_IMPLEMENTED; - } - break; - - default: - if (zcl_scenes_cb(bufid) == ZB_FALSE) { - device_cb_param->status = RET_NOT_IMPLEMENTED; - } - break; - } - - LOG_INF("%s status: %hd", __func__, device_cb_param->status); -} - -/**@brief Zigbee stack event handler. - * - * @param[in] bufid Reference to the Zigbee stack buffer - * used to pass signal. - */ -void zboss_signal_handler(zb_bufid_t bufid) -{ - /* Update network status LED. */ - zigbee_led_status_update(bufid, ZIGBEE_NETWORK_STATE_LED); - - /* No application-specific behavior is required. - * Call default signal handler. - */ - ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid)); - - /* All callbacks should either reuse or free passed buffers. - * If bufid == 0, the buffer is invalid (not passed). - */ - if (bufid) { - zb_buf_free(bufid); - } -} - -int main(void) -{ - int blink_status = 0; - int err; - - LOG_INF("Starting Zigbee + Matter Light Bulb example"); - - /* Initialize GPIO for buttons and LEDs */ - configure_gpio(); - - /* Initialize settings subsystem */ - err = settings_subsys_init(); - if (err) { - LOG_ERR("settings initialization failed"); - } - - register_factory_reset_button(FACTORY_RESET_BUTTON); - -#ifdef CONFIG_CHIP - /* Initialize Matter stack */ - err = matter_init(); - if (err) { - LOG_ERR("Matter initialization failed (err: %d)", err); - /* Continue with Zigbee only */ - } else { - LOG_INF("Matter stack initialized"); - } -#endif - - /* Register callback for handling ZCL commands. */ - ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb); - - /* Register dimmer switch device context (endpoints). */ - ZB_AF_REGISTER_DEVICE_CTX(&dimmable_light_ctx); - - bulb_clusters_attr_init(); - level_control_set_value(dev_ctx.level_control_attr.current_level); - - /* Register handler to identify notifications. */ - ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(DIMMABLE_LIGHT_ENDPOINT, identify_cb); - - /* Initialize ZCL scene table */ - zcl_scenes_init(); - - /* Settings should be loaded after zcl_scenes_init */ - err = settings_load(); - if (err) { - LOG_ERR("settings loading failed"); - } - - /* Start Zigbee default thread */ - zigbee_enable(); - - LOG_INF("Zigbee + Matter Light Bulb example started"); - - while (1) { - dk_set_led(RUN_STATUS_LED, (++blink_status) % 2); - k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL)); - } -} diff --git a/samples/light_bulb/src/matter_init.cpp b/samples/light_bulb/src/matter_init.cpp deleted file mode 100644 index e4021d58..00000000 --- a/samples/light_bulb/src/matter_init.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2026 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#ifdef CONFIG_CHIP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_CHIP_CRYPTO_PSA -#include -#endif - -LOG_MODULE_REGISTER(matter_init, CONFIG_CHIP_APP_LOG_LEVEL); - -using namespace ::chip; -using namespace ::chip::DeviceLayer; -using namespace ::chip::Credentials; - -chip::app::Clusters::NetworkCommissioning::InstanceAndDriver< - NetworkCommissioning::GenericThreadDriver> - sThreadNetworkDriver(0 /*endpointId*/); -static chip::CommonCaseDeviceServerInitParams sServerInitParamsDefault; -static chip::DeviceLayer::DeviceInfoProviderImpl sDeviceInfoProviderDefault; - -#ifdef CONFIG_CHIP_CRYPTO_PSA -static chip::Crypto::PSAOperationalKeystore sOperationalKeystoreDefault; -#endif - -CHIP_ERROR configure_thread_role() { - using ThreadRole = ConnectivityManager::ThreadDeviceType; - - // Assuming FTD role for the light bulb sample - ThreadRole threadRole{ThreadRole::kThreadDeviceType_Router}; - - return ConnectivityMgr().SetThreadDeviceType(threadRole); -} - -void lock_open_thread_task(void) { - chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); -} - -void unlock_open_thread_task(void) { - chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); -} - -/** - * @brief Initialize Matter stack for combined Zigbee+Matter application - * - * Simplified initialization for memory estimation purposes. - * Full Zigbee/Matter integration would require additional synchronization. - */ -extern "C" int matter_init(void) { - CHIP_ERROR err = CHIP_NO_ERROR; - - LOG_INF("Initializing Matter stack (simplified for memory estimation)"); - - // Initialize Matter platform - err = PlatformMgr().InitChipStack(); - if (err != CHIP_NO_ERROR) { - LOG_ERR("PlatformMgr().InitChipStack() failed: %s", ErrorStr(err)); - return -ENODEV; - } - - err = ThreadStackMgr().InitThreadStack(); - if (err != CHIP_NO_ERROR) { - LOG_ERR("ThreadStackMgr().InitThreadStack() failed: %s", ErrorStr(err)); - return -ENODEV; - } - - err = configure_thread_role(); - if (err != CHIP_NO_ERROR) { - LOG_ERR("configure_thread_role() failed: %s", ErrorStr(err)); - return -ENODEV; - } - - sThreadNetworkDriver.Init(); - - // Initialize device attestation credentials - SetDeviceInstanceInfoProvider(&DeviceInstanceInfoProviderMgrImpl()); - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); - - chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; - nativeParams.lockCb = lock_open_thread_task; - nativeParams.unlockCb = unlock_open_thread_task; - nativeParams.openThreadInstancePtr = - chip::DeviceLayer::ThreadStackMgrImpl().OTInstance(); - sServerInitParamsDefault.endpointNativeParams = - static_cast(&nativeParams); - -#ifdef CONFIG_CHIP_CRYPTO_PSA - sServerInitParamsDefault.operationalKeystore = &sOperationalKeystoreDefault; -#endif - - sServerInitParamsDefault.InitializeStaticResourcesBeforeServerInit(); - - SetDeviceInfoProvider(&sDeviceInfoProviderDefault); - - sServerInitParamsDefault.dataModelProvider = - chip::app::CodegenDataModelProviderInstance( - sServerInitParamsDefault.persistentStorageDelegate); - - err = Server::GetInstance().Init(sServerInitParamsDefault); - if (err != CHIP_NO_ERROR) { - LOG_ERR("Server::GetInstance().Init() failed: %s", ErrorStr(err)); - return -ENODEV; - } - - ConfigurationMgr().LogDeviceConfig(); - PrintOnboardingCodes( - RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); - - // Start Matter event loop - err = PlatformMgr().StartEventLoopTask(); - if (err != CHIP_NO_ERROR) { - LOG_ERR("PlatformMgr().StartEventLoopTask() failed: %s", ErrorStr(err)); - return -ENODEV; - } - - LOG_INF("Matter stack initialized successfully"); - - return 0; -} - -/** - * @brief Synchronize Zigbee and Matter light states - * - * Simplified version for memory estimation. - */ -extern "C" void matter_zigbee_light_sync(bool on_off, uint8_t level) { - // In a full implementation, this would update Matter attributes - // For now, just log for memory estimation purposes - LOG_DBG("Light sync: on_off=%d, level=%d", on_off, level); -} - -#endif /* CONFIG_CHIP */ - -/** - * @brief Update Matter on/off attribute from Zigbee state - */ -extern "C" void matter_update_onoff(bool on) { - LOG_DBG("Updating Matter on/off to %d", on); - // For memory estimation, we skip the actual cluster update - // In full implementation: - // chip::app::Clusters::OnOff::Attributes::OnOff::Set(MATTER_LIGHT_ENDPOINT, - // on); -} - -/** - * @brief Update Matter level control attribute from Zigbee state - */ -extern "C" void matter_update_level(uint8_t level) { - LOG_DBG("Updating Matter level to %d", level); - // For memory estimation, we skip the actual cluster update - // In full implementation: - // chip::app::Clusters::LevelControl::Attributes::CurrentLevel::Set(MATTER_LIGHT_ENDPOINT, - // level); -} diff --git a/samples/light_bulb/src/matter_init.h b/samples/light_bulb/src/matter_init.h deleted file mode 100644 index 8d1df271..00000000 --- a/samples/light_bulb/src/matter_init.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2026 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef MATTER_INIT_H -#define MATTER_INIT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize Matter stack - * - * @return 0 on success, negative errno on failure - */ -int matter_init(void); - -/** - * @brief Update Matter on/off attribute - * - * @param on true for on, false for off - */ -void matter_update_onoff(bool on); - -/** - * @brief Update Matter level control attribute - * - * @param level Level value (0-255) - */ -void matter_update_level(uint8_t level); - -#ifdef __cplusplus -} -#endif - -#endif /* MATTER_INIT_H */ diff --git a/subsys/osif/zb_nrf_platform.c b/subsys/osif/zb_nrf_platform.c index b1dae81f..4a07a185 100644 --- a/subsys/osif/zb_nrf_platform.c +++ b/subsys/osif/zb_nrf_platform.c @@ -365,6 +365,20 @@ int zigbee_init(void) SYS_INIT(zigbee_init, POST_KERNEL, CONFIG_ZBOSS_INIT_PRIORITY); +void zigbee_deinit(void) +{ + if (zboss_tid) { + k_thread_abort(zboss_tid); + zboss_tid = NULL; + } + + stack_is_started = false; + (void)k_work_cancel(&zb_app_cb_work); + k_msgq_purge(&zb_app_cb_msgq); + k_poll_signal_reset(&zigbee_sig); + (void)atomic_clear((atomic_t *)&zb_app_cb_process_scheduled); +} + #if IS_ENABLED(CONFIG_ZIGBEE_LIBRARY_NCP_DEV) void zb_ncp_app_fw_custom_post_start(void) { diff --git a/subsys/osif/zb_nrf_platform.h b/subsys/osif/zb_nrf_platform.h index 0418fbdf..05cc6b97 100644 --- a/subsys/osif/zb_nrf_platform.h +++ b/subsys/osif/zb_nrf_platform.h @@ -68,6 +68,9 @@ bool zigbee_is_zboss_thread_suspended(void); */ int zigbee_init(void); +/**@brief Function for deinitializing Zigbee OSIF resources after disable. */ +void zigbee_deinit(void); + /**@brief Notify the ZBOSS thread about a new event. * * @param[in] event Event to notify. diff --git a/subsys/osif/zb_nrf_transceiver.c b/subsys/osif/zb_nrf_transceiver.c index 5d1a64d8..15319e60 100644 --- a/subsys/osif/zb_nrf_transceiver.c +++ b/subsys/osif/zb_nrf_transceiver.c @@ -11,11 +11,16 @@ #include #include #include +#include #include #include #include #include "zb_nrf_platform.h" +#if defined(CONFIG_NRF_802154_CALLBACKS_DISPATCHER) +#include +#endif + #if defined(CONFIG_NRF_802154_SER_HOST) #include "nrf_802154_serialization_error.h" #endif @@ -61,7 +66,7 @@ struct zboss_rx_frame { struct nrf5_data { enum zb_radio_state state; - + int8_t tx_power; uint8_t channel; bool promiscuous; @@ -80,7 +85,7 @@ struct nrf5_data { uint32_t time_us; uint8_t value; } energy_detection; - + struct k_sem rssi_wait; }; @@ -92,22 +97,16 @@ static void tx_done_ack_work_fn(struct k_work *work); static K_WORK_DEFINE(tx_done_ack_work, tx_done_ack_work_fn); #endif -static int nrf_802154_radio_init(void) +void zigbee_nrf_802154_radio_init(void) { + memset(&nrf5_data, 0, sizeof(nrf5_data)); k_fifo_init(&nrf5_data.rx.fifo); k_sem_init(&nrf5_data.rssi_wait, 0, 1); - - nrf_802154_init(); - nrf5_data.state = ZB_RADIO_STATE_SLEEP; - LOG_INF("802.15.4 radio driver initialized"); - - return 0; + LOG_INF("Zigbee radio initialized"); } -SYS_INIT(nrf_802154_radio_init, POST_KERNEL, CONFIG_ZBOSS_RADIO_INIT_PRIORITY); - void zb_trans_hw_init(void) { nrf_802154_src_addr_matching_method_set(NRF_802154_SRC_ADDR_MATCH_ZIGBEE); @@ -134,11 +133,11 @@ void zb_trans_set_short_addr(zb_uint16_t addr) static int zboss_energy_detection_start(uint32_t time_us) { nrf5_data.energy_detection.time_us = time_us; - + if (!nrf_802154_energy_detection(time_us)) { return -EBUSY; } - + return 0; } @@ -150,7 +149,7 @@ void zb_trans_start_get_rssi(zb_uint8_t scan_duration_bi) LOG_DBG("%s: %d us", __func__, time_us); err = zboss_energy_detection_start(time_us); - + while (err != 0) { LOG_DBG("Energy detection start failed, retrying"); k_usleep(500); @@ -328,7 +327,6 @@ zb_bool_t zb_trans_set_pending_bit(zb_uint8_t *addr, zb_bool_t value, zb_bool_t void zb_trans_src_match_tbl_drop(void) { - LOG_DBG("%s", __func__); nrf_802154_pending_bit_for_addr_reset(false); nrf_802154_pending_bit_for_addr_reset(true); } @@ -365,7 +363,7 @@ zb_uint8_t zb_trans_get_next_packet(zb_bufid_t buf) zb_macll_metadata_t *metadata = ZB_MACLL_GET_METADATA(buf); metadata->lqi = rx_frame->lqi; metadata->power = rx_frame->power; - + *ZB_BUF_GET_PARAM(buf, zb_time_t) = (zb_time_t)rx_frame->time; zb_macll_set_received_data_status(buf, rx_frame->ack_fpb); @@ -394,8 +392,8 @@ static void tx_done_ack_work_fn(struct k_work *work) /* nRF 802.15.4 driver callbacks - modern API with metadata structures */ -void nrf_802154_transmitted_raw(uint8_t *p_frame, - const nrf_802154_transmit_done_metadata_t *p_metadata) +static void zigbee_nrf_802154_transmitted_raw(uint8_t *p_frame, + const nrf_802154_transmit_done_metadata_t *p_metadata) { ARG_UNUSED(p_frame); @@ -414,9 +412,8 @@ void nrf_802154_transmitted_raw(uint8_t *p_frame, zigbee_event_notify(ZIGBEE_EVENT_TX_DONE); } -void nrf_802154_transmit_failed(uint8_t *p_frame, - nrf_802154_tx_error_t error, - const nrf_802154_transmit_done_metadata_t *p_metadata) +static void zigbee_nrf_802154_transmit_failed(uint8_t *p_frame, nrf_802154_tx_error_t error, + const nrf_802154_transmit_done_metadata_t *p_metadata) { ARG_UNUSED(p_frame); ARG_UNUSED(p_metadata); @@ -442,13 +439,13 @@ void nrf_802154_transmit_failed(uint8_t *p_frame, zigbee_event_notify(ZIGBEE_EVENT_TX_FAILED); } -void nrf_802154_tx_ack_started(const uint8_t *p_data) +static void zigbee_nrf_802154_tx_ack_started(const uint8_t *p_data) { nrf5_data.rx.last_frame_ack_fpb = p_data[FRAME_PENDING_OFFSET] & FRAME_PENDING_BIT; } -void nrf_802154_received_timestamp_raw(uint8_t *p_data, int8_t power, - uint8_t lqi, uint64_t time) +static void zigbee_nrf_802154_received_timestamp_raw(uint8_t *p_data, int8_t power, uint8_t lqi, + uint64_t time) { struct zboss_rx_frame *rx_frame_free_slot = NULL; @@ -483,25 +480,25 @@ void nrf_802154_received_timestamp_raw(uint8_t *p_data, int8_t power, zigbee_event_notify(ZIGBEE_EVENT_RX_DONE); } -void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) +static void zigbee_nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) { ARG_UNUSED(id); ARG_UNUSED(error); nrf5_data.rx.last_frame_ack_fpb = false; } -void nrf_802154_energy_detected(const nrf_802154_energy_detected_t *p_result) +static void zigbee_nrf_802154_energy_detected(const nrf_802154_energy_detected_t *p_result) { nrf5_data.energy_detection.value = zboss_normalize_ed_dbm(p_result->ed_dbm); k_sem_give(&nrf5_data.rssi_wait); } -void nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error) +static void zigbee_nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error) { ARG_UNUSED(error); - + int err = zboss_energy_detection_start(nrf5_data.energy_detection.time_us); - + if (err != 0) { LOG_ERR("Failed to restart energy detection after failure"); nrf5_data.energy_detection.value = UINT8_MAX; @@ -510,9 +507,102 @@ void nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error) } #if defined(CONFIG_NRF_802154_SER_HOST) -void nrf_802154_serialization_error(const nrf_802154_ser_err_data_t *err) +static void zigbee_nrf_802154_serialization_error(const nrf_802154_ser_err_data_t *err) { + ARG_UNUSED(err); __ASSERT(false, "802.15.4 serialization error: %d", err->reason); k_oops(); } #endif + +#ifdef CONFIG_NRF_802154_CALLBACKS_DISPATCHER +static void zigbee_nrf_802154_release_rx_frames(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(nrf5_data.rx.frames); i++) { + if (nrf5_data.rx.frames[i].psdu != NULL) { + nrf_802154_buffer_free_raw(nrf5_data.rx.frames[i].psdu); + nrf5_data.rx.frames[i].psdu = NULL; + } + } +} + +static void zigbee_nrf_802154_radio_deinit(void) +{ +#if defined(CONFIG_NRF_802154_SER_HOST) + (void)k_work_cancel(&tx_done_ack_work); +#endif + zigbee_nrf_802154_release_rx_frames(); +} + +static const struct nrf_802154_callbacks zigbee_802154_callbacks = { + .init = zigbee_nrf_802154_radio_init, + .deinit = zigbee_nrf_802154_radio_deinit, + .received_timestamp_raw = zigbee_nrf_802154_received_timestamp_raw, + .receive_failed = zigbee_nrf_802154_receive_failed, + .tx_ack_started = zigbee_nrf_802154_tx_ack_started, + .transmitted_raw = zigbee_nrf_802154_transmitted_raw, + .transmit_failed = zigbee_nrf_802154_transmit_failed, + .energy_detected = zigbee_nrf_802154_energy_detected, + .energy_detection_failed = zigbee_nrf_802154_energy_detection_failed, +#if defined(CONFIG_NRF_802154_SER_HOST) + .serialization_error = zigbee_nrf_802154_serialization_error, +#endif +}; + +NRF_802154_CALLBACKS_DISPATCHER_REGISTER(zigbee, zigbee_802154_callbacks); + +#else +/* Translate the nrf_802154 callbacks to zigbee_nrf_802154_callbacks for + * backward compatibility */ +void nrf_802154_received_timestamp_raw(uint8_t *data, int8_t power, uint8_t lqi, uint64_t time) +{ + zigbee_nrf_802154_received_timestamp_raw(data, power, lqi, time); +} + +void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) +{ + zigbee_nrf_802154_receive_failed(error, id); +} + +void nrf_802154_tx_ack_started(const uint8_t *data) +{ + zigbee_nrf_802154_tx_ack_started(data); +} + +void nrf_802154_transmitted_raw(uint8_t *frame, const nrf_802154_transmit_done_metadata_t *metadata) +{ + zigbee_nrf_802154_transmitted_raw(frame, metadata); +} + +void nrf_802154_transmit_failed(uint8_t *frame, nrf_802154_tx_error_t error, + const nrf_802154_transmit_done_metadata_t *metadata) +{ + zigbee_nrf_802154_transmit_failed(frame, error, metadata); +} + +void nrf_802154_energy_detected(const nrf_802154_energy_detected_t *result) +{ + zigbee_nrf_802154_energy_detected(result); +} + +void nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error) +{ + zigbee_nrf_802154_energy_detection_failed(error); +} + +#if defined(CONFIG_NRF_802154_SER_HOST) +void nrf_802154_serialization_error(const nrf_802154_ser_err_data_t *err) +{ + zigbee_nrf_802154_serialization_error(err); +} +#endif + +static int zigbee_802154_radio_init(void) +{ + zigbee_nrf_802154_radio_init(); + nrf_802154_init(); + return 0; +} + +SYS_INIT(zigbee_802154_radio_init, POST_KERNEL, CONFIG_ZBOSS_RADIO_INIT_PRIORITY); +#endif /* CONFIG_NRF_802154_CALLBACKS_DISPATCHER */ diff --git a/west.yml b/west.yml index 7212de42..cec73f4d 100644 --- a/west.yml +++ b/west.yml @@ -10,5 +10,5 @@ manifest: - name: nrf remote: ncs repo-path: sdk-nrf - revision: v3.2.0 + revision: v3.3.0-rc2 import: true