Mistake on this page? Email us

Command-line tutorial for the Device Management Client example with Zephyr OS

This is a Device Management Client example, written using Device Management Client 4.13.0 and Zephyr OS 2.7.3.

Supported boards

Supported boards have:

  • At least 1 MiB total storage:
    • 512 KiB for application, bootloader and credential storage.
    • 512 KiB for firmware update.
  • 256 KiB RAM.
  • These Zephyr APIs implemented:

You can use this tutorial with the example application mbed-cloud-client-example and the following boards:

Board Example application Connectivity
frdm_k64f mbed-cloud-client-example Ethernet

For third party example applications and boards, use the following tutorials:

Board Example application Connectivity
nrf52840dk_nrf52840 pelion_client OpenThread mesh
nrf5340dk_nrf5340 pelion_client OpenThread mesh
nrf9160dk_nrf9160 pelion_client Cat-M1 or NB-IoT cellular

Prerequisites

To work with the Device Management Client example application, you need:

  • A Zephyr OS supported board with a network connection and enough flash and RAM.

  • Serial or debugger connection to your device for accessing the log.

  • Zephyr's command-line tool, West.

  • A toolchain matching your development board.

  • An Izuma Cloud account, if you do not have an account - contact us.

  • Device Management's command-line manifest-tool version 2.4.1 or later for firmware updates.

    Note: If your host system Python version is 3.6, use manifest-tool version 2.4.1, use version 2.5.0 (or newer) for more up-to-date system. You can specify version via: pip install manifest-tool==2.4.1.

Configuring Device Management Client

  1. Initialize a new Zephyr workspace using the manifest from mbed-cloud-client-example:

    west init -m https://github.com/PelionIoT/mbed-cloud-client-example zephyr-workspace
    cd zephyr-workspace
    west update
    

    This creates the following workspace on your computer:

    zephyr-workspace
    ├── bootloader
    ├── modules
    │   └── lib
    │       └── izuma-dm (middleware library)
    ├── izuma-dm-example (example application)
    │   ├── pal-platform
    │   │   └── SDK
    │   │       └── ZephyrOS (Zephyr project)
    │   │           └── boards (example overlays)
    │   └── west.yml (West manifest)
    ├── tools
    └── zephyr
    
  2. Download a developer certificate from Device Management Portal.

  3. Copy the mbed_cloud_dev_credentials.c file to the izuma-dm-example directory in your workspace.

  4. Get an access key for your Device Management account.

  5. Create update-related configuration and credentials in a new, empty directory using the manifest-tool:

    mkdir manifest
    cd manifest
    manifest-dev-tool init --access-key <Device Management access key>
    

    This directory now contains a private key suitable for authorizing firmware updates for devices provisioned with the public key and configuration stored in the file update_default_resources.c.

  6. Copy the update_default_resources.c file from the manifest directory to the pelion-dm-example directory.

Note: When you create a firmware update image for a deployed device, you must use the same update-related configuration and credentials (update private key, public key certificate, update_default_resources.c and configuration files) you used in the original device firmware image.

We highly recommend creating a Python virtual env for Zephyr SDK. Do install also the Zephyr python requirements.

python3 -m venv venv
source venv/bin/activate
pip install -r zephyr/scripts/requirements.txt

Compiling and flashing Device Management Client

Using the Freedom-K64F board as an example:

  1. Build the MCUboot bootloader using the memory overlay file frdm_k64f.overlay by executing this command from the top-level zephyr-workspace directory:

    west build -b frdm_k64f -d build/mcuboot -s bootloader/mcuboot/boot/zephyr -- \
    -DDTC_OVERLAY_FILE="$PWD/izuma-dm-example/pal-platform/SDK/ZephyrOS/boards/frdm_k64f.overlay" \
    -DCONFIG_MCUBOOT_CLEANUP_ARM_CORE=y
    

    Note: See the flash layout section for more about overlay files.

  2. Build and sign the example application:

    west build -b frdm_k64f -d build/dmc -s izuma-dm-example -- \
    -DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE=\"bootloader/mcuboot/root-rsa-2048.pem\"
    

    root-rsa-2048.pem is the default MCUboot private key used for testing and development.

Flashing the binary to the device

To flash the bootloader and application to the device:

west flash -d build/mcuboot
west flash -d build/dmc

Connecting and performing a firmware update on your device

Checking the device connection and obtaining the device ID

Obtain the Device ID either from device console logs or from Device Management Portal.

When the client has successfully connected, the terminal shows:

Client registered
Endpoint Name: <Endpoint name>
Device ID: <Device ID>

To verify the connection with Device Management Portal:

  1. Log in to Device Management Portal for your region:

  2. Select Device directory from the menu on the left.

    When the Devices page lists the device as registered, the device is connected and available.

The device is now ready for firmware update. For development devices, the endpoint name and device ID are identical.

Updating the firmware

To update the firmware on the device, copy the file zephyr.signed.bin from the build folder build/dmc/zephyr to the manifest directory created earlier, which contains your update credentials. To start a firmware update campaign, run:

manifest-dev-tool update-v1 \
--payload-path zephyr.signed.bin \
--device-id <Device ID> \
--wait-for-completion

This command:

  1. Uploads the new firmware to Device Management.
  2. Creates and signs a manifest file describing the firmware.
  3. Creates and starts a firmware update campaign for the given device ID, using the manifest.
  4. Waits for the campaign to finish and reports the result.

During the update flow, the client tracing log shows:

Firmware download requested
Authorization granted
Downloading: 1 %
...
Downloading: 100 %
Download completed
Firmware install requested
Authorization granted

After this, the device reboots automatically and registers to Device Management.

Note: Device Management Client for Zephyr OS currently only supports firmware update features from version 4.7. Please refer to the version 4.7 documentation when using firmware update.

User applications

To add Device Management Client to an existing project, add this repository and module to the West manifest:

remotes:
  - name: PelionIoT
    url-base: https://github.com/PelionIoT
projects:
  - name: izuma-dm
    repo-path: mbed-cloud-client
    remote: PelionIoT
    revision: master
    path: modules/lib/izuma-dm

Flash layout

Zephyr OS abstracts internal and external storage devices into isolated, labeled partitions. Each starts at address 0x0 regardless of the real, underlying storage medium.

The bootloader, MCUboot, is stored in the partition labeled mcuboot. The active application is executed from image_0, and the candidate firmware is stored in image_1. Izuma Device Management Client uses the partition pelion_storage to store configuration and credentials. If pelion_storage doesn't exist, Izuma Device Management Client uses the storage partition instead, if Zephyr isn't already using it (CONFIG_SETTINGS=n).

Depending on the architecture, you can put "image_0" and "image_1" on external storage. For better security, keep pelion_storage in internal storage.

For more information about Zephyr's storage partitions, see the Zephyr Project documentation.

As a reference, we've provided a partition overlay for the target frdm_k64f in the pelion-dm-example/pal-platform/SDK/ZephyrOS/boards directory, using this flash layout:

+--------------------------+
|                          |
|         TDBStore         | <-+ "izuma_storage"
|                          |
+--------------------------+
|                          |
|      MCUboot scratch     | <-+ "image_scratch"
|                          |
+--------------------------+
|                          |
|                          |
|Firmware candidate storage| <-+ "image_1"
|                          |
|                          |
+--------------------------+
|                          |
|                          |
|        Active app        | <-+ "image_0"
|                          |
|                          |
+--------------------------+
|                          |
|      Zephyr storage      | <-+ "storage"
|                          |
+--------------------------+
|                          |
|        Bootloader        | <-+ "mcuboot"
|                          |
+--------------------------+

Bootloader

Zephyr OS uses MCUboot as a bootloader.

The example application installs new firmware as "permanent" by default. To use MCUboot's rollback feature, use Kconfig to set CONFIG_IZUMA_UPDATE_PERMANENT=n and Zephyr's DFU commands for interacting with MCUboot.

Note: The build instructions use the default developer keys in MCUboot. For production devices, use secure credentials instead.

Platform Abstraction Layer (PAL)

The PAL implementation uses these Zephyr subsystems in the implementation:

  • RTOS:

    • Threads are statically allocated using K_THREAD_STACK_ARRAY_DEFINE with the maximum number of threads and stack sizes set with the compile definitions PAL_THREADS_MAX_COUNT and PAL_STACKS_MAX_SIZE, respectively.
    • Timers use kernel work queues for scheduling timeouts and invoking callbacks.
  • Network:

    • Sockets are implemented using Zephyr's POSIX API and are statically allocated with the compile definition PAL_SOCKET_MAX setting the maximum number of sockets.
    • PAL DNS API version 0 is implemented using POSIX getaddrinfo.
    • PAL DNS API version 3 is implemented using DNS Resolve.
    • Asynchronous callbacks are signaled through kernel work queues.
  • Storage:

    • Device Management Client's FlashIAP API is mapped through Zephyr's FlashMap API.
    • Device Management Client instantiates multiple FlashIAP drivers to map between Izuma's absolute addresses and Zephyr's partions.

Advanced Kconfig options

To activate the Kconfig, you need to be in the izuma-dm-example folder and run:

west build -t menuconfig --board=frdm_k64f

You can find the configuration options in the Kconfig menu under modules -> izuma-dm. Alternatively, you can pass configuration options on the command-line or set them permanently in the projects configuration file.

Once you have done your changes, remember to S save the configuration. Delete the build folder and rebuild.

Configuration option Type Default setting Description
CONFIG_IZUMA_ENDPOINT_TYPE String "default" Endpoint type name:
Optional name for the type of endpoint being connected. Useful for creating filters and organizing devices.
CONFIG_IZUMA_LIFETIME Integer 86400 Registration lifetime:
Interval in seconds between registration renewals. A device transitions from state "Registered" to "Deregistered" if the registration is not renewed within this lifetime interval. Recommended lifetime settings are in the range of multiple hours and days.
Choose one of:
- CONFIG_IZUMA_TRANSPORT_MODE_TCP
- CONFIG_IZUMA_TRANSPORT_MODE_UDP
- CONFIG_IZUMA_TRANSPORT_MODE_UDP_QUEUE


UDP Transport mode:
- TCP: Data is sent over TCP. Device actively listens for incoming messages. Recommended for applications that are always connected.
- UDP: Data is sent over UDP. Device actively listens for incoming messages. Recommended for low-bandwidth applications.
- UDP queue: Data is sent over UDP. Messages sent to the device queue in the cloud and are only delivered immediately after the device renews its registration. Recommended for low-power, low-bandwidth applications that powers down between transmissions.


CONFIG_IZUMA_EVENT_LOOP_THREAD_STACK_SIZE Integer 8192 Event loop thread stack size:
Stack size for the event loop thread.
CONFIG_IZUMA_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE Integer 512 Max CoAP blockwise payload size:
Maximum payload size used by CoAP.
CONFIG_IZUMA_DEBUG_TRACE Bool False Build Izuma client with debug tracing:
Use debug tracing to observe Izuma Device Management Client's internal workings.
CONFIG_IZUMA_UPDATE Bool True Enable firmware update:
Build Izuma Device Management Client with support for firmware update.
CONFIG_IZUMA_UPDATE_PERMANENT Bool False Instruct MCUboot to perform a permanent update instead of a test:
Marking new firmware as permanent is useful during the development phase where applications evolve rapidly.
CONFIG_IZUMA_UPDATE_BUFFER Integer 1024 Download buffer size for firmware updates:
Buffer used for downloading and processing firmware. Must be divisible by 2.
CONFIG_IZUMA_UPDATE_PAGE_SIZE Integer 8 Page size for the candidate firmware image's storage medium:
Smallest write granularity supported by the underlying storage medium. This value is used at compile time to ensure buffers are correctly aligned.
CONFIG_IZUMA_UPDATE_DEVELOPER Bool False Automatically populate developer update credentials in secure storage:
For development purposes, the manifest creation tool can generate credentials useful during development (not production). Select this option for automatic insertion into the credential manager and add update_default_resources.c, which the manifest tool generated, to the build.

Mbed TLS options

Configuration option Type Default setting Description
CONFIG_IZUMA_MBEDTLS_FILE Bool False Built-in Mbed TLS, configuration from file:
Use Mbed TLS library from Zephyr OS' manifest with a custom configuration file.
CONFIG_MBEDTLS_CFG_FILE String "config-tls-pelion.h" Custom Mbed TLS configuration file name.
CONFIG_IZUMA_MBEDTLS_LIB_NAME String "mbedTLS" Specify one or more Mbed TLS library files to be linked with Izuma. Separate multiple values with space " ".

Platform Abstraction Layer options

Configuration option Type Default setting Description
CONFIG_IZUMA_PAL_SUPPORT_NAT64 Bool True Automatic NAT64 address support on IPv6 networks:
Help IPv6 devices behind NAT64 use public DNS servers by converting IPv4 addresses to IPv6 using default NAT64 prefix. Only comes into effect when an IPv6-only device receives an IPv4 address from the DNS server.
CONFIG_IZUMA_PAL_SUPPORT_SSL_CONNECTION_ID Bool False Use Connection Identifiers for DTLS 1.2:
Connection ID is an extention to DTLS 1.2 that allows a DTLS session to persist even if the device's IP address and port changes, which otherwise would require a new DTLS handshake. This enables devices to power down their network interface for long periods of time, saving power and network bandwidth.
Requires Mbed TLS 2.18.0 or newer and transport mode to be UDP or UDP Queue.

CONFIG_IZUMA_PAL_USE_APPLICATION_REBOOT Bool False Use reboot function provided by application:
Override default reboot function with one provided by application. Useful for shutting down the device gracefully, powering down external components and saving state.
Signature for C function:
void pal_plat_osApplicationReboot(void)


CONFIG_IZUMA_PAL_USE_APPLICATION_NETWORK_CALLBACK Bool False Use network status callback provided by application:
Provide setter for registering network status callback function in application. Application uses callback function to notify Izuma Device Management Client about changes in network connectivity, enabling the client to refrain from sending data during network loss.
Signature for C function:
#include "pal.h"
palStatus_t pal_plat_setConnectionStatusCallback(uint32_t interfaceIndex,
connectionStatusCallback callback,
void *client_arg)





Choose either:
- POSIX CONFIG_IZUMA_PAL_USE_DNS_API_POSIX
- DNS Resolve CONFIG_IZUMA_PAL_USE_DNS_API_RESOLVE

DNS Resolve DNS API:
- POSIX: Use POSIX's getaddrinfo. This call is synchronous and maps to Izuma's DNS version 0.
- DNS Resolve: Use DNS Resolve's dns_get_addr_info. This call is asynchronous and maps to Izuma's DNS version 3.

CONFIG_NEWLIB_LIBC_FLOAT_PRINTF Bool True Build with newlib float printf:
Enable floating points in Newlib's snprintf. Must be enabled for correctly formatting floating points in LwM2M resources.