diff --git a/Dockerfile b/Dockerfile index 221d6d9e..a96eb79e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,18 +30,16 @@ RUN if [ "$TARGETARCH" = "arm64" ]; then \ ca-certificates \ git \ && rm -rf /var/lib/apt/lists/* \ - # Download QEMU 11.0.0 source - && aria2c --checksum=sha-256=253fb688815c7ba4bf1a3ecb582bd4476cfa485deb759f5f641efcde0d4bfabd -o qemu.tar.gz \ - https://gitlab.com/qemu-project/qemu/-/archive/v11.0.0/qemu-v11.0.0.tar.gz \ + # Download QEMU 11.0.2 source + && aria2c --checksum=sha-256=f1ab4eda29aa2e5c0b29ba38b7411c368b9b9bf822de6569c53ea8d4e04f980a -o qemu.tar.gz \ + https://gitlab.com/qemu-project/qemu/-/archive/v11.0.2/qemu-v11.0.2.tar.gz \ && tar xzf qemu.tar.gz && rm qemu.tar.gz \ - && mv qemu-v11.0.0 qemu \ + && mv qemu-v11.0.2 qemu \ && cd qemu \ # Apply execve interception patch from conda-forge && aria2c -o execve.patch \ - https://raw.githubusercontent.com/conda-forge/qemu-execve-feedstock/eaea9abfa56f859c98fb3938535a961465a58ae6/recipe/patches/execve/apply-execve-JH.patch \ + https://raw.githubusercontent.com/conda-forge/qemu-execve-feedstock/988a9d79604e0a88cecc6bc4439625decdc308e9/recipe/patches/execve/apply-execve-JH.patch \ && patch -p1 < execve.patch && rm execve.patch \ - # Skip vsyscall page setup when reserved_va is enabled - && sed -i '/Cannot allocate vsyscall page/{s/.*/ return true;/;n;d}' linux-user/x86_64/elfload.c \ && ./configure \ --target-list=x86_64-linux-user \ --static \ @@ -56,20 +54,45 @@ RUN if [ "$TARGETARCH" = "arm64" ]; then \ mkdir -p /usr/src/qemu/build && touch /usr/src/qemu/build/qemu-x86_64; \ fi -# The new `slt` tool does not provide Gecko SDK builds so we have to download it ourselves. -FROM debian:trixie-slim AS gecko-sdk-v4.5.0 -RUN apt-get update && apt-get install -y --no-install-recommends aria2 ca-certificates libarchive-tools \ - && rm -rf /var/lib/apt/lists/* \ - && aria2c --checksum=sha-256=b5b2b2410eac0c9e2a72320f46605ecac0d376910cafded5daca9c1f78e966c8 -o sdk.zip \ - https://github.com/SiliconLabs/gecko_sdk/releases/download/v4.5.0/gecko-sdk.zip \ - && mkdir /out && bsdtar -xf sdk.zip -C /out \ - && rm sdk.zip +# Arm's official aarch64 toolchain was built WITHOUT libzstd and SiLabs uses +# zstd-compressed LTO bytecode in their precompiled SDK stack libraries. This prevents +# any compilation from succeeding on ARM64 hosts. We need to build our own minimal +# toolchain with zstd support to work around this. x86 is not affected. +FROM debian:trixie-slim AS zstd-gcc-builder +ARG TARGETARCH +RUN mkdir -p /opt/zstd-gcc \ + && if [ "$TARGETARCH" = "arm64" ]; then set -eux \ + && apt-get update && apt-get install -y --no-install-recommends \ + build-essential flex bison texinfo gawk libtool autoconf m4 \ + zlib1g-dev libzstd-dev wget file gettext bzip2 xz-utils ca-certificates git aria2 \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p /build/src && cd /build \ + && aria2c --checksum=sha-256=e6405f20f8a817a50d92dbf7974d0ee77708dfdf9e79900a59c5d343b464ef9c -o src.tar.xz \ + https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/14.2.rel1/srcrel/arm-gnu-toolchain-src-snapshot-14.2.rel1.tar.xz \ + && tar -xJf src.tar.xz -C /build/src && rm src.tar.xz \ + && git clone --depth 1 --branch v1.1.0 \ + https://git.gitlab.arm.com/tooling/gnu-devtools-for-arm.git /build/src/gnu-devtools-for-arm \ + && ln -sf src/gnu-devtools-for-arm/build-gnu-toolchain.sh . \ + # The `start` stage normally creates `install/`. Running stages individually skips + # it, so pre-create it or the first `do_config` can't write `install/.build_flags`. + && mkdir -p /build/build-arm-none-eabi-armv7e-m/install \ + # Single multilib, no gdb. Through gcc2 so cc1plus (C++) is built too. + && ./build-gnu-toolchain.sh --target=arm-none-eabi --with-arch=armv7e-m \ + --disable-multilib --disable-gdb \ + gmp mpfr mpc isl iconv binutils gcc1 newlib gcc2 \ + && for t in cc1 cc1plus lto1; do \ + cp "$(find /build -path '*/libexec/gcc/arm-none-eabi/*' -name "$t" | head -1)" /opt/zstd-gcc/; \ + done \ + # Strip debug info (Arm ships these stripped; unstripped they are ~340 MB each) + && strip /opt/zstd-gcc/* \ + && rm -rf /build; \ + fi # Python virtual environment for the firmware builder script FROM debian:trixie-slim AS python-venv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/bin/ COPY requirements.txt /tmp/ -RUN UV_PYTHON_INSTALL_DIR=/opt/pythons uv venv -p 3.13 /opt/venv --no-cache \ +RUN UV_PYTHON_INSTALL_DIR=/opt/pythons uv venv -p 3.14 /opt/venv --no-cache \ && uv pip install --python /opt/venv -r /tmp/requirements.txt # Install slt and all toolchain packages (depends on QEMU for ARM64) @@ -106,9 +129,7 @@ RUN set -e \ # Install conan && slt --non-interactive install conan \ && mv /root/.silabs/slt/engines/conan/conan_engine /root/.silabs/slt/engines/conan/conan_engine-bin \ - # -R limits address space to 47 bits, fixing Go binaries that assume 48-bit sign-extended addresses - # This can be removed once conan_engine is recompiled with a newer Go toolchain - && printf '#!/bin/sh\nexec /usr/bin/qemu-x86_64-static -R 0x800000000000 /root/.silabs/slt/engines/conan/conan_engine-bin "$@"\n' > /root/.silabs/slt/engines/conan/conan_engine \ + && printf '#!/bin/sh\nexec /usr/bin/qemu-x86_64-static /root/.silabs/slt/engines/conan/conan_engine-bin "$@"\n' > /root/.silabs/slt/engines/conan/conan_engine \ && chmod +x /root/.silabs/slt/engines/conan/conan_engine \ # Remove --execve from slt wrapper once we install conan, so native tools (tar, etc.) run without QEMU && printf '#!/bin/sh\nexec /usr/bin/qemu-x86_64-static /usr/bin/slt-bin "$@"\n' > /usr/bin/slt \ @@ -132,14 +153,13 @@ RUN set -e \ && slt --non-interactive install \ cmake/3.30.2 \ ninja/1.12.1 \ - commander/1.23.1 \ - slc-cli/6.0.17 \ - simplicity-sdk/2025.6.2 \ - zap/2026.02.26 \ - # conan cannot resolve two copies of the same package, even with different versions, - # in a single command - && slt --non-interactive install \ - simplicity-sdk/2025.12.1 \ + commander/1.24.1 \ + slc-cli/6.0.22 \ + simplicity-sdk/2026.6.0 \ + zap/2026.06.17 \ + # We don't currently use the LLVM toolchain that is pulled in as a default + # dependency. Uninstall it to save space. + && slt --non-interactive uninstall --force llvm-arm-toolchain-for-embedded \ # Clean up download caches to reduce image size && rm -rf /root/.silabs/slt/installs/archive/*.zip \ /root/.silabs/slt/installs/archive/*.tar.* \ @@ -180,17 +200,24 @@ RUN set -e \ libpng16-16 \ libpcre2-16-0 \ libglib2.0-0 \ + # Needed at runtime by the zstd-enabled cc1/cc1plus/lto1 swapped in below (ARM64) + libzstd1 \ && rm -rf /var/lib/apt/lists/* \ # Fix git permission error when building locally && git config --global --add safe.directory '*' # Copy from parallel stages -COPY --from=gecko-sdk-v4.5.0 /out /gecko_sdk_4.5.0 COPY --from=python-venv /opt/pythons /opt/pythons COPY --from=python-venv /opt/venv /opt/venv COPY --from=qemu-execve-builder /usr/src/qemu/build/qemu-x86_64 /usr/bin/qemu-x86_64-static COPY --from=slt-toolchain /usr/bin/slt* /usr/bin/ COPY --from=slt-toolchain /root/.silabs /root/.silabs +COPY --from=zstd-gcc-builder /opt/zstd-gcc /tmp/zstd-gcc +RUN if [ "$TARGETARCH" = "arm64" ]; then set -eux \ + && d="$(dirname "$(find /root/.silabs -path '*/libexec/gcc/arm-none-eabi/*' -name lto1 | head -1)")" \ + && cp /tmp/zstd-gcc/cc1 /tmp/zstd-gcc/cc1plus /tmp/zstd-gcc/lto1 "$d/"; \ + fi \ + && rm -rf /tmp/zstd-gcc # Signal to the firmware builder script that we are running within Docker ENV SILABS_FIRMWARE_BUILD_CONTAINER=1 diff --git a/extension/nabucasa_hardware_extension/src/zbt2_router_callbacks.c b/extension/nabucasa_hardware_extension/src/zbt2_router_callbacks.c index bbd43a98..f192c087 100644 --- a/extension/nabucasa_hardware_extension/src/zbt2_router_callbacks.c +++ b/extension/nabucasa_hardware_extension/src/zbt2_router_callbacks.c @@ -192,13 +192,17 @@ static void sync_light_state(uint8_t endpoint) // Commissioning event handler - starts network steering static void commissioning_retry_event_handler(sl_zigbee_af_event_t *event) { + (void)event; + if (sl_zigbee_af_network_state() != SL_ZIGBEE_JOINED_NETWORK) { // Switch from white pulse (ready) to blue pulse (searching) led_pattern_t search_pattern = { .mode = LED_MODE_PULSE, .color = LED_COLOR_SEARCH_BLUE, .period_ms = 2760, - .duration_ms = 0 + .duration_ms = 0, + .brightness_min = 6554, // ~10% + .brightness_max = 65535, }; led_manager_set_pattern(LED_PRIORITY_BACKGROUND, &search_pattern); @@ -248,6 +252,10 @@ void sl_zigbee_af_network_steering_complete_cb(sl_status_t status, uint8_t joinAttempts, uint8_t finalState) { + (void)totalBeacons; + (void)joinAttempts; + (void)finalState; + sl_zigbee_app_debug_println("Network steering complete: 0x%X", status); if (status != SL_STATUS_OK) { @@ -268,6 +276,11 @@ void sl_zigbee_af_post_attribute_change_cb(uint8_t endpoint, uint8_t size, uint8_t* value) { + (void)manufacturerCode; + (void)type; + (void)size; + (void)value; + if (mask != CLUSTER_MASK_SERVER) { return; } diff --git a/manifests/nabucasa/skyconnect/skyconnect_bootloader.yaml b/manifests/nabucasa/skyconnect/skyconnect_bootloader.yaml index 1c16d901..bc737853 100644 --- a/manifests/nabucasa/skyconnect/skyconnect_bootloader.yaml +++ b/manifests/nabucasa/skyconnect/skyconnect_bootloader.yaml @@ -2,8 +2,8 @@ name: SkyConnect Bootloader device: EFR32MG21A020F512IM32 base_project: src/bootloader filename: "{manifest_name}_{gecko_bootloader_version}" -sdk: "gecko_sdk:4.5.0" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "14.2.1.20241119" gbl: fw_type: gecko-bootloader diff --git a/manifests/nabucasa/skyconnect/skyconnect_openthread_rcp.yaml b/manifests/nabucasa/skyconnect/skyconnect_openthread_rcp.yaml index 3d8e87df..b15abdfe 100644 --- a/manifests/nabucasa/skyconnect/skyconnect_openthread_rcp.yaml +++ b/manifests/nabucasa/skyconnect/skyconnect_openthread_rcp.yaml @@ -2,14 +2,17 @@ name: SkyConnect OpenThread RCP device: EFR32MG21A020F512IM32 base_project: src/openthread_rcp filename: "{manifest_name}_{ot_rcp_version.split('/')[-1]}_gsdk_{sdk_version}" -sdk: "simplicity_sdk:2025.6.2" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "14.2.1.20241119" gbl: fw_type: openthread_rcp ot_rcp_version: dynamic baudrate: 460800 +sdk_patches: + - disable_gp_rx_filter.patch + add_components: - id: iostream_usart instance: [vcom] diff --git a/manifests/nabucasa/skyconnect/skyconnect_zigbee_ncp.yaml b/manifests/nabucasa/skyconnect/skyconnect_zigbee_ncp.yaml index 297628f6..c4a45f19 100644 --- a/manifests/nabucasa/skyconnect/skyconnect_zigbee_ncp.yaml +++ b/manifests/nabucasa/skyconnect/skyconnect_zigbee_ncp.yaml @@ -2,8 +2,8 @@ name: SkyConnect Zigbee device: EFR32MG21A020F512IM32 base_project: src/zigbee_ncp filename: "{manifest_name}_{ezsp_version}" -sdk: "gecko_sdk:4.5.0" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "14.2.1.20241119" gbl: fw_type: zigbee_ncp @@ -32,35 +32,44 @@ c_defines: XNCP_BUILD_STRING: template:"{now:%Y%m%d%H%M%S}" XNCP_MANUAL_SOURCE_ROUTE_TABLE_SIZE: 200 - EMBER_APS_UNICAST_MESSAGE_COUNT: 32 - EMBER_BINDING_TABLE_SIZE: 32 - EMBER_BROADCAST_TABLE_SIZE: 64 - EMBER_KEY_TABLE_SIZE: 12 - EMBER_MAX_END_DEVICE_CHILDREN: 32 - EMBER_PACKET_BUFFER_COUNT: 255 - EMBER_SOURCE_ROUTE_TABLE_SIZE: 200 + SL_ZIGBEE_APS_UNICAST_MESSAGE_COUNT: 64 + SL_ZIGBEE_BINDING_TABLE_SIZE: 32 + SL_ZIGBEE_BROADCAST_TABLE_SIZE: 64 + SL_ZIGBEE_KEY_TABLE_SIZE: 12 + SL_ZIGBEE_MAX_END_DEVICE_CHILDREN: 32 + SL_ZIGBEE_SOURCE_ROUTE_TABLE_SIZE: 200 + SL_ZIGBEE_NEIGHBOR_TABLE_SIZE: 26 + SL_ZIGBEE_ADDRESS_TABLE_SIZE: 32 - EMBER_CHILD_TABLE_SIZE: + SL_ZIGBEE_CHILD_TABLE_SIZE: type: c_flag value: 32 - EMBER_ROUTE_TABLE_SIZE: + SL_ZIGBEE_ROUTE_TABLE_SIZE: type: c_flag value: 250 + SL_ZIGBEE_MULTICAST_TABLE_SIZE: + type: c_flag + value: 26 + + SL_ZIGBEE_DISCOVERY_TABLE_SIZE: + type: c_flag + value: 8 + SL_IOSTREAM_USART_VCOM_BAUDRATE: 115200 SL_IOSTREAM_USART_VCOM_FLOW_CONTROL_TYPE: usartHwFlowControlCtsAndRts SL_IOSTREAM_USART_VCOM_PERIPHERAL: USART0 SL_IOSTREAM_USART_VCOM_PERIPHERAL_NO: 0 - SL_IOSTREAM_USART_VCOM_TX_PORT: gpioPortA + SL_IOSTREAM_USART_VCOM_TX_PORT: SL_GPIO_PORT_A SL_IOSTREAM_USART_VCOM_TX_PIN: 6 - SL_IOSTREAM_USART_VCOM_RX_PORT: gpioPortA + SL_IOSTREAM_USART_VCOM_RX_PORT: SL_GPIO_PORT_A SL_IOSTREAM_USART_VCOM_RX_PIN: 5 - SL_IOSTREAM_USART_VCOM_CTS_PORT: gpioPortB + SL_IOSTREAM_USART_VCOM_CTS_PORT: SL_GPIO_PORT_B SL_IOSTREAM_USART_VCOM_CTS_PIN: 1 - SL_IOSTREAM_USART_VCOM_RTS_PORT: gpioPortB + SL_IOSTREAM_USART_VCOM_RTS_PORT: SL_GPIO_PORT_B SL_IOSTREAM_USART_VCOM_RTS_PIN: 0 SL_IOSTREAM_USART_VCOM_RX_BUFFER_SIZE: 128 diff --git a/manifests/nabucasa/yellow/yellow_bootloader.yaml b/manifests/nabucasa/yellow/yellow_bootloader.yaml index 80c62d1d..f5af9ae5 100644 --- a/manifests/nabucasa/yellow/yellow_bootloader.yaml +++ b/manifests/nabucasa/yellow/yellow_bootloader.yaml @@ -2,8 +2,8 @@ name: Yellow Bootloader device: MGM210PA32JIA base_project: src/bootloader filename: "{manifest_name}_{gecko_bootloader_version}" -sdk: "gecko_sdk:4.5.0" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "14.2.1.20241119" gbl: fw_type: gecko-bootloader diff --git a/manifests/nabucasa/yellow/yellow_openthread_rcp.yaml b/manifests/nabucasa/yellow/yellow_openthread_rcp.yaml index b36363c9..bd9de79d 100644 --- a/manifests/nabucasa/yellow/yellow_openthread_rcp.yaml +++ b/manifests/nabucasa/yellow/yellow_openthread_rcp.yaml @@ -2,14 +2,17 @@ name: Yellow OpenThread RCP device: MGM210PA32JIA base_project: src/openthread_rcp filename: "{manifest_name}_{ot_rcp_version.split('/')[-1]}_gsdk_{sdk_version}" -sdk: "simplicity_sdk:2025.6.2" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "14.2.1.20241119" gbl: fw_type: openthread_rcp ot_rcp_version: dynamic baudrate: 460800 +sdk_patches: + - disable_gp_rx_filter.patch + add_components: - id: iostream_usart instance: [vcom] diff --git a/manifests/nabucasa/yellow/yellow_zigbee_ncp.yaml b/manifests/nabucasa/yellow/yellow_zigbee_ncp.yaml index 83a8e76f..f3879029 100644 --- a/manifests/nabucasa/yellow/yellow_zigbee_ncp.yaml +++ b/manifests/nabucasa/yellow/yellow_zigbee_ncp.yaml @@ -2,8 +2,8 @@ name: Yellow Zigbee device: MGM210PA32JIA base_project: src/zigbee_ncp filename: "{manifest_name}_{ezsp_version}" -sdk: "gecko_sdk:4.5.0" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "14.2.1.20241119" gbl: fw_type: zigbee_ncp @@ -34,47 +34,63 @@ add_components: vendor: nabucasa package: xncp_common +# SLC validates clock settings before c_defines are patched, use `configuration` +configuration: + SL_CLOCK_MANAGER_PCLK_DIVIDER: SL_CLOCK_MANAGER_PCLK_DIV_MIN + c_defines: + # SDK bug: the PCLK divider is set to 1 for the MGM210, it is set to 2 everywhere else + SL_CLOCK_MANAGER_PCLK_DIVIDER: SL_CLOCK_MANAGER_PCLK_DIV_MIN + XNCP_MFG_MANUF_NAME: '"Nabu Casa"' XNCP_MFG_BOARD_NAME: '"Home Assistant Yellow"' XNCP_BUILD_STRING: template:"{now:%Y%m%d%H%M%S}" XNCP_MANUAL_SOURCE_ROUTE_TABLE_SIZE: 200 - EMBER_APS_UNICAST_MESSAGE_COUNT: 32 - EMBER_BINDING_TABLE_SIZE: 32 - EMBER_BROADCAST_TABLE_SIZE: 64 - EMBER_KEY_TABLE_SIZE: 12 - EMBER_MAX_END_DEVICE_CHILDREN: 32 - EMBER_PACKET_BUFFER_COUNT: 255 - EMBER_SOURCE_ROUTE_TABLE_SIZE: 200 + SL_ZIGBEE_APS_UNICAST_MESSAGE_COUNT: 64 + SL_ZIGBEE_BINDING_TABLE_SIZE: 32 + SL_ZIGBEE_BROADCAST_TABLE_SIZE: 64 + SL_ZIGBEE_KEY_TABLE_SIZE: 12 + SL_ZIGBEE_MAX_END_DEVICE_CHILDREN: 32 + SL_ZIGBEE_SOURCE_ROUTE_TABLE_SIZE: 200 + SL_ZIGBEE_NEIGHBOR_TABLE_SIZE: 26 + SL_ZIGBEE_ADDRESS_TABLE_SIZE: 32 - EMBER_CHILD_TABLE_SIZE: + SL_ZIGBEE_CHILD_TABLE_SIZE: type: c_flag value: 32 - EMBER_ROUTE_TABLE_SIZE: + SL_ZIGBEE_ROUTE_TABLE_SIZE: type: c_flag value: 250 + SL_ZIGBEE_MULTICAST_TABLE_SIZE: + type: c_flag + value: 26 + + SL_ZIGBEE_DISCOVERY_TABLE_SIZE: + type: c_flag + value: 8 + SL_IOSTREAM_USART_VCOM_BAUDRATE: 115200 SL_IOSTREAM_USART_VCOM_FLOW_CONTROL_TYPE: usartHwFlowControlCtsAndRts SL_IOSTREAM_USART_VCOM_PERIPHERAL: USART0 SL_IOSTREAM_USART_VCOM_PERIPHERAL_NO: 0 - SL_IOSTREAM_USART_VCOM_TX_PORT: gpioPortA + SL_IOSTREAM_USART_VCOM_TX_PORT: SL_GPIO_PORT_A SL_IOSTREAM_USART_VCOM_TX_PIN: 5 - SL_IOSTREAM_USART_VCOM_RX_PORT: gpioPortA + SL_IOSTREAM_USART_VCOM_RX_PORT: SL_GPIO_PORT_A SL_IOSTREAM_USART_VCOM_RX_PIN: 6 - SL_IOSTREAM_USART_VCOM_CTS_PORT: gpioPortD + SL_IOSTREAM_USART_VCOM_CTS_PORT: SL_GPIO_PORT_D SL_IOSTREAM_USART_VCOM_CTS_PIN: 2 - SL_IOSTREAM_USART_VCOM_RTS_PORT: gpioPortC + SL_IOSTREAM_USART_VCOM_RTS_PORT: SL_GPIO_PORT_C SL_IOSTREAM_USART_VCOM_RTS_PIN: 1 SL_IOSTREAM_USART_VCOM_RX_BUFFER_SIZE: 128 SL_SIMPLE_LED_BOARD_ACTIVITY_POLARITY: SL_SIMPLE_LED_POLARITY_ACTIVE_LOW - SL_SIMPLE_LED_BOARD_ACTIVITY_PORT: gpioPortB + SL_SIMPLE_LED_BOARD_ACTIVITY_PORT: SL_GPIO_PORT_B SL_SIMPLE_LED_BOARD_ACTIVITY_PIN: 1 BOARD_ACTIVITY_LED_INSTANCE: sl_led_board_activity diff --git a/manifests/nabucasa/zbt2/config/zcl/zcl_config.zap b/manifests/nabucasa/zbt2/config/zcl/zcl_config.zap index d5e45f1a..3eea84ea 100644 --- a/manifests/nabucasa/zbt2/config/zcl/zcl_config.zap +++ b/manifests/nabucasa/zbt2/config/zcl/zcl_config.zap @@ -758,6 +758,142 @@ } ] }, + { + "name": "Poll Control", + "code": 32, + "mfgCode": null, + "define": "POLL_CONTROL_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "CheckInResponse", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CheckIn", + "code": 0, + "mfgCode": null, + "source": "server", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "FastPollStop", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Keep-Alive", + "code": 37, + "mfgCode": null, + "define": "KEEPALIVE_CLUSTER", + "side": "client", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Keep-Alive", + "code": 37, + "mfgCode": null, + "define": "KEEPALIVE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Keep-Alive Base", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Keep-Alive Jitter", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "60", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "Color Control", "code": 768, diff --git a/manifests/nabucasa/zbt2/zbt2_bootloader.yaml b/manifests/nabucasa/zbt2/zbt2_bootloader.yaml index 14905770..cfbdde41 100644 --- a/manifests/nabucasa/zbt2/zbt2_bootloader.yaml +++ b/manifests/nabucasa/zbt2/zbt2_bootloader.yaml @@ -2,25 +2,14 @@ name: Home Assistant Connect ZBT-2 Bootloader device: EFR32MG24A420F1536IM40 base_project: src/bootloader filename: "{manifest_name}_{gecko_bootloader_version}" -sdk: "gecko_sdk:4.5.0" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "14.2.1.20241119" gbl: fw_type: gecko-bootloader gecko_bootloader_version: dynamic baudrate: 115200 -sdk_extension: - - id: bootloader_gpio_activation_dual - vendor: nabucasa - version: 1.0.0 - -remove_components: - - id: bootloader_gpio_activation - -add_components: - - id: bootloader_gpio_activation_dual - c_defines: SL_SERIAL_UART_FLOW_CONTROL: 1 @@ -29,23 +18,16 @@ c_defines: SL_SERIAL_UART_TX_PORT: gpioPortA SL_SERIAL_UART_TX_PIN: 8 + SL_SERIAL_UART_RX_PORT: gpioPortA SL_SERIAL_UART_RX_PIN: 7 + SL_SERIAL_UART_CTS_PORT: gpioPortA SL_SERIAL_UART_CTS_PIN: 5 + SL_SERIAL_UART_RTS_PORT: gpioPortA SL_SERIAL_UART_RTS_PIN: 0 - # The bootloader does not allow downgrades so we need to bump the version - BOOTLOADER_VERSION_MAIN_CUSTOMER: 4 - - # Dual GPIO activation for the bootloader - # Triggered by trace to S3 - NC_PRIMARY_GPIO_ACTIVATION_POLARITY: LOW - NC_BTL_BUTTON_PRIMARY_PORT: gpioPortA - NC_BTL_BUTTON_PRIMARY_PIN: 6 - - # And by the reset button on the back - NC_SECONDARY_GPIO_ACTIVATION_POLARITY: LOW - NC_BTL_BUTTON_SECONDARY_PORT: gpioPortC - NC_BTL_BUTTON_SECONDARY_PIN: 5 \ No newline at end of file + SL_GPIO_ACTIVATION_POLARITY: LOW + SL_BTL_BUTTON_PORT: gpioPortA + SL_BTL_BUTTON_PIN: 6 diff --git a/manifests/nabucasa/zbt2/zbt2_openthread_rcp.yaml b/manifests/nabucasa/zbt2/zbt2_openthread_rcp.yaml index f7f8acfe..8bb510e1 100644 --- a/manifests/nabucasa/zbt2/zbt2_openthread_rcp.yaml +++ b/manifests/nabucasa/zbt2/zbt2_openthread_rcp.yaml @@ -2,8 +2,8 @@ name: Home Assistant Connect ZBT-2 OpenThread RCP device: EFR32MG24A420F1536IM40 base_project: src/openthread_rcp filename: "{manifest_name}_{ot_rcp_version.split('/')[-1]}_gsdk_{sdk_version}" -sdk: "simplicity_sdk:2025.6.2" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "gcc:14.2.1.20241119" gbl: fw_type: openthread_rcp @@ -18,6 +18,9 @@ sdk_extension: version: 1.0.0 vendor: nabucasa +sdk_patches: + - disable_gp_rx_filter.patch + add_components: - id: spidrv_eusart instance: [ws2812] diff --git a/manifests/nabucasa/zbt2/zbt2_router.yaml b/manifests/nabucasa/zbt2/zbt2_router.yaml index b934d27f..c6bff3ce 100644 --- a/manifests/nabucasa/zbt2/zbt2_router.yaml +++ b/manifests/nabucasa/zbt2/zbt2_router.yaml @@ -2,8 +2,8 @@ name: Home Assistant Connect ZBT-2 Zigbee Router device: EFR32MG24A420F1536IM40 base_project: src/zigbee_router filename: "{manifest_name}_{sdk_version}" -sdk: "simplicity_sdk:2025.6.2" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "gcc:14.2.1.20241119" gbl: fw_type: zigbee_router diff --git a/manifests/nabucasa/zbt2/zbt2_zigbee_ncp.yaml b/manifests/nabucasa/zbt2/zbt2_zigbee_ncp.yaml index 2e7929dd..ed9d1bf4 100644 --- a/manifests/nabucasa/zbt2/zbt2_zigbee_ncp.yaml +++ b/manifests/nabucasa/zbt2/zbt2_zigbee_ncp.yaml @@ -1,9 +1,9 @@ name: Home Assistant Connect ZBT-2 Zigbee device: EFR32MG24A420F1536IM40 base_project: src/zigbee_ncp -filename: "{manifest_name}_{ezsp_version}_{fw_variant}" -sdk: "gecko_sdk:4.5.0" -toolchain: "12.2.1.20221205" +filename: "{manifest_name}_{ezsp_version}" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "gcc:14.2.1.20241119" gbl: fw_type: zigbee_ncp @@ -69,70 +69,81 @@ c_defines: # The hardware flow control is only between the S3 and the MG24. The application # should not use hardware flow control. - XNCP_FLOW_CONTROL_TYPE: usartHwFlowControlNone + XNCP_FLOW_CONTROL_TYPE: SL_IOSTREAM_EUSART_UART_FLOW_CTRL_NONE + + SL_ZIGBEE_APS_UNICAST_MESSAGE_COUNT: 128 + SL_ZIGBEE_BINDING_TABLE_SIZE: 32 + SL_ZIGBEE_BROADCAST_TABLE_SIZE: 64 + SL_ZIGBEE_KEY_TABLE_SIZE: 12 + SL_ZIGBEE_MAX_END_DEVICE_CHILDREN: 32 + SL_ZIGBEE_SOURCE_ROUTE_TABLE_SIZE: 254 + SL_ZIGBEE_NEIGHBOR_TABLE_SIZE: 26 + SL_ZIGBEE_ADDRESS_TABLE_SIZE: 128 + SL_ZIGBEE_APS_DUPLICATE_REJECTION_MAX_ENTRIES: 64 + SL_ZIGBEE_PACKET_BUFFER_HEAP_SIZE: SL_ZIGBEE_HUGE_PACKET_BUFFER_HEAP + + SL_ZIGBEE_CHILD_TABLE_SIZE: + type: c_flag + value: 32 - EMBER_APS_UNICAST_MESSAGE_COUNT: 32 - EMBER_BINDING_TABLE_SIZE: 32 - EMBER_BROADCAST_TABLE_SIZE: 64 - EMBER_KEY_TABLE_SIZE: 12 - EMBER_MAX_END_DEVICE_CHILDREN: 32 - EMBER_PACKET_BUFFER_COUNT: 255 - EMBER_SOURCE_ROUTE_TABLE_SIZE: 200 + SL_ZIGBEE_ROUTE_TABLE_SIZE: + type: c_flag + value: 254 - EMBER_CHILD_TABLE_SIZE: + SL_ZIGBEE_MULTICAST_TABLE_SIZE: type: c_flag - value: 32 + value: 26 - EMBER_ROUTE_TABLE_SIZE: + SL_ZIGBEE_DISCOVERY_TABLE_SIZE: type: c_flag - value: 250 + value: 16 - SL_DEVICE_INIT_HFXO_FREQ: 39000000 - SL_DEVICE_INIT_HFXO_PRECISION: 10 - SL_DEVICE_INIT_HFXO_CTUNE: 108 + SL_CLOCK_MANAGER_HFXO_FREQ: 39000000 + SL_CLOCK_MANAGER_HFXO_PRECISION: 10 + SL_CLOCK_MANAGER_HFXO_CTUNE: 108 - SL_IOSTREAM_USART_VCOM_BAUDRATE: 460800 - SL_IOSTREAM_USART_VCOM_FLOW_CONTROL_TYPE: usartHwFlowControlCtsAndRts + SL_IOSTREAM_EUSART_VCOM_BAUDRATE: 460800 + SL_IOSTREAM_EUSART_VCOM_FLOW_CONTROL_TYPE: SL_IOSTREAM_EUSART_UART_FLOW_CTRL_CTS_RTS - SL_IOSTREAM_USART_VCOM_PERIPHERAL: USART0 - SL_IOSTREAM_USART_VCOM_PERIPHERAL_NO: 0 + SL_IOSTREAM_EUSART_VCOM_PERIPHERAL: EUSART0 + SL_IOSTREAM_EUSART_VCOM_PERIPHERAL_NO: 0 - SL_IOSTREAM_USART_VCOM_TX_PORT: gpioPortA - SL_IOSTREAM_USART_VCOM_TX_PIN: 8 - SL_IOSTREAM_USART_VCOM_RX_PORT: gpioPortA - SL_IOSTREAM_USART_VCOM_RX_PIN: 7 - SL_IOSTREAM_USART_VCOM_CTS_PORT: gpioPortA - SL_IOSTREAM_USART_VCOM_CTS_PIN: 5 - SL_IOSTREAM_USART_VCOM_RTS_PORT: gpioPortA - SL_IOSTREAM_USART_VCOM_RTS_PIN: 0 + SL_IOSTREAM_EUSART_VCOM_TX_PORT: SL_GPIO_PORT_A + SL_IOSTREAM_EUSART_VCOM_TX_PIN: 8 + SL_IOSTREAM_EUSART_VCOM_RX_PORT: SL_GPIO_PORT_A + SL_IOSTREAM_EUSART_VCOM_RX_PIN: 7 + SL_IOSTREAM_EUSART_VCOM_CTS_PORT: SL_GPIO_PORT_A + SL_IOSTREAM_EUSART_VCOM_CTS_PIN: 5 + SL_IOSTREAM_EUSART_VCOM_RTS_PORT: SL_GPIO_PORT_A + SL_IOSTREAM_EUSART_VCOM_RTS_PIN: 0 - SL_IOSTREAM_USART_VCOM_RX_BUFFER_SIZE: 128 + SL_IOSTREAM_EUSART_VCOM_RX_BUFFER_SIZE: 512 # WS2812 LED driver SL_SPIDRV_EUSART_WS2812_PERIPHERAL: EUSART1 SL_SPIDRV_EUSART_WS2812_PERIPHERAL_NO: 1 - SL_SPIDRV_EUSART_WS2812_TX_PORT: gpioPortC + SL_SPIDRV_EUSART_WS2812_TX_PORT: SL_GPIO_PORT_C SL_SPIDRV_EUSART_WS2812_TX_PIN: 2 - SL_SPIDRV_EUSART_WS2812_RX_PORT: gpioPortC + SL_SPIDRV_EUSART_WS2812_RX_PORT: SL_GPIO_PORT_C SL_SPIDRV_EUSART_WS2812_RX_PIN: 1 - SL_SPIDRV_EUSART_WS2812_SCLK_PORT: gpioPortD + SL_SPIDRV_EUSART_WS2812_SCLK_PORT: SL_GPIO_PORT_D SL_SPIDRV_EUSART_WS2812_SCLK_PIN: 2 SL_SPIDRV_EUSART_WS2812_CS_CONTROL: spidrvCsControlApplication SL_SPIDRV_EUSART_WS2812_BITRATE: 3200000 SL_SPIDRV_EUSART_WS2812_BIT_ORDER: spidrvBitOrderMsbFirst - WS2812_EN_PORT: gpioPortC + WS2812_EN_PORT: SL_GPIO_PORT_C WS2812_EN_PIN: 3 WS2812_NUM_LEDS: 4 # I2C SL_I2CSPM_INST_PERIPHERAL: I2C0 - SL_I2CSPM_INST_SCL_PORT: gpioPortC + SL_I2CSPM_INST_SCL_PORT: SL_GPIO_PORT_C SL_I2CSPM_INST_SCL_PIN: 6 - SL_I2CSPM_INST_SDA_PORT: gpioPortC + SL_I2CSPM_INST_SDA_PORT: SL_GPIO_PORT_C SL_I2CSPM_INST_SDA_PIN: 7 # Pinhole button - SL_SIMPLE_BUTTON_PIN_HOLE_BUTTON_PORT: gpioPortC + SL_SIMPLE_BUTTON_PIN_HOLE_BUTTON_PORT: SL_GPIO_PORT_C SL_SIMPLE_BUTTON_PIN_HOLE_BUTTON_PIN: 5 # Product ID to prevent cross-flashing across devices diff --git a/manifests/nabucasa/zwa2/zwa2_controller.yaml b/manifests/nabucasa/zwa2/zwa2_controller.yaml index 0c67011c..02418e40 100644 --- a/manifests/nabucasa/zwa2/zwa2_controller.yaml +++ b/manifests/nabucasa/zwa2/zwa2_controller.yaml @@ -2,8 +2,8 @@ name: Home Assistant Connect ZWA-2 Z-Wave Controller device: EFR32ZG23A020F512GM40 base_project: src/zwa2_controller filename: "{manifest_name}_{zwave_version}" -sdk: "simplicity_sdk:2025.12.1" -toolchain: "12.2.1.20221205" +sdk: "simplicity_sdk:2026.6.0" +toolchain: "gcc:14.2.1.20241119" gbl: fw_type: zwave_ncp zwave_version: dynamic @@ -126,7 +126,7 @@ c_defines: # Firmware version (reported in SERIALAPI_CAPABILITIES) # See src/zwa2_controller/README.md for versioning scheme details. USER_APP_VERSION: 1 - USER_APP_REVISION: 2 + USER_APP_REVISION: 3 USER_APP_PATCH: 0 # USART0 serial API pins diff --git a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/bootloader_gpio_activation_dual.slcc b/src/bootloader/extension/bootloader_gpio_activation_dual_extension/bootloader_gpio_activation_dual.slcc deleted file mode 100644 index aff92fcb..00000000 --- a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/bootloader_gpio_activation_dual.slcc +++ /dev/null @@ -1,24 +0,0 @@ -id: bootloader_gpio_activation_dual -label: GPIO activation (dual pin) -package: bootloader_gpio_activation_dual -description: > - The Bootloader GPIO activation component provides entry to bootloader firmware upgrade mode - if either of two GPIOs has a given state at reset. The GPIO state is configurable. -category: Platform|Bootloader|Utils -quality: production -source: - - path: src/btl_gpio_activation_dual.c -include: - - path: inc - file_list: - - path: gpio/gpio-activation/btl_gpio_activation.h -config_file: - - path: inc/btl_gpio_activation_dual_cfg.h - file_id: btl_gpio_activation_cfg -define: - - name: BTL_GPIO_ACTIVATION - value: 1 -provides: - - name: bootloader_gpio_activation_dual - - name: bootloader_nonsecure_incompatible - condition: [bootloader_core_nonsecure] \ No newline at end of file diff --git a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/bootloader_gpio_activation_dual.slce b/src/bootloader/extension/bootloader_gpio_activation_dual_extension/bootloader_gpio_activation_dual.slce deleted file mode 100644 index afad976f..00000000 --- a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/bootloader_gpio_activation_dual.slce +++ /dev/null @@ -1,5 +0,0 @@ -id: bootloader_gpio_activation_dual -vendor: nabucasa -version: "1.0.0" -component_path: - - path: "./" diff --git a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/inc/btl_gpio_activation_dual_cfg.h b/src/bootloader/extension/bootloader_gpio_activation_dual_extension/inc/btl_gpio_activation_dual_cfg.h deleted file mode 100644 index f9b3a724..00000000 --- a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/inc/btl_gpio_activation_dual_cfg.h +++ /dev/null @@ -1,62 +0,0 @@ -/***************************************************************************//** - * @file - * @brief Configuration header for bootloader Dual GPIO Activation - ******************************************************************************* - * # License - * Copyright 2021 Silicon Laboratories Inc. www.silabs.com - ******************************************************************************* - * - * The licensor of this software is Silicon Laboratories Inc. Your use of this - * software is governed by the terms of Silicon Labs Master Software License - * Agreement (MSLA) available at - * www.silabs.com/about-us/legal/master-software-license-agreement. This - * software is distributed to you in Source Code format and is governed by the - * sections of the MSLA applicable to Source Code. - * - ******************************************************************************/ -#ifndef BTL_GPIO_ACTIVATION_DUAL_CONFIG_H -#define BTL_GPIO_ACTIVATION_DUAL_CONFIG_H - -// <<< Use Configuration Wizard in Context Menu >>> - -// Properties of Bootloader Entry - -// Primary button active state -// Low -// High -// Default: LOW -// Enter firmware upgrade mode if primary GPIO pin has this state -#define NC_PRIMARY_GPIO_ACTIVATION_POLARITY LOW - -// Secondary button active state -// Low -// High -// Default: LOW -// Enter firmware upgrade mode if secondary GPIO pin has this state -#define NC_SECONDARY_GPIO_ACTIVATION_POLARITY LOW - -// - -// <<< end of configuration section >>> - -// <<< sl:start pin_tool >>> - -// NC_BTL_BUTTON_PRIMARY - -// $[GPIO_NC_BTL_BUTTON_PRIMARY] -#warning "Primary GPIO activation port not configured" -//#define NC_BTL_BUTTON_PRIMARY_PORT gpioPortA -//#define NC_BTL_BUTTON_PRIMARY_PIN 6 -// [GPIO_NC_BTL_BUTTON_PRIMARY]$ - -// NC_BTL_BUTTON_SECONDARY - -// $[GPIO_NC_BTL_BUTTON_SECONDARY] -#warning "Secondary GPIO activation port not configured" -//#define NC_BTL_BUTTON_SECONDARY_PORT gpioPortC -//#define NC_BTL_BUTTON_SECONDARY_PIN 5 -// [GPIO_NC_BTL_BUTTON_SECONDARY]$ - -// <<< sl:end pin_tool >>> - -#endif // BTL_GPIO_ACTIVATION_DUAL_CONFIG_H diff --git a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/inc/gpio/gpio-activation/btl_gpio_activation.h b/src/bootloader/extension/bootloader_gpio_activation_dual_extension/inc/gpio/gpio-activation/btl_gpio_activation.h deleted file mode 100644 index a2671ba4..00000000 --- a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/inc/gpio/gpio-activation/btl_gpio_activation.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef BTL_GPIO_ACTIVATION_H -#define BTL_GPIO_ACTIVATION_H - -/***************************************************************************//** - * @addtogroup Components - * @{ - * @addtogroup GpioActivation GPIO Activation - * @brief Enter bootloader based on GPIO state. - * @brief This component provides functionality to enter firmware upgrade mode automatically after reset if a GPIO pin is active during boot. - * @brief The GPIO pin location and polarity are configurable. - * @details - * @{ - * @addtogroup ButtonGPIO Button GPIO - * @brief Enter bootloader based on Button GPIO state. - * @brief By enabling the GPIO activation component, the firmware upgrade mode can be activated by the GPIO configuration. - * @details - * @{ - ******************************************************************************/ - -/***************************************************************************//** - * Enter the bootlader if the GPIO pin is active. - * - * @return True if the bootloader should be entered - ******************************************************************************/ -bool gpio_enterBootloader(void); - -/** @} (end addtogroup Button GPIO) */ -/** @} (end addtogroup GpioActivation) */ -/** @} (end addtogroup Components) */ - -#endif // BTL_GPIO_ACTIVATION_H diff --git a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/src/btl_gpio_activation_dual.c b/src/bootloader/extension/bootloader_gpio_activation_dual_extension/src/btl_gpio_activation_dual.c deleted file mode 100644 index d2a76deb..00000000 --- a/src/bootloader/extension/bootloader_gpio_activation_dual_extension/src/btl_gpio_activation_dual.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "config/btl_config.h" -#include "em_device.h" -#include "em_gpio.h" -#include "gpio/gpio-activation/btl_gpio_activation.h" -#include "btl_gpio_activation_dual_cfg.h" - -#define HIGH 0 -#define LOW 1 - -bool gpio_enterBootloader(void) -{ - bool pressed; - -#if defined(CMU_HFBUSCLKEN0_GPIO) - CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO; -#endif -#if defined(_CMU_CLKEN0_MASK) - CMU->CLKEN0_SET = CMU_CLKEN0_GPIO; -#endif - - GPIO_PinModeSet(NC_BTL_BUTTON_PRIMARY_PORT, NC_BTL_BUTTON_PRIMARY_PIN, gpioModePushPull, NC_PRIMARY_GPIO_ACTIVATION_POLARITY); - GPIO_PinModeSet(NC_BTL_BUTTON_SECONDARY_PORT, NC_BTL_BUTTON_SECONDARY_PIN, gpioModePushPull, NC_SECONDARY_GPIO_ACTIVATION_POLARITY); - for (volatile int i = 0; i < 100; i++); - - GPIO_PinModeSet(NC_BTL_BUTTON_PRIMARY_PORT, NC_BTL_BUTTON_PRIMARY_PIN, gpioModeInputPull, NC_PRIMARY_GPIO_ACTIVATION_POLARITY); - GPIO_PinModeSet(NC_BTL_BUTTON_SECONDARY_PORT, NC_BTL_BUTTON_SECONDARY_PIN, gpioModeInputPull, NC_SECONDARY_GPIO_ACTIVATION_POLARITY); - for (volatile int i = 0; i < 500; i++); - - bool primary_pressed = (GPIO_PinInGet(NC_BTL_BUTTON_PRIMARY_PORT, NC_BTL_BUTTON_PRIMARY_PIN) != NC_PRIMARY_GPIO_ACTIVATION_POLARITY); - bool secondary_pressed = (GPIO_PinInGet(NC_BTL_BUTTON_SECONDARY_PORT, NC_BTL_BUTTON_SECONDARY_PIN) != NC_SECONDARY_GPIO_ACTIVATION_POLARITY); - pressed = primary_pressed || secondary_pressed; - - GPIO_PinModeSet(NC_BTL_BUTTON_PRIMARY_PORT, NC_BTL_BUTTON_PRIMARY_PIN, gpioModeDisabled, NC_PRIMARY_GPIO_ACTIVATION_POLARITY); - GPIO_PinModeSet(NC_BTL_BUTTON_SECONDARY_PORT, NC_BTL_BUTTON_SECONDARY_PIN, gpioModeDisabled, NC_SECONDARY_GPIO_ACTIVATION_POLARITY); - -#if defined(CMU_HFBUSCLKEN0_GPIO) - CMU->HFBUSCLKEN0 &= ~CMU_HFBUSCLKEN0_GPIO; -#endif - - return pressed; -} diff --git a/src/openthread_rcp/CHANGELOG.md b/src/openthread_rcp/CHANGELOG.md index 51763492..9dd661f3 100644 --- a/src/openthread_rcp/CHANGELOG.md +++ b/src/openthread_rcp/CHANGELOG.md @@ -1,3 +1,9 @@ +# SL-OPENTHREAD/3.1.0.0_GitHub-fb274efe6 +This beta release is built with OpenThread 3.1.0 from Simplicity SDK 2026.6.0. + +# SL-OPENTHREAD/3.0.2.0_GitHub-61e43cffb +This beta release is built with OpenThread 3.0.2 from Simplicity SDK 2025.12.3. + # SL-OPENTHREAD/2.7.2.0_GitHub-fb0446f53 This beta release is built with Simplicity SDK 2025.6.2. diff --git a/src/openthread_rcp/openthread_rcp.slcp b/src/openthread_rcp/openthread_rcp.slcp index b9849e11..83182e17 100644 --- a/src/openthread_rcp/openthread_rcp.slcp +++ b/src/openthread_rcp/openthread_rcp.slcp @@ -19,8 +19,13 @@ component: - id: bootloader_interface - id: clock_manager - id: ot_reset_utils - # Platform - Enable LTO for gcc by installing the following component + # Platform - Enable LTO for gcc and llvm by installing the following components - id: toolchain_gcc_lto + condition: + - toolchain_gcc + - id: toolchain_llvm_lto + condition: + - toolchain_llvm include: - path: . diff --git a/src/openthread_rcp/sdk_patches/disable_gp_rx_filter.patch b/src/openthread_rcp/sdk_patches/disable_gp_rx_filter.patch new file mode 100644 index 00000000..14321306 --- /dev/null +++ b/src/openthread_rcp/sdk_patches/disable_gp_rx_filter.patch @@ -0,0 +1,14 @@ +diff --git a/openthread/platform-abstraction/efr32/sl_gp_interface.c b/openthread/platform-abstraction/efr32/sl_gp_interface.c +index b4601a1..226ea80 100644 +--- a/openthread/platform-abstraction/efr32/sl_gp_interface.c ++++ b/openthread/platform-abstraction/efr32/sl_gp_interface.c +@@ -323,7 +323,8 @@ bool sl_gp_intf_is_gp_pkt(otRadioFrame *aFrame) + bool networkVersionCheck = GP_NWK_PROTOCOL_VERSION_CHECK(fc); + bool frameVersionCheck = (efr32GetFrameVersion(aFrame) == IEEE802154_FRAME_VERSION_2003); + +- isGpPkt = (lengthCheck && networkVersionCheck && frameVersionCheck); ++ // Patched out: misclassifies zero-payload 2003 MAC commands (it reads past the frame) ++ isGpPkt = false && (lengthCheck && networkVersionCheck && frameVersionCheck); + #if 0 // Debugging + if (!isGpPkt) + { diff --git a/src/zigbee_ncp/CHANGELOG.md b/src/zigbee_ncp/CHANGELOG.md index b4cdad3a..81f7353e 100644 --- a/src/zigbee_ncp/CHANGELOG.md +++ b/src/zigbee_ncp/CHANGELOG.md @@ -1,3 +1,9 @@ +# 9.1.0.0 +Beta release built with EmberZNet 9.1 from Simplicity SDK 2026.6.0. + +# 9.0.2.0 +Beta release built with EmberZNet 9.0 from Simplicity SDK 2025.12.3. This is our first release that migrates from the older Gecko SDK to the newer Simplicity SDK. + # 7.5.1.0 Beta release built with Gecko SDK 4.5.0. This includes a new feature to restore routes on adapter startup, speeding up network responsiveness after a reset. diff --git a/src/zigbee_ncp/app.c b/src/zigbee_ncp/app.c index a0d2a974..0cc620ad 100644 --- a/src/zigbee_ncp/app.c +++ b/src/zigbee_ncp/app.c @@ -16,16 +16,23 @@ ******************************************************************************/ #include PLATFORM_HEADER -#include "ember.h" +#include "sl_zigbee.h" //---------------------- // Implemented Callbacks /** @brief * - * Application framework equivalent of ::emberRadioNeedsCalibratingHandler + * Application framework equivalent of ::sl_zigbee_radio_needs_calibrating_handler */ -void emberAfRadioNeedsCalibratingCallback(void) +void sl_zigbee_af_radio_needs_calibrating_cb(void) { sl_mac_calibrate_current_channel(); } + +/** @brief Init + * Application init function + */ +void sl_zigbee_af_main_init_cb(void) +{ +} diff --git a/src/zigbee_ncp/extension/xncp_common_extension/config/xncp_config.h b/src/zigbee_ncp/extension/xncp_common_extension/config/xncp_config.h index dfc9f289..7eac5fb8 100644 --- a/src/zigbee_ncp/extension/xncp_common_extension/config/xncp_config.h +++ b/src/zigbee_ncp/extension/xncp_common_extension/config/xncp_config.h @@ -5,7 +5,12 @@ #ifndef XNCP_CONFIG_H_ #define XNCP_CONFIG_H_ +#if defined(SL_CATALOG_IOSTREAM_EUSART_PRESENT) +#include "sl_iostream_eusart.h" +#include "sl_iostream_eusart_vcom_config.h" +#elif defined(SL_CATALOG_IOSTREAM_USART_PRESENT) #include "sl_iostream_usart_vcom_config.h" +#endif // <<< Use Configuration Wizard in Context Menu >>> @@ -40,7 +45,13 @@ // Default: auto-detect from UART config (SL_IOSTREAM_USART_VCOM_FLOW_CONTROL_TYPE) // Override only if external flow control differs from internal UART (e.g. ZBT-2) #ifndef XNCP_FLOW_CONTROL_TYPE -#define XNCP_FLOW_CONTROL_TYPE SL_IOSTREAM_USART_VCOM_FLOW_CONTROL_TYPE + #if defined(SL_CATALOG_IOSTREAM_EUSART_PRESENT) + #define XNCP_FLOW_CONTROL_TYPE_DEFAULT SL_IOSTREAM_EUSART_VCOM_FLOW_CONTROL_TYPE + #else + #define XNCP_FLOW_CONTROL_TYPE_DEFAULT SL_IOSTREAM_USART_VCOM_FLOW_CONTROL_TYPE + #endif + + #define XNCP_FLOW_CONTROL_TYPE XNCP_FLOW_CONTROL_TYPE_DEFAULT #endif // EZSP version patch number override diff --git a/src/zigbee_ncp/extension/xncp_common_extension/src/xncp_common_commands.c b/src/zigbee_ncp/extension/xncp_common_extension/src/xncp_common_commands.c index a04ed771..c82364b9 100644 --- a/src/zigbee_ncp/extension/xncp_common_extension/src/xncp_common_commands.c +++ b/src/zigbee_ncp/extension/xncp_common_extension/src/xncp_common_commands.c @@ -8,11 +8,17 @@ #include "xncp_types.h" #include "xncp_config.h" #include "tx_power.h" -#include "ember.h" #include "ezsp-enum.h" #include "em_usart.h" #include "random.h" + +#if defined(SL_CATALOG_IOSTREAM_EUSART_PRESENT) +#include "sl_iostream_eusart.h" +#include "sl_iostream_eusart_vcom_config.h" +#elif defined(SL_CATALOG_IOSTREAM_USART_PRESENT) #include "sl_iostream_usart_vcom_config.h" +#endif + #include #define BUILD_UINT16(low, high) (((uint16_t)(low)) | ((uint16_t)(high) << 8)) @@ -23,17 +29,17 @@ typedef enum { } XncpFlowControlType; typedef enum { - EMBER_ROUTE_ACTIVE = 0, - EMBER_ROUTE_BEING_DISCOVERED = 1, - EMBER_ROUTE_UNUSED = 3, - EMBER_ROUTE_VALIDATING = 4 -} EmberRouteStatus; + ROUTE_ACTIVE = 0, + ROUTE_BEING_DISCOVERED = 1, + ROUTE_UNUSED = 3, + ROUTE_VALIDATING = 4 +} RouteStatus; typedef struct ManualSourceRoute { bool active; uint16_t destination; uint8_t num_relays; - uint16_t relays[EMBER_MAX_SOURCE_ROUTE_RELAY_COUNT]; + uint16_t relays[XNCP_MAX_SOURCE_ROUTE_RELAY_COUNT]; } ManualSourceRoute; static ManualSourceRoute manual_source_routes[XNCP_MANUAL_SOURCE_ROUTE_TABLE_SIZE]; @@ -88,7 +94,7 @@ void xncp_common_init(uint8_t init_level) // Multicast override (XNCP_FEATURE_MEMBER_OF_ALL_GROUPS) //------------------------------------------------------------------------------ -bool __wrap_sli_zigbee_am_multicast_member(EmberMulticastId multicastId) +bool __wrap_sli_zigbee_am_multicast_member(xncp_multicast_id_t multicastId) { (void)multicastId; // Ignore all binding and multicast table logic, we want all group packets @@ -99,7 +105,7 @@ bool __wrap_sli_zigbee_am_multicast_member(EmberMulticastId multicastId) // Source route management (XNCP_FEATURE_MANUAL_SOURCE_ROUTE) //------------------------------------------------------------------------------ -static ManualSourceRoute* get_manual_source_route(EmberNodeId destination) +static ManualSourceRoute* get_manual_source_route(xncp_node_id_t destination) { for (uint8_t i = 0; i < XNCP_MANUAL_SOURCE_ROUTE_TABLE_SIZE; i++) { if (manual_source_routes[i].active && @@ -110,7 +116,7 @@ static ManualSourceRoute* get_manual_source_route(EmberNodeId destination) return NULL; } -static sli_zigbee_route_table_entry_t* find_free_routing_table_entry(EmberNodeId destination) +static sli_zigbee_route_table_entry_t* find_free_routing_table_entry(xncp_node_id_t destination) { uint8_t index = 0xFF; sli_zigbee_route_table_entry_t *route_table_entry = NULL; @@ -120,14 +126,14 @@ static sli_zigbee_route_table_entry_t* find_free_routing_table_entry(EmberNodeId if (route_table_entry->destination == destination) { return route_table_entry; - } else if (route_table_entry->status == EMBER_ROUTE_UNUSED) { + } else if (route_table_entry->status == ROUTE_UNUSED) { index = i; continue; } } if (index == 0xFF) { - index = emberGetPseudoRandomNumber() % sli_zigbee_route_table_size; + index = xncp_get_pseudo_random_number() % sli_zigbee_route_table_size; } return &sli_zigbee_route_table[index]; @@ -138,7 +144,7 @@ void nc_zigbee_override_append_source_route(uint16_t destination, void *header, bool *consumed) { - EmberMessageBuffer *msg_header = (EmberMessageBuffer *)header; + xncp_message_buffer_t *msg_header = (xncp_message_buffer_t *)header; ManualSourceRoute *route = get_manual_source_route(destination); if (route == NULL) { @@ -154,7 +160,7 @@ void nc_zigbee_override_append_source_route(uint16_t destination, sli_zigbee_route_table_entry_t *route_table_entry = find_free_routing_table_entry(route->destination); route_table_entry->destination = route->destination; route_table_entry->nextHop = route->destination; - route_table_entry->status = EMBER_ROUTE_ACTIVE; + route_table_entry->status = ROUTE_ACTIVE; route_table_entry->cost = 0; route_table_entry->networkIndex = 0; return; @@ -164,29 +170,29 @@ void nc_zigbee_override_append_source_route(uint16_t destination, route->active = false; // Disable the route after a single use - emberAppendToLinkedBuffers(*msg_header, &route->num_relays, 1); - emberAppendToLinkedBuffers(*msg_header, &relay_index, 1); + xncp_append_to_linked_buffers(*msg_header, &route->num_relays, 1); + xncp_append_to_linked_buffers(*msg_header, &relay_index, 1); for (uint8_t i = 0; i < route->num_relays; i++) { - emberAppendToLinkedBuffers(*msg_header, (uint8_t*)&route->relays[route->num_relays - i - 1], 2); + xncp_append_to_linked_buffers(*msg_header, (uint8_t*)&route->relays[route->num_relays - i - 1], 2); } } static bool handle_set_source_route(xncp_context_t *ctx) { if ((ctx->payload_length < 2) || (ctx->payload_length % 2 != 0)) { - *ctx->status = EMBER_BAD_ARGUMENT; + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } uint8_t num_relays = (ctx->payload_length - 2) / 2; - if (num_relays > EMBER_MAX_SOURCE_ROUTE_RELAY_COUNT) { - *ctx->status = EMBER_BAD_ARGUMENT; + if (num_relays > XNCP_MAX_SOURCE_ROUTE_RELAY_COUNT) { + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } - uint8_t insertion_index = emberGetPseudoRandomNumber() % XNCP_MANUAL_SOURCE_ROUTE_TABLE_SIZE; + uint8_t insertion_index = xncp_get_pseudo_random_number() % XNCP_MANUAL_SOURCE_ROUTE_TABLE_SIZE; uint16_t node_id = BUILD_UINT16(ctx->payload[0], ctx->payload[1]); for (uint8_t i = 0; i < XNCP_MANUAL_SOURCE_ROUTE_TABLE_SIZE; i++) { @@ -211,7 +217,7 @@ static bool handle_set_source_route(xncp_context_t *ctx) route->num_relays = num_relays; route->active = true; - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } @@ -222,13 +228,13 @@ static bool handle_set_source_route(xncp_context_t *ctx) static bool handle_set_route_table_entry(xncp_context_t *ctx) { if (ctx->payload_length != 7) { - *ctx->status = EMBER_BAD_ARGUMENT; + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } uint8_t route_table_index = ctx->payload[0]; if (route_table_index >= sli_zigbee_route_table_size) { - *ctx->status = EMBER_BAD_ARGUMENT; + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } @@ -239,20 +245,20 @@ static bool handle_set_route_table_entry(xncp_context_t *ctx) entry->cost = ctx->payload[6]; entry->networkIndex = 0; - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } static bool handle_get_route_table_entry(xncp_context_t *ctx) { if (ctx->payload_length != 1) { - *ctx->status = EMBER_BAD_ARGUMENT; + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } uint8_t route_table_index = ctx->payload[0]; if (route_table_index >= sli_zigbee_route_table_size) { - *ctx->status = EMBER_BAD_ARGUMENT; + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } @@ -267,7 +273,7 @@ static bool handle_get_route_table_entry(xncp_context_t *ctx) ctx->reply[(*ctx->reply_length)++] = entry->status; ctx->reply[(*ctx->reply_length)++] = entry->cost; - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } @@ -278,7 +284,7 @@ static bool handle_get_route_table_entry(xncp_context_t *ctx) static bool handle_get_mfg_token_override(xncp_context_t *ctx) { if (ctx->payload_length != 1) { - *ctx->status = EMBER_BAD_ARGUMENT; + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } @@ -286,16 +292,16 @@ static bool handle_get_mfg_token_override(xncp_context_t *ctx) char *override_value; switch (token_id) { - case EZSP_MFG_STRING: + case SL_ZIGBEE_EZSP_MFG_STRING: override_value = XNCP_MFG_MANUF_NAME; break; - case EZSP_MFG_BOARD_NAME: + case SL_ZIGBEE_EZSP_MFG_BOARD_NAME: override_value = XNCP_MFG_BOARD_NAME; break; default: - *ctx->status = EMBER_NOT_FOUND; + *ctx->status = XNCP_STATUS_NOT_FOUND; return true; } @@ -303,7 +309,7 @@ static bool handle_get_mfg_token_override(xncp_context_t *ctx) memcpy(ctx->reply + *ctx->reply_length, override_value, value_length); *ctx->reply_length += value_length; - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } @@ -313,7 +319,7 @@ static bool handle_get_build_string(xncp_context_t *ctx) memcpy(ctx->reply + *ctx->reply_length, XNCP_BUILD_STRING, value_length); *ctx->reply_length += value_length; - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } @@ -334,7 +340,7 @@ static bool handle_get_flow_control_type(xncp_context_t *ctx) ctx->reply[(*ctx->reply_length)++] = (uint8_t)(flow_control_type & 0xFF); - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } @@ -353,7 +359,7 @@ static bool handle_get_chip_info(xncp_context_t *ctx) memcpy(ctx->reply + *ctx->reply_length, PART_NUMBER, value_length); *ctx->reply_length += value_length; - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } @@ -361,14 +367,14 @@ static bool handle_get_chip_info(xncp_context_t *ctx) static bool handle_get_tx_power_info(xncp_context_t *ctx) { if (ctx->payload_length != 2) { - *ctx->status = EMBER_BAD_ARGUMENT; + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } - + CountryTxPower result; get_tx_power_for_country(ctx->payload[0], ctx->payload[1], &result); - - *ctx->status = EMBER_SUCCESS; + + *ctx->status = XNCP_STATUS_OK; ctx->reply[(*ctx->reply_length)++] = (uint8_t)result.recommended_power_dbm; ctx->reply[(*ctx->reply_length)++] = (uint8_t)result.max_power_dbm; diff --git a/src/zigbee_ncp/extension/xncp_extension/inc/xncp_types.h b/src/zigbee_ncp/extension/xncp_extension/inc/xncp_types.h index 68a9b0b6..7bd26a20 100644 --- a/src/zigbee_ncp/extension/xncp_extension/inc/xncp_types.h +++ b/src/zigbee_ncp/extension/xncp_extension/inc/xncp_types.h @@ -10,6 +10,51 @@ #include #include +// SDK compatibility layer +#ifdef STACK_TYPES_HEADER +// Simplicity SDK (2025.x) +#include "stack/include/sl_zigbee.h" +#include "stack/include/sl_zigbee_types_internal.h" +#include "stack/include/message.h" + +typedef sl_status_t xncp_status_t; +#define XNCP_STATUS_OK SL_STATUS_OK +#define XNCP_STATUS_BAD_ARGUMENT SL_STATUS_INVALID_PARAMETER +#define XNCP_STATUS_NOT_FOUND SL_STATUS_NOT_FOUND + +#define XNCP_MAX_SOURCE_ROUTE_RELAY_COUNT SL_ZIGBEE_MAX_SOURCE_ROUTE_RELAY_COUNT + +typedef sl_zigbee_multicast_id_t xncp_multicast_id_t; +typedef sl_802154_short_addr_t xncp_node_id_t; +typedef sli_buffer_manager_buffer_t xncp_message_buffer_t; + +#define xncp_get_pseudo_random_number sl_zigbee_get_pseudo_random_number +#define xncp_append_to_linked_buffers sl_legacy_buffer_manager_append_to_linked_buffers + +#else +// Gecko SDK (4.x) +#include "ember.h" + +typedef EmberStatus xncp_status_t; +#define XNCP_STATUS_OK EMBER_SUCCESS +#define XNCP_STATUS_BAD_ARGUMENT EMBER_BAD_ARGUMENT +#define XNCP_STATUS_NOT_FOUND EMBER_NOT_FOUND + +#define XNCP_MAX_SOURCE_ROUTE_RELAY_COUNT EMBER_MAX_SOURCE_ROUTE_RELAY_COUNT + +typedef EmberMulticastId xncp_multicast_id_t; +typedef EmberNodeId xncp_node_id_t; +typedef EmberMessageBuffer xncp_message_buffer_t; + +#define xncp_get_pseudo_random_number emberGetPseudoRandomNumber +#define xncp_append_to_linked_buffers emberAppendToLinkedBuffers + +// EZSP enum aliases for new SDK names +#define SL_ZIGBEE_EZSP_MFG_STRING EZSP_MFG_STRING +#define SL_ZIGBEE_EZSP_MFG_BOARD_NAME EZSP_MFG_BOARD_NAME + +#endif + // Feature flags - components OR these together #define XNCP_FEATURE_MEMBER_OF_ALL_GROUPS (1UL << 0) #define XNCP_FEATURE_MANUAL_SOURCE_ROUTE (1UL << 1) diff --git a/src/zigbee_ncp/extension/xncp_extension/src/xncp_core.c b/src/zigbee_ncp/extension/xncp_extension/src/xncp_core.c index 40578aee..683095e5 100644 --- a/src/zigbee_ncp/extension/xncp_extension/src/xncp_core.c +++ b/src/zigbee_ncp/extension/xncp_extension/src/xncp_core.c @@ -6,21 +6,20 @@ #include "xncp_types.h" #include "xncp_dispatcher.h" -#include "ember.h" #define BUILD_UINT16(low, high) (((uint16_t)(low)) | ((uint16_t)(high) << 8)) -EmberStatus emberAfPluginXncpIncomingCustomFrameCallback( +static xncp_status_t xncp_incoming_custom_frame_handler( uint8_t messageLength, uint8_t *messagePayload, uint8_t *replyPayloadLength, uint8_t *replyPayload) { - uint8_t rsp_status = EMBER_SUCCESS; + uint8_t rsp_status = XNCP_STATUS_OK; uint16_t rsp_command_id = XNCP_CMD_UNKNOWN; if (messageLength < 3) { - rsp_status = EMBER_BAD_ARGUMENT; + rsp_status = XNCP_STATUS_BAD_ARGUMENT; goto respond; } @@ -57,12 +56,34 @@ EmberStatus emberAfPluginXncpIncomingCustomFrameCallback( }; if (!xncp_dispatch_command(&ctx)) { - rsp_status = EMBER_NOT_FOUND; + rsp_status = XNCP_STATUS_NOT_FOUND; } respond: replyPayload[0] = (uint8_t)((rsp_command_id >> 0) & 0xFF); replyPayload[1] = (uint8_t)((rsp_command_id >> 8) & 0xFF); replyPayload[2] = rsp_status; - return EMBER_SUCCESS; + return XNCP_STATUS_OK; +} + +#ifdef STACK_TYPES_HEADER +sl_status_t sl_zigbee_af_xncp_incoming_custom_frame_cb( + uint8_t messageLength, + uint8_t *messagePayload, + uint8_t *replyPayloadLength, + uint8_t *replyPayload) +{ + return xncp_incoming_custom_frame_handler(messageLength, messagePayload, + replyPayloadLength, replyPayload); +} +#else +EmberStatus emberAfPluginXncpIncomingCustomFrameCallback( + uint8_t messageLength, + uint8_t *messagePayload, + uint8_t *replyPayloadLength, + uint8_t *replyPayload) +{ + return xncp_incoming_custom_frame_handler(messageLength, messagePayload, + replyPayloadLength, replyPayload); } +#endif diff --git a/src/zigbee_ncp/extension/xncp_zbt2_extension/src/xncp_zbt2_commands.c b/src/zigbee_ncp/extension/xncp_zbt2_extension/src/xncp_zbt2_commands.c index ffc55180..87236a37 100644 --- a/src/zigbee_ncp/extension/xncp_zbt2_extension/src/xncp_zbt2_commands.c +++ b/src/zigbee_ncp/extension/xncp_zbt2_extension/src/xncp_zbt2_commands.c @@ -12,7 +12,6 @@ #include "led_manager.h" #include "sl_i2cspm_instances.h" #include "sl_simple_rgb_pwm_led.h" -#include "ember.h" #include //------------------------------------------------------------------------------ @@ -49,13 +48,13 @@ static bool handle_set_led_state(xncp_context_t *ctx) color.g = ((uint16_t)ctx->payload[2] << 8) | ctx->payload[3]; color.b = ((uint16_t)ctx->payload[4] << 8) | ctx->payload[5]; } else { - *ctx->status = EMBER_BAD_ARGUMENT; + *ctx->status = XNCP_STATUS_BAD_ARGUMENT; return true; } led_manager_set_color(LED_PRIORITY_MANUAL, color); - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } @@ -76,6 +75,6 @@ static bool handle_get_accelerometer(xncp_context_t *ctx) memcpy(ctx->reply + *ctx->reply_length, (uint8_t*)&xyz[2], sizeof(float)); *ctx->reply_length += sizeof(float); - *ctx->status = EMBER_SUCCESS; + *ctx->status = XNCP_STATUS_OK; return true; } diff --git a/src/zigbee_ncp/main.c b/src/zigbee_ncp/main.c index e3c41b0a..0abba207 100644 --- a/src/zigbee_ncp/main.c +++ b/src/zigbee_ncp/main.c @@ -3,75 +3,76 @@ * @brief main() function. ******************************************************************************* * # License - * Copyright 2021 Silicon Laboratories Inc. www.silabs.com + * Copyright 2025 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * - * The licensor of this software is Silicon Laboratories Inc. Your use of this - * software is governed by the terms of Silicon Labs Master Software License - * Agreement (MSLA) available at - * www.silabs.com/about-us/legal/master-software-license-agreement. This - * software is distributed to you in Source Code format and is governed by the - * sections of the MSLA applicable to Source Code. + * SPDX-License-Identifier: Zlib + * + * The licensor of this software is Silicon Laboratories Inc. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ - -#ifdef SL_COMPONENT_CATALOG_PRESENT #include "sl_component_catalog.h" -#endif -#include "sl_system_init.h" +#include "sl_main_init.h" #if defined(SL_CATALOG_POWER_MANAGER_PRESENT) #include "sl_power_manager.h" #endif #if defined(SL_CATALOG_KERNEL_PRESENT) -#include "sl_system_kernel.h" -#else -#include "sl_system_process_action.h" -#endif // SL_CATALOG_KERNEL_PRESENT - -#ifdef EMBER_TEST -#define main nodeMain -#endif - -void app_init(void) -{ -} - -void app_process_action(void) -{ -} +#include "sl_main_kernel.h" +#else // SL_CATALOG_KERNEL_PRESENT +#include "sl_main_process_action.h" +#endif // SL_CATALOG_KERNEL_PRESENT +#ifdef SL_ZIGBEE_TEST +int nodeMain(void) +#else #if defined(__ICCARM__) #pragma diag_suppress=Pe111 #endif // defined(__ICCARM__) int main(void) +#endif { // Initialize Silicon Labs device, system, service(s) and protocol stack(s). - // Note that if the kernel is present, processing task(s) will be created by - // this call. - sl_system_init(); - - // Initialize the application. For example, create periodic timer(s) or - // task(s) if the kernel is present. - app_init(); + // Note that if the kernel is present, the start task will be started and software component + // configuration will take place there. + sl_main_init(); #if defined(SL_CATALOG_KERNEL_PRESENT) - // Start the kernel. Task(s) created in app_init() will start running. - sl_system_kernel_start(); + // Start the kernel. The start task will be executed (Highest priority) to complete + // the Simplicity SDK components initialization and the user app_init() hook function will be called. + sl_main_kernel_start(); #else // SL_CATALOG_KERNEL_PRESENT + + // User provided code. + app_init(); + while (1) { - // Do not remove this call: Silicon Labs components process action routine + // Silicon Labs components process action routine // must be called from the super loop. - sl_system_process_action(); + sl_main_process_action(); - // Application process. + // User provided code. Application process. app_process_action(); - // Let the CPU go to sleep if the system allow it. #if defined(SL_CATALOG_POWER_MANAGER_PRESENT) + // Let the CPU go to sleep if the system allows it. sl_power_manager_sleep(); -#endif // SL_CATALOG_POWER_MANAGER_PRESENT +#endif } #endif // SL_CATALOG_KERNEL_PRESENT - - return 0; } diff --git a/src/zigbee_ncp/zigbee_ncp.slcp b/src/zigbee_ncp/zigbee_ncp.slcp index 93990a4d..d6abf647 100644 --- a/src/zigbee_ncp/zigbee_ncp.slcp +++ b/src/zigbee_ncp/zigbee_ncp.slcp @@ -7,49 +7,77 @@ description: Zigbee NCP firmware. Derived from the `ncp-uart-hw` example Gecko S author: Nabu Casa component: + - id: sl_main - id: iostream_usart instance: - vcom + condition: + - device_generic_family_efr32xg21 + - id: iostream_eusart + instance: + - vcom + condition: + - device_has_eusart - id: zigbee_debug_print - id: iostream_vuart - - id: token_manager + - id: common_token_manager - id: zigbee_token_interface - id: zigbee_mfglib - id: zigbee_pro_stack - id: zigbee_source_route - id: zigbee_gp - id: zigbee_r22_support + - id: zigbee_r23_support + - id: zigbee_dynamic_commissioning - id: zigbee_security_link_keys - id: zigbee_zll - - id: zigbee_app_framework_common + - id: zigbee_system_common - id: zigbee_ncp_uart_hardware - id: zigbee_debug_basic - id: zigbee_debug_extended - id: zigbee_xncp - id: rail_util_rssi - id: legacy_hal_wdog + - id: clock_manager + # Platform - enable LTO for gcc and llvm + - id: toolchain_gcc_lto + condition: + - toolchain_gcc + - id: toolchain_llvm_lto + condition: + - toolchain_llvm define: - - name: EMBER_CUSTOM_MAC_FILTER_TABLE_SIZE - value: 15 + - name: SL_ZIGBEE_CUSTOM_MAC_FILTER_TABLE_SIZE + value: 2 + +# Prevent LTO from stripping sl_zigbee_version, which is read from the ELF +# by create_gbl.py to extract the EZSP version for firmware metadata. +toolchain_settings: + - option: gcc_linker_option + value: "-Wl,--undefined=sl_zigbee_version" configuration: - name: SL_CLI_MAX_INPUT_ARGUMENTS value: 16 - name: SL_BOARD_ENABLE_VCOM value: 1 + condition: + - iostream_usart + - name: SL_IOSTREAM_EUSART_VCOM_FLOW_CONTROL_TYPE + value: SL_IOSTREAM_EUSART_UART_FLOW_CTRL_CTS_RTS + condition: + - iostream_eusart - name: SL_IOSTREAM_USART_VCOM_FLOW_CONTROL_TYPE value: usartHwFlowControlCtsAndRts - name: SL_CLI_EXAMPLE_IOSTREAM_HANDLE value: sl_iostream_vuart_handle - - name: NVM3_DEFAULT_NVM_SIZE - value: 36864 - condition: - - device_series_1 - name: NVM3_DEFAULT_NVM_SIZE value: 32768 condition: - device_series_2 + - name: SL_ZIGBEE_PACKET_BUFFER_HEAP_SIZE + value: SL_ZIGBEE_LARGE_PACKET_BUFFER_HEAP # If using zigbee_secure_key_storage we do not need to support backwards # compatibility because we have never deployed images with keys in PSA # As a result, these lines end up saving some code space @@ -59,7 +87,15 @@ configuration: value: 0 - name: SL_PSA_ITS_SUPPORT_V3_DRIVER value: 1 - - name: EMBER_AF_PLUGIN_PACKET_HANDOFF_ALLOW_ALL_PACKETS + - name: SL_STACK_SIZE + value: 4096 + condition: + - cmsis_rtos2 + - name: SL_ZIGBEE_STACK_RTOS_TASK_STACK_SIZE + value: 4096 + condition: + - cmsis_rtos2 + - name: SL_ZIGBEE_AF_PLUGIN_PACKET_HANDOFF_ALLOW_ALL_PACKETS value: 1 - name: SL_LEGACY_HAL_DISABLE_WATCHDOG value: 0 diff --git a/src/zigbee_router/zigbee_router.slcp b/src/zigbee_router/zigbee_router.slcp index ac455e17..68e00f8e 100644 --- a/src/zigbee_router/zigbee_router.slcp +++ b/src/zigbee_router/zigbee_router.slcp @@ -53,10 +53,22 @@ component: - id: zigbee_basic - id: zigbee_scan_dispatch - id: zigbee_update_tc_link_key + - id: zigbee_update_app_link_key + - id: zigbee_security_link_keys - id: clock_manager + - id: zigbee_dynamic_commissioning + - id: zigbee_trust_center_keepalive + - id: zigbee_poll_control_client + - id: zigbee_bdb_3dot1_rejoin_algorithm + # - id: zigbee_bdb_3dot1_trust_center_extension # Unnecessary for a simple router - id: zigbee_application_bootloader - # Platform - enable LTO for gcc + # Platform - enable LTO for gcc and llvm - id: toolchain_gcc_lto + condition: + - toolchain_gcc + - id: toolchain_llvm_lto + condition: + - toolchain_llvm # Custom router components - id: router_nvram_reset vendor: nabucasa @@ -87,7 +99,7 @@ configuration: - name: SLI_ZIGBEE_PRIMARY_NETWORK_DEVICE_TYPE value: SLI_ZIGBEE_NETWORK_DEVICE_TYPE_ROUTER - name: SLI_ZIGBEE_PRIMARY_NETWORK_SECURITY_TYPE - value: SLI_ZIGBEE_NETWORK_SECURITY_TYPE_3_0 + value: SLI_ZIGBEE_NETWORK_SECURITY_TYPE_4_0 - name: SL_CLI_PROMPT_STRING value: "\"zigbee_router>\"" - name: NVM3_DEFAULT_NVM_SIZE @@ -165,6 +177,12 @@ configuration: value: 2000 condition: - device_series_3 + - name: SL_ZIGBEE_AF_PLUGIN_NETWORK_STEERING_ENABLE_AUTOSTART + value: 0 + - name: SL_ZIGBEE_AF_PLUGIN_TRUST_CENTER_KEEPALIVE_DEFAULT_BASE_PERIOD_MINUTES + value: 1 + - name: SL_ZIGBEE_AF_PLUGIN_TRUST_CENTER_KEEPALIVE_DEFAULT_JITTER_PERIOD_SECONDS + value: 30 source: - path: main.c diff --git a/src/zwa2_controller/CHANGELOG.md b/src/zwa2_controller/CHANGELOG.md index 12f6d3b9..e46f8afe 100644 --- a/src/zwa2_controller/CHANGELOG.md +++ b/src/zwa2_controller/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.3.0 +* SDK updated to Simplicity SDK 2025.12.3 (Z-Wave SDK 8.0.2) + # 1.2.0 * SDK updated to Simplicity SDK 2025.12.1. diff --git a/src/zwa2_controller/README.md b/src/zwa2_controller/README.md index 08524e00..075285e9 100644 --- a/src/zwa2_controller/README.md +++ b/src/zwa2_controller/README.md @@ -22,11 +22,14 @@ Examples: | `0` | [`2024.12.1`][sisdk-2024.12.1] | [`7.23.1`][zdk-7.23.1] | | `1` | [`2024.12.2`][sisdk-2024.12.2] | [`7.23.2`][zdk-7.23.2] | | `2` | [`2025.12.1`][sisdk-2025.12.1] | [`8.0.0`][zdk-8.0.0] | +| `3` | [`2025.12.3`][sisdk-2025.12.3] | [`8.0.2`][zdk-8.0.2] | [sisdk-2024.12.1]: https://github.com/SiliconLabs/simplicity_sdk/releases/tag/v2024.12.1-0 [sisdk-2024.12.2]: https://github.com/SiliconLabs/simplicity_sdk/releases/tag/v2024.12.2 [sisdk-2025.12.1]: https://docs.silabs.com/sisdk-release-notes/2025.12.1/sisdk-release-notes-overview/ +[sisdk-2025.12.3]: https://docs.silabs.com/sisdk-release-notes/2025.12.3/sisdk-release-notes-overview/ [zdk-7.23.1]: https://www.silabs.com/documents/public/release-notes/SRN14930-7.23.1.0.pdf [zdk-7.23.2]: https://www.silabs.com/documents/public/release-notes/SRN14930-7.23.2.0.pdf [zdk-8.0.0]: https://docs.silabs.com/sisdk-release-notes/2025.12.1/sisdk-zwave-release-notes/ +[zdk-8.0.2]: https://docs.silabs.com/sisdk-release-notes/2025.12.3/sisdk-zwave-release-notes/ diff --git a/src/zwa2_controller/app.c b/src/zwa2_controller/app.c index 512f955d..56a1dd61 100644 --- a/src/zwa2_controller/app.c +++ b/src/zwa2_controller/app.c @@ -40,6 +40,9 @@ #if defined(SL_CATALOG_POWER_MANAGER_PRESENT) #include "sl_power_manager.h" #endif +#ifdef SL_CATALOG_ZW_HOST_HIBERNATION_PRESENT +#include "sl_host_hibernation_api.h" +#endif #include #include "led_effects_zwa2.h" @@ -59,6 +62,11 @@ #include "zw_shutdown_manager.h" #endif +#ifdef SL_CATALOG_ZW_JAMMING_DETECTION_PRESENT +#include "sl_jamming_detection.h" +#include "sl_jamming_cmd_handlers.h" +#endif + /* Basic level definitions */ #define BASIC_ON 0xFF #define BASIC_OFF 0x00 @@ -141,6 +149,9 @@ zpal_reset_reason_t g_eApplResetReason; bool bTxStatusReportEnabled; +static void (*m_urgent_app_callback)(const SZwaveReceivePackage *) = NULL; +static bool (*m_keep_alive_callback)(node_id_t) = NULL; + static void ApplicationInitSW(void); static void ApplicationTask(SApplicationHandles *pAppHandles); @@ -149,7 +160,7 @@ static bool request_protocol_cc_encryption(SZwaveReceivePackage *pRPCCEPackage); #endif #ifdef ZW_CONTROLLER_BRIDGE -static void ApplicationCommandHandler_Bridge(SReceiveMulti *pReciveMulti); +void ApplicationCommandHandler_Bridge(SReceiveMulti *pReciveMulti); #else void ApplicationCommandHandler(void *pSubscriberContext, SZwaveReceivePackage* pRxPackage); #endif @@ -168,10 +179,6 @@ extern void ZCB_ComplHandler_ZW_ReplaceFailedNode(uint8_t bStatus); extern void ZCB_ComplHandler_ZW_SetSlaveLearnMode(uint8_t bStatus, uint8_t orgID, uint8_t newID); #endif -#if SUPPORT_ZW_SET_RF_RECEIVE_MODE -extern uint8_t SetRFReceiveMode(uint8_t mode); -#endif - ZW_WEAK void cmds_power_management_init(void) { // Do nothing @@ -314,12 +321,28 @@ void zaf_event_distributor_app_zw_rx(SZwaveReceivePackage *RxPackage) switch (RxPackage->eReceiveType) { case EZWAVERECEIVETYPE_SINGLE: #ifndef ZW_CONTROLLER_BRIDGE +#ifdef SL_CATALOG_ZW_HOST_HIBERNATION_PRESENT + if (is_host_sleeping()) { + node_id_t node_id = RxPackage->uReceiveParams.Rx.RxOptions.sourceNode; + const uint8_t * const payload = (uint8_t*) &RxPackage->uReceiveParams.Rx.Payload; + s2_message_update_count(node_id, payload); + break; + } +#endif ApplicationCommandHandler(NULL, RxPackage); #endif break; #ifdef ZW_CONTROLLER_BRIDGE case EZWAVERECEIVETYPE_MULTI: +#ifdef SL_CATALOG_ZW_HOST_HIBERNATION_PRESENT + if (is_host_sleeping()) { + node_id_t node_id = RxPackage->uReceiveParams.RxMulti.RxOptions.sourceNode; + const uint8_t * const payload = (uint8_t*) &RxPackage->uReceiveParams.RxMulti.Payload; + s2_message_update_count(node_id, payload); + break; + } +#endif ApplicationCommandHandler_Bridge(&RxPackage->uReceiveParams.RxMulti); break; #endif // #ifdef ZW_CONTROLLER_BRIDGE @@ -337,6 +360,18 @@ void zaf_event_distributor_app_zw_rx(SZwaveReceivePackage *RxPackage) ?ERPCCEEVENT_SERIALAPI_OK : ERPCCEEVENT_SERIALAPI_FAIL); break; #endif + case EZWAVERECEIVETYPE_SINGLE_URGENT: + if (m_urgent_app_callback != NULL) { + m_urgent_app_callback(RxPackage); + } else { +#ifndef ZW_CONTROLLER_BRIDGE + ApplicationCommandHandler(NULL, RxPackage); +#else + ApplicationCommandHandler_Bridge(&RxPackage->uReceiveParams.RxMulti); +#endif + } + break; + default: break; } @@ -393,6 +428,11 @@ void zaf_event_distributor_app_zw_command_status(SZwaveCommandStatusPackage *Sta } #endif #endif + case EZWAVECOMMANDSTATUS_KEEP_ALIVE_UPDATE: + if (m_keep_alive_callback != NULL) { + m_keep_alive_callback(Status->Content.KeepAliveUpdate.nodeId); + } + break; default: break; } @@ -488,6 +528,11 @@ ApplicationTask(SApplicationHandles* pAppHandles) #endif zaf_event_distributor_init(); +#ifdef SL_CATALOG_ZW_HOST_HIBERNATION_PRESENT + keep_alive_init(); + gpio_wakeup_host_init(); +#endif + set_state_and_notify(stateStartup); // Wait for and process events ZPAL_LOG_DEBUG(ZPAL_LOG_APP, "SerialApi Event processor Started\r\n"); @@ -554,7 +599,6 @@ static void SerialAPIStateHandler(void) case stateStartup: { ApplicationInitSW(); - SetRFReceiveMode(1); set_state_and_notify(stateIdle); } break; @@ -791,6 +835,62 @@ ApplicationInitSW(void) cmds_power_management_init(); } +/** + * @brief Callback from rssi collection: + * - send proprietary Serial API frame 0xF1 to host. + * - Subcommands + * -- 0x01: Collection + * - Payload is 4 bytes: + * rssi[0] rssi on channel 0 + * rssi[1] rssi on channel 1 + * rssi[2] rssi on channel 2 + * rssi[3] rssi on channel LR Channel A + * rssi[4] rssi on channel LR Channel B + */ +#ifdef SL_CATALOG_ZW_JAMMING_DETECTION_PRESENT +static zpal_status_t application_rssi_collection_callback(const sl_jamming_detection_collection_t *collection) +{ + zpal_status_t status = ZPAL_STATUS_FAIL; + struct __attribute__((packed)) { + uint8_t sub_command; + sl_jamming_detection_collection_t payload; + } collection_packet = { + .sub_command = FUNC_ID_PROP_JAMMING_SUBCOMMAND_COLLECTION, + .payload = *collection + }; + + status = RequestUnsolicited(FUNC_ID_PROP_JAMMING_DETECTION_COMMAND, (uint8_t *)&collection_packet, sizeof(collection_packet)) ? ZPAL_STATUS_OK : ZPAL_STATUS_FAIL; + return status; +} + +/** + * Callback from jamming detection ZPAL: + * - send proprietary Serial API frame 0xF1 to host. + * - Subcommands + * -- 0x00: Report + * - Payload 1 byte is : jammed channels bitmap. + * 0b00000001 = channel 0 is jammed + * 0b00000010 = channel 1 is jammed + * 0b00000100 = channel 2 is jammed + * 0b00001000 = channel LR A is jammed + * 0b00010000 = channel LR B is jammed + */ +static zpal_status_t application_jamming_detected_callback(const sl_jamming_detection_statistics_t *report) +{ + zpal_status_t status = ZPAL_STATUS_FAIL; + struct __attribute__((packed)) { + uint8_t sub_command; + sl_jamming_detection_statistics_t payload; + } jamming_packet = { + .sub_command = FUNC_ID_PROP_JAMMING_SUBCOMMAND_REPORT, + .payload = *report + }; + + status = RequestUnsolicited(FUNC_ID_PROP_JAMMING_DETECTION_COMMAND, (uint8_t *)&jamming_packet, sizeof(jamming_packet)) ? ZPAL_STATUS_OK : ZPAL_STATUS_FAIL; + return status; +} +#endif /* SL_CATALOG_ZW_JAMMING_DETECTION_PRESENT */ + /*============================== ApplicationInit ====================== ** Init UART and setup port pins for LEDs ** @@ -800,12 +900,33 @@ ApplicationInit( zpal_reset_reason_t eResetReason) { #ifdef SL_CATALOG_ZW_SHUTDOWN_MANAGER_PRESENT - zw_shutdown_manager_init(); + zpal_status_t status = zw_shutdown_manager_init(); + if (status != ZPAL_STATUS_OK) { + assert(false); + } #endif // enable the watchdog at init of application zpal_watchdog_init(); zpal_enable_watchdog(true); +#ifdef SL_CATALOG_ZW_JAMMING_DETECTION_PRESENT + sl_jamming_detection_config_t config = { 0 }; + + // set the default configuration for the jamming detection + if ( ZPAL_STATUS_OK == sl_jamming_detection_default_config(&config)) { + // set the callback function to be called when jamming is detected + config.report_callback = application_jamming_detected_callback; + config.collection_callback = application_rssi_collection_callback; + + /*with or without jamming detection, the rest of the application runs as usual.*/ + if (ZPAL_STATUS_OK != sl_jamming_detection_init(&config)) { + assert(false); + } + } else { + assert(false); + } +#endif /* SL_CATALOG_ZW_JAMMING_DETECTION_PRESENT */ + // Serial API can control hardware with information // set in the file system therefore it should be the first // step in the Initialization @@ -815,7 +936,7 @@ ApplicationInit( app_hw_init(); #endif - /* g_eApplResetReason now contains lastest System Reset reason */ + /* g_eApplResetReason now contains lastest System Ryeset reason */ g_eApplResetReason = eResetReason; ZPAL_LOG_INFO(ZPAL_LOG_APP, "ApplicationInit eResetReason = %d\n", eResetReason); @@ -873,8 +994,7 @@ ApplicationInit( ** Handling of received application commands and requests ** **--------------------------------------------------------------------------*/ -void /*RET Nothing */ -ApplicationCommandHandler(__attribute__((unused)) void *pSubscriberContext, SZwaveReceivePackage* pRxPackage) +void ApplicationCommandHandler(__attribute__((unused)) void *pSubscriberContext, SZwaveReceivePackage* pRxPackage) { ZW_APPLICATION_TX_BUFFER *pCmd = (ZW_APPLICATION_TX_BUFFER *)&pRxPackage->uReceiveParams.Rx.Payload; uint8_t cmdLength = pRxPackage->uReceiveParams.Rx.iLength; @@ -923,8 +1043,7 @@ typedef struct SMultiCastNodeMaskHeaderSerial{ ** Handling of received application commands and requests ** **--------------------------------------------------------------------------*/ -static void /*RET Nothing */ -ApplicationCommandHandler_Bridge(SReceiveMulti* pReceiveMulti) +void ApplicationCommandHandler_Bridge(SReceiveMulti* pReceiveMulti) { /* ZW->HOST: REQ | 0xA8 | rxStatus | destNode | sourceNode | cmdLength * | pCmd[] | multiDestsOffset_NodeMaskLen | multiDestsNodeMask[] | rssiVal @@ -1081,3 +1200,13 @@ ZW_WEAK const void * SerialAPI_get_uart_config_ext(void) { return NULL; } + +void set_urgent_app_callback(urgent_app_callback_t callback) +{ + m_urgent_app_callback = callback; +} + +void set_keep_alive_callback(keep_alive_callback_t callback) +{ + m_keep_alive_callback = callback; +} diff --git a/src/zwa2_controller/extension/nabucasa_zwa2_extension/src/zwave_dmadrv_compat.c b/src/zwa2_controller/extension/nabucasa_zwa2_extension/src/zwave_dmadrv_compat.c index 04bd68ab..5733d280 100644 --- a/src/zwa2_controller/extension/nabucasa_zwa2_extension/src/zwave_dmadrv_compat.c +++ b/src/zwa2_controller/extension/nabucasa_zwa2_extension/src/zwave_dmadrv_compat.c @@ -50,6 +50,11 @@ bool zwave_ldma_tx_callback(unsigned int channel, unsigned int sequenceNo, void return false; } +// As of Simplicity SDK 2026.6.0, DMADRV is deprecated in favour of sl_dma_manager (it still works, +// delegating internally). This shim is deliberately built on DMADRV constructs to match the Z-Wave +// ZPAL and SPI/I2C drivers, so we suppress the deprecation warning rather than re-implement it. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" sl_status_t zwave_dmadrv_compat_init() { Ecode_t result = DMADRV_Init(); @@ -82,3 +87,4 @@ sl_status_t zwave_dmadrv_compat_init() return SL_STATUS_OK; } +#pragma GCC diagnostic pop diff --git a/src/zwa2_controller/sdk_patches/dmadrv-rename-ldma-irqhandler.patch b/src/zwa2_controller/sdk_patches/dmadrv-rename-ldma-irqhandler.patch index 464ab7c2..4d259761 100644 --- a/src/zwa2_controller/sdk_patches/dmadrv-rename-ldma-irqhandler.patch +++ b/src/zwa2_controller/sdk_patches/dmadrv-rename-ldma-irqhandler.patch @@ -1,13 +1,12 @@ -diff --git a/platform_core/platform/emdrv/dmadrv/src/dmadrv.c b/platform_core/platform/emdrv/dmadrv/src/dmadrv.c -index dd45751..06234c6 100755 ---- a/platform_core/platform/emdrv/dmadrv/src/dmadrv.c -+++ b/platform_core/platform/emdrv/dmadrv/src/dmadrv.c -@@ -1036,7 +1042,7 @@ Ecode_t DMADRV_TransferRemainingCount(unsigned int channelId, - * @brief - * An interrupt handler for LDMA. +diff --git a/platform_core/platform/service/dma_manager/src/sl_dma_manager_hal_ldma.c b/platform_core/platform/service/dma_manager/src/sl_dma_manager_hal_ldma.c +--- a/platform_core/platform/service/dma_manager/src/sl_dma_manager_hal_ldma.c ++++ b/platform_core/platform/service/dma_manager/src/sl_dma_manager_hal_ldma.c +@@ -275,7 +275,7 @@ void sli_dma_manager_hal_set_pending_errors(uint8_t channel_nbr, uint32_t errors + /***************************************************************************//** + * Interrupt handler for LDMA module. ******************************************************************************/ -void LDMA_IRQHandler(void) +void dmadrv_LDMA_IRQHandler(void) { - bool stop; - ChTable_t *ch; + uint32_t pending; + uint32_t pending_done; diff --git a/src/zwa2_controller/zwa2_controller.slcp b/src/zwa2_controller/zwa2_controller.slcp index 96490412..f3bf9ddc 100644 --- a/src/zwa2_controller/zwa2_controller.slcp +++ b/src/zwa2_controller/zwa2_controller.slcp @@ -186,7 +186,7 @@ configuration: - condition: - device_series_2 name: SL_SLEEPTIMER_PERIPHERAL - value: SL_SLEEPTIMER_PERIPHERAL_BURTC + value: SL_SLEEPTIMER_PERIPHERAL_DEFAULT - name: ZAF_CONFIG_INSTALLER_ICON_TYPE value: '0' - name: ZAF_APP_NAME diff --git a/tools/build_project.py b/tools/build_project.py index b0a8cf4b..373b3a54 100755 --- a/tools/build_project.py +++ b/tools/build_project.py @@ -57,12 +57,13 @@ def get_toolchain_default_paths() -> list[pathlib.Path]: if sys.platform == "darwin": return list( pathlib.Path( - "/Applications/Simplicity Studio.app/Contents/Eclipse/developer/toolchains/gnu_arm/" - ).glob("*") + "/Applications/Simplicity Studio.app/Contents/Eclipse/developer/toolchains/" + ).glob("*/*") ) if is_running_in_docker(): - return list(pathlib.Path("/root/.silabs/slt/installs/conan/p").glob("gcc-*/p")) + root = pathlib.Path("/root/.silabs/slt/installs/conan/p") + return list(root.glob("gcc-*/p")) + list(root.glob("llvm-*/p")) return [] @@ -172,6 +173,20 @@ def load_toolchains(paths: list[pathlib.Path]) -> dict[pathlib.Path, str]: toolchains = {} for toolchain in paths: + # libc++ encodes its version in `__config` as `_LIBCPP_VERSION` (MMmmpp, e.g. 210101) + libcpp_config = next( + toolchain.glob("lib/clang-runtimes/**/include/c++/v1/__config"), None + ) + if libcpp_config is not None: + for line in libcpp_config.read_text().split("\n"): + if "define _LIBCPP_VERSION " in line: + version = int(line.split()[-1]) + toolchains[toolchain] = ( + f"llvm:{version // 10000}.{version // 100 % 100}.{version % 100}" + ) + break + continue + gcc_plugin_version_h = next( toolchain.glob("lib/gcc/arm-none-eabi/*/plugin/include/plugin-version.h") ) @@ -185,7 +200,7 @@ def load_toolchains(paths: list[pathlib.Path]) -> dict[pathlib.Path, str]: version_info[name] = value toolchains[toolchain] = ( - version_info["basever"] + "." + version_info["datestamp"] + f"gcc:{version_info['basever']}.{version_info['datestamp']}" ) return toolchains @@ -264,6 +279,38 @@ def get_elf_source_paths(elf_path: pathlib.Path) -> set[pathlib.PurePosixPath]: return paths +def remap_debug_build_paths(elf_path: pathlib.Path, prefix_map: dict[str, str]) -> None: + """Remap absolute build-path prefixes in an ELF's DWARF string tables, in place.""" + replacements = {} + for old, new in prefix_map.items(): + old_bytes, new_bytes = old.encode(), new.encode() + assert len(new_bytes) <= len(old_bytes), f"{new!r} is longer than {old!r}" + replacements[old_bytes] = new_bytes + b"/" * (len(old_bytes) - len(new_bytes)) + + with elf_path.open("rb") as f: + elf = ELFFile(f) + sections = [ + (section["sh_offset"], bytearray(section.data())) + for name in (".debug_str", ".debug_line_str") + if (section := elf.get_section_by_name(name)) is not None + ] + + with elf_path.open("r+b") as f: + for offset, data in sections: + for old_bytes, padded in replacements.items(): + search = 0 + + while (index := data.find(old_bytes, search)) != -1: + # Only rewrite at a string start (offset 0 or right after a NUL) + if index == 0 or data[index - 1] == 0: + data[index : index + len(old_bytes)] = padded + + search = index + 1 + + f.seek(offset) + f.write(data) + + def main(): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter @@ -383,6 +430,9 @@ def main(): manifest = yaml.load(args.manifest.read_text()) + for key, override in args.overrides: + manifest[key] = override + # Ensure we can load the correct SDK and toolchain sdks = load_sdks(args.sdks) sdk, sdk_and_version = next( @@ -392,11 +442,11 @@ def main(): toolchains = load_toolchains(args.toolchains) toolchain = next( - path for path, version in toolchains.items() if version == manifest["toolchain"] + path + for path, name in toolchains.items() + if manifest["toolchain"] in (name, name.split(":", 1)[1]) ) - - for key, override in args.overrides: - manifest[key] = override + is_llvm = toolchains[toolchain].startswith("llvm:") # First, copy the base project into the build dir, under `template/` projects_root = pathlib.Path(__file__).parent.parent @@ -536,7 +586,7 @@ def main(): "--copy-proj-sources", "--copy-sdk-sources", "--new-project", - "--toolchain", "toolchain_gcc", + "--toolchain", "toolchain_llvm" if is_llvm else "toolchain_gcc", "--sdk", sdk, "--output-type", "vscode", ], @@ -702,15 +752,25 @@ def main(): ) ) - cmake_dir = args.build_dir / "cmake_gcc" + cmake_dir = args.build_dir / ("cmake_llvm" if is_llvm else "cmake_gcc") - # Remove absolute paths from the build for reproducibility remapped_paths = { args.build_dir.absolute(): "/src", f"{cmake_dir.absolute()}/..": "/src", + # The toolchain's own resource/runtime headers (e.g. clang's builtin and newlib + # include dirs) are recorded in debug info under a machine-specific conan path + str(toolchain): "/src/vendor/toolchain", "/home/buildengineer/jenkins/workspace/Gecko_Workspace/gsdk": f"/src/{sdk_name}_{sdk_version}", + # Zigbee sources reference the GitHub Actions workspace they were packaged in + "/__w/zigbee/zigbee": f"/src/{sdk_name}_{sdk_version}/zigbee", "/home/buildengineer/.silabs/slt/installs/conan/p/cmsisfb920dbb6ad42/p": "/src/vendor/cmsis", "/home/buildengineer/.silabs/slt/installs/conan/p/platf85e95225bc406/p": f"/src/{sdk_name}_{sdk_version}/platform_core", + "/home/buildengineer/.silabs/slt/installs/conan/p/platfe548addd6aec0/p": f"/src/{sdk_name}_{sdk_version}/platform_core", + # The Z-Wave libraries were packaged against their own conan hashes + "/home/buildengineer/.silabs/slt/installs/conan/p/cmsis4dea3e6cbb6ce/p": "/src/vendor/cmsis", + "/home/buildengineer/.silabs/slt/installs/conan/p/platf6edd0cd4d4914/p": f"/src/{sdk_name}_{sdk_version}/platform_core", + # The zigbee stack libraries reference the silabs_core package they were built against + "/github/home/.silabs/slt/installs/conan/p/commo8335073ce327e/p": f"/src/{sdk_name}_{sdk_version}/platform_core", # The Z-Wave SDK isn't part of the Simplicity SDK but is still referenced. If we # ever decide to compile it as part of CI, we can change this remap. "/opt/github/runner/_work/z-wave/z-wave": "/src/vendor/zwave", @@ -723,12 +783,24 @@ def main(): build_flags["LD_FLAGS"] += ["-Wl,--sort-section=name"] # Enable errors - build_flags["C_FLAGS"] += [ - "-Wall", - "-Wextra", - "-Werror", - "-Wno-error=maybe-uninitialized", # Linking fails due to a few SDK bugs - ] + build_flags["C_FLAGS"] += ["-Wall", "-Wextra", "-Werror"] + + if is_llvm: + build_flags["C_FLAGS"] += [ + "-Wno-unknown-warning-option", # ignore GCC-only warning names + "-Wno-error=format-security", # SDK `diagnostic.c` uses a non-literal format string + "-Wno-error=unknown-pragmas", # our `ws2812.c` uses `#pragma GCC optimize` + "-Wno-error=unused-function", # unused statics in SDK/OpenThread sources + "-Wno-error=c23-extensions", # our `cmds_proprietary.c` has a label before a declaration + "-Wno-error=unterminated-string-initialization", # char arrays in zigbee router sources + ] + else: + build_flags["C_FLAGS"] += [ + "-Wno-error=maybe-uninitialized", # Linking fails due to a few SDK bugs + "-Wno-error=uninitialized", # False positive in zigbee `core-cli.c` under LTO + "-Wno-error=unused-function", # mbedTLS `ssl_tls.c` with X.509 hostname verification disabled + ] + build_flags["CXX_FLAGS"] = build_flags["C_FLAGS"] # CMake expects a semicolon-separated list for the post-build command @@ -759,7 +831,7 @@ def main(): env={ "HOME": os.environ["HOME"], "PATH": f"{pathlib.Path(sys.executable).parent}:{os.environ['PATH']}", - "ARM_GCC_DIR": toolchain, + ("ARM_LLVM_DIR" if is_llvm else "ARM_GCC_DIR"): toolchain, "NINJA_EXE_PATH": shutil.which("ninja"), "SOURCE_DATE_EPOCH": str(int(args.build_timestamp.timestamp())), }, @@ -774,6 +846,7 @@ def main(): env={ "HOME": os.environ["HOME"], "PATH": f"{pathlib.Path(sys.executable).parent}:{os.environ['PATH']}", + "SOURCE_DATE_EPOCH": str(int(args.build_timestamp.timestamp())), }, ) @@ -782,15 +855,30 @@ def main(): # Verify that --wrap linker flags don't wrap weak stubs validate_linker_wrap_symbols(map_file=output_artifact.with_suffix(".map")) - # Verify that all source paths in the ELF have been remapped + # Rewrite absolute build paths in the ELF's DWARF for reproducibility, then verify + # none leaked + out_elf = output_artifact.with_suffix(".out") + remap_debug_build_paths( + out_elf, + { + str(args.build_dir.resolve()): "/src", + "/root/.silabs": "/src/vendor", # local conan toolchain/SDK headers + "/home/buildengineer": "/src/vendor", # Silicon Labs build machines + "/github/home": "/src/vendor", # Silicon Labs Zigbee CI + "/opt/github": "/src/vendor", # Silicon Labs Z-Wave CI + "/__w": "/src", # GitHub Actions workspace + }, + ) + unreproducible_paths = [ path - for path in get_elf_source_paths(output_artifact.with_suffix(".out")) + for path in get_elf_source_paths(out_elf) if not path.is_relative_to("/src") ] if unreproducible_paths: raise RuntimeError( - f"Unreproducible source paths in ELF: {'\n - '.join(map(str, unreproducible_paths))}" + "Unreproducible source paths in ELF: " + + "\n - ".join(map(str, unreproducible_paths)) ) # Read the metadata extracted from the source and build trees diff --git a/tools/create_gbl.py b/tools/create_gbl.py index 1a9755b9..fbae055e 100755 --- a/tools/create_gbl.py +++ b/tools/create_gbl.py @@ -23,7 +23,7 @@ def _jump_to_elf_symbol(file: BinaryIO, symbol_name: str) -> tuple[ELFFile, int, symtab = elf.get_section_by_name(".symtab") symbols = symtab.get_symbol_by_name(symbol_name) - if len(symbols) != 1: + if symbols is None or len(symbols) != 1: raise ValueError(f"Expected one symbol for {symbol_name!r}, got {symbols}") symbol = symbols[0] @@ -216,7 +216,14 @@ def main(): elf = list(build_dir.glob("*.out"))[0] with elf.open("rb") as f: - ember_version = read_elf_symbol(f, "emberVersion") + # Try new SDK symbol name first, fall back to old + try: + ember_version = read_elf_symbol(f, "sl_zigbee_version") + version_symbol = "sl_zigbee_version" + except (ValueError, TypeError): + f.seek(0) + ember_version = read_elf_symbol(f, "emberVersion") + version_symbol = "emberVersion" ( build, @@ -247,7 +254,7 @@ def main(): version_type, padding, ) - ember_version = modify_elf_symbol(f, "emberVersion", new_ember_version) + modify_elf_symbol(f, version_symbol, new_ember_version) metadata["ezsp_version"] = f"{major}.{minor}.{patch}.{special}" @@ -294,14 +301,27 @@ def main(): gbl_dynamic.remove("ot_rcp_version") ot_proj_path = project_root / "config/sl_openthread_generic_config.h" - ot_sdk_path = ( - gsdk_path / "protocol/openthread/include/sl_openthread_package_info.h" + ot_sdk_path = next( + ( + path + for path in ( + # Gecko SDK and Simplicity SDK up to 2025.6.x + ( + gsdk_path + / "protocol/openthread/include/sl_openthread_package_info.h" + ), + # Simplicity SDK 2025.12.0 and above + (gsdk_path / "openthread/include/sl_openthread_package_info.h"), + ) + if path.exists() + ), + None, ) if ot_proj_path.exists(): openthread_config_h = parse_c_header_defines(ot_proj_path.read_text()) metadata["ot_rcp_version"] = openthread_config_h["PACKAGE_STRING"] - elif ot_sdk_path.exists(): + elif ot_sdk_path is not None: openthread_package_info_h = parse_c_header_defines(ot_sdk_path.read_text()) metadata["ot_rcp_version"] = ( openthread_package_info_h["PACKAGE_NAME"] @@ -313,9 +333,23 @@ def main(): if "gecko_bootloader_version" in gbl_dynamic: gbl_dynamic.remove("gecko_bootloader_version") - btl_config_h = parse_c_header_defines( - (gsdk_path / "platform/bootloader/config/btl_config.h").read_text() + btl_config_path = next( + ( + path + for path in ( + # Gecko SDK and Simplicity SDK up to 2025.6.x + (gsdk_path / "platform/bootloader/config/btl_config.h"), + # Simplicity SDK 2025.12.0 and above + (gsdk_path / "bootloader/platform/bootloader/config/btl_config.h"), + ) + if path.exists() + ), + None, ) + if btl_config_path is None: + raise FileNotFoundError("Could not find bootloader btl_config.h") + + btl_config_h = parse_c_header_defines(btl_config_path.read_text()) # Look for overrides btl_core_config_h = parse_c_header_defines(