Creating Z-Wave + BLE SMP Solution#

This guide explains how to build a switched multiprotocol (SMP) firmware for an EFR32ZG28 device which combines a Z-Wave Switch On/Off application and a Bluetooth OTA DFU application that can upgrade the Z-Wave app. It combines:

  • App 1 (Z-Wave): Switch On/Off application

  • App 2 (Bluetooth LE): OTA DFU application used to deliver updates for the Z-Wave app

  • A bootloader that supports switching between the two apps and provides an OTA storage slot

This workflow uses the SLC command line interface to generate a single workspace containing both applications.

Glossary#

Projects

  • Z-Wave app project: zwave_soc_switch_on_off

  • Bootloader project: bootloader-storage-internal-single-zwave-ota

  • BLE app project: bt_soc_app_ota_dfu

Prerequisites#

Install required components via Simplicity Studio Package Manager#

In Simplicity Studio, open Package Manager and install the components required for:

  • Simplicity SDK 2026.6.x containing Z-Wave and Bluetooth examples

  • SLC CLI (Simplicity Studio command-line project generator)

  • Simplicity Commander (device erase/flash and token provisioning)

  • LLVM toolchain

Workspace/path guidance (Windows)#

Keep project paths short to avoid Windows path-length issues during generation/build.

Flash Layout#

Start Address

Region

Size

0x08000000

Bootloader

24 KiB

0x08006000

App 1 – Z-Wave

248 KiB

0x08044000

OTA Slot 0

240 KiB

0x08080000

App 2 – BLE

256 KiB

0x080C0000

SMP Page 1

8 KiB

0x080C2000

SMP Page 2

8 KiB

0x080C4000

Uncommitted

~240 KiB (on 1 MiB ZG28)

0x08100000

End of Flash

Instructions#

Execute the following instructions on the command-line with SLC:

Set up the Workspace and Project#

Step 1: Set up the SLC#

  1. Set up SLC. For instructions, see SLC.

Step 2: Set up the the workspace#

  1. Create a folder for the SLC solution.

  2. Open the folder in your preferred editor.

  3. Copy the .slcw of the Switch On/Off application from <SiSDK_path>\zwave-sample-app\workspaces\zwave_soc_switch_on_off_ota.slcw (henceforth referred to as smp.slcw)

  4. Place the file into your working directory.

Step 3: Edit the project file#

  1. In the smp.slcw file, replace all SDK paths to use / instead of \.

  2. Add the bt_soc_app_ota_dfu project's path as a new entry. For example:

    - path: <SiSDK_path>/bluetooth_le_app/example/bt_soc_app_ota_dfu/bt_soc_app_ota_dfu.slcp
      id: ble_app
      output: ble_app

Step 4: Generate the project#

  1. Run the following command:

    slc-cli.exe generate --new-project --workspace=smp.slcw --with=brd4401c --sdk-package-path=<SiSDK_path> --destination=.\sln --output-type=cmake --toolchain=llvm
    • If you encounter errors such as:

      Problems generating template files from component: %extension-silabs.simplicity_sdk%agents_md - Potential jar issue: python script did not properly register a template generator

      reinstall python:

      i.  `slt uninstall --force python`
      ii. `slt install python`.
  2. Ensure the --new project flag is used to copy .slcp files to the solution correctly.

Configure the Applications#

Step 1: Update the BLE application#

  1. Open the BLE project's .slcp file.

  2. Add the following template_contribution to place it at the correct flash address:

    template_contribution:
      - name: memory_flash_start
        value: 0x08080000
      - name: memory_flash_size
        value: 0x40000
  3. Add the following to app.c:

    • The necessary includes:

      #include "btl_smp_switch_flash_api.h"
      #include "btl_smp_switch_record.h"
      #include "em_device.h"
  4. Update the OTA event handler:

    • In the event handler function 'app_ota_dfu_on_status_change', extend the SL_BT_APP_OTA_DFU_WAIT_FOR_REBOOT case with a request reboot to Z-Wave app on successful OTA:

      case SL_BT_APP_OTA_DFU_WAIT_FOR_REBOOT:
            if (btl_smp_switch_request_next_boot_app((uint8_t)BTL_SMP_APP_ID_1)) {
              sl_bt_app_ota_dfu_reboot();
            }
      
            // <Existing code>
      
            break;
    • Optionally, you can extend the button handlers with similar functionality.

      For that, add the following code at the end of the handler of BTN0 events in sl_on_button_change as follows:

            if (app_ota_dfu_status == SL_BT_APP_OTA_DFU_ERROR)
      
            // <Existing code>
      
            } else if (app_ota_dfu_status == SL_BT_APP_OTA_DFU_WAIT_FOR_REBOOT) {
              if (btl_smp_switch_request_next_boot_app((uint8_t)BTL_SMP_APP_ID_1)) {
                app_log_info("SMP: next boot Z-Wave; rebooting." APP_LOG_NL);
                sl_bt_app_ota_dfu_reboot();
              }
            }
  5. Regenerate the project:

    slc generate -p "c:\w\b\smp\sln\ble_app\bt_soc_app_ota_dfu.slcp" -d "c:\w\b\smp\sln\ble_app" -s <SiSDK_path> -o cmake -tlcn llvm

Step 2: Update the Z-Wave app#

  1. Add a mechanism to switch to the BLE application. This can be implemented in several ways, such as a CLI command or a button handler.

    To implement switching apps via medium press of BTN0, extend app_btn_hander.c:

    i. Add the necessary includes:

    #include "btl_smp_switch_flash_api.h"
    #include "btl_smp_switch_record.h"
    #include "em_device.h"

    ii. Handle medium length press for BTN0 – in app_button_press_btn_0_handler, add:

    case APP_BUTTON_PRESS_DURATION_MEDIUM:
      if (btl_smp_switch_request_next_boot_app((uint8_t)BTL_SMP_APP_ID_2)) {
        NVIC_SystemReset();
      }
      break;
  2. Optionally, add this code to the ApplicationTask function in app.c to see at a glance the software version for testing the OTA upgrade:

    #include "zw_version_config.h"
    
    ...
    ZPAL_LOG_INFO(
        ZPAL_LOG_APP,
        "Z-Wave application image version: %u.%u.%u\n",
        (unsigned)APP_VERSION,
        (unsigned)APP_REVISION,
        (unsigned)APP_PATCH);
  3. Change the size of the OTA image's slot by editing config/sl_storage_config.h:

    #define ZW_BTL_STORAGE_SIZE_RELEASE  0x3C000

Configure the Bootloader#

  1. Add the bootloader_smp_switch component to the bootloader's .slcp:

    slc modify project -p .\sln\bootloader\bootloader-storage-internal-single-zwave-ota.slcp --with=bootloader_smp_switch --sdk-package-path=<SiSDK_path>
  2. Regenerate the project

    slc generate -p "C:\w\b\smp\sln\bootloader\bootloader-storage-internal-single-zwave-ota.slcp" -d "C:\w\b\smp\sln\bootloader" -s <SiSDK_path> -o cmake -tlcn llvm
  3. Edit config/btl_smp_cfg.h to declare where the SMP switch component's non-volatile memory is placed:

    #define BTL_SMP_PAGE_1_BASE  0x080C0000
    #define BTL_SMP_PAGE_2_BASE  0x080C2000
    #define BTL_SMP_APP_2_BASE 0x08080000
  4. Change the address & size of the OTA image's slot by editing config/btl_storage_slot_cfg.h:

    #define SLOT0_START 0x8044000
    #define SLOT0_SIZE 0x3C000

Build the Complete Solution#

Step 1: Update the solution file#

  1. Open the top-level file .slpb file in the generated solution.

  2. Locate the 'steps' key and replace it with the following:

    steps:
    - task: "convert"
     output: "artifacts/smp.s37"
     input:
     - "{{bootloader_binary_s37}}"
     - "{{application_binary_s37}}" # Z-Wave app
     - "{{application_binary}}" # BLE app
    - task: "copy" # For OTA update
     output: "artifacts/smp-zwave.gbl"
     input: "{{application_binary_gbl}}"

Step 2: Build the workspace#

  1. Go to the cmake_llvm directory.

  2. Run the following command:

    cmake --workflow --preset project

Program and Test the Device#

Step 1: Flash the device#

  1. Erase the device, then write the keys and the firmware.

    WARNING: Be sure to use the same keys that were used to create the .gbl file. By default, these are the ones included in the SDK at: <SiSDK_path>\zwave_sample_app\sample-keys.

    The sample keys should not be used in production!

    commander device masserase -s <serial_number>
    
    commander flash -s <serial_number> --tokengroup znet --tokenfile <SiSDK_path>\zwave_sample_app\sample-keys\sample_encrypt.key --tokenfile <SiSDK_path>zwave_sample_app\sample-keys\sample_sign.key-tokens.txt
    
    commander flash -s <serial_number> .\sln\artifacts\smp.s37

Step 2: Create a .gbl file to test OTA DFU functionality#

  1. Modify the application version of the Z-Wave app. Open the config/zw_version_config.h file and change the values to:

    #define USE_USER_APP_VERSION  1
    #define USER_APP_VERSION  255
  2. Run the workspace build command again.

    cmake --workflow --preset project

Step 3: Test the software#

  1. Optionally, include the device in a Z-Wave network.

  2. It's recommended to connect to the serial output of the app to see system messages and upgrade progress.

  3. Switch to the BLE application (for example, by using a medium press of BTN0). For more information, see Step 7.

  4. Perform the OTA upgrade over BLE – push the .gbl file to the device and wait for it to install the upgrade.

    • Using the Simplicity Connect app – refer to this guide

    • Using the Bluetooth - Host OTA DFU application with a second device running the Bluetooth NCP app – refer to the host app project's README

  5. If the upgrade succeeds, the device should reboot to the Z-Wave application.

    At this point, you can verify the Z-Wave application version reported by the device.