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
-
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
-
Download a developer certificate from Device Management Portal.
-
Copy the
mbed_cloud_dev_credentials.c
file to theizuma-dm-example
directory in your workspace. -
Get an access key for your Device Management account.
-
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
. -
Copy the
update_default_resources.c
file from themanifest
directory to thepelion-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:
-
Build the MCUboot bootloader using the memory overlay file
frdm_k64f.overlay
by executing this command from the top-levelzephyr-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.
-
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:
-
Log in to Device Management Portal for your region:
-
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:
- Uploads the new firmware to Device Management.
- Creates and signs a manifest file describing the firmware.
- Creates and starts a firmware update campaign for the given device ID, using the manifest.
- 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 definitionsPAL_THREADS_MAX_COUNT
andPAL_STACKS_MAX_SIZE
, respectively. - Timers use kernel work queues for scheduling timeouts and invoking callbacks.
- Threads are statically allocated using
-
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.
- Sockets are implemented using Zephyr's POSIX API and are statically allocated with the compile definition
-
Storage:
- Device Management Client's
FlashIAP
API is mapped through Zephyr'sFlashMap
API. - Device Management Client instantiates multiple
FlashIAP
drivers to map between Izuma's absolute addresses and Zephyr's partions.
- Device Management Client's
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. |