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(