samples: subsys: mgmt: smp_svr: add udp sample

This sample now supports SMP UDP transport.
Two config overlays have been added for ipv4 and ipv6, respectively.

The sample documentation has been completely revamped to be less
bluetooth focused and more general.

Signed-off-by: Mikkel Jakobsen <mikkel.aunsbjerg@prevas.dk>
This commit is contained in:
Mikkel Jakobsen 2020-04-10 11:38:32 +02:00 committed by Jukka Rissanen
commit a518516d5d
7 changed files with 228 additions and 138 deletions

View file

@ -384,6 +384,7 @@
/samples/shields/ @avisconti /samples/shields/ @avisconti
/samples/subsys/logging/ @nordic-krch @jakub-uC /samples/subsys/logging/ @nordic-krch @jakub-uC
/samples/subsys/shell/ @jakub-uC @nordic-krch /samples/subsys/shell/ @jakub-uC @nordic-krch
/samples/subsys/mgmt/mcumgr/smp_svr/ @aunsbjerg
/samples/subsys/usb/ @jfischer-phytec-iot @finikorg /samples/subsys/usb/ @jfischer-phytec-iot @finikorg
/samples/subsys/power/ @wentongwu @pabigot /samples/subsys/power/ @wentongwu @pabigot
/samples/userspace/ @andrewboie /samples/userspace/ @andrewboie

View file

@ -14,3 +14,4 @@ project(smp_svr)
target_sources(app PRIVATE src/main.c) target_sources(app PRIVATE src/main.c)
target_sources_ifdef(CONFIG_MCUMGR_SMP_BT app PRIVATE src/bluetooth.c) target_sources_ifdef(CONFIG_MCUMGR_SMP_BT app PRIVATE src/bluetooth.c)
target_sources_ifdef(CONFIG_MCUMGR_SMP_UDP app PRIVATE src/udp.c)

View file

@ -14,6 +14,7 @@ This sample application supports the following mcumgr transports by default:
* Shell * Shell
* Bluetooth * Bluetooth
* UDP
``smp_svr`` enables support for the following command groups: ``smp_svr`` enables support for the following command groups:
@ -25,9 +26,6 @@ This sample application supports the following mcumgr transports by default:
Caveats Caveats
******* *******
* The Zephyr port of ``smp_svr`` is configured to run on a Nordic nRF52x MCU. The
application should build and run for other platforms without modification.
* The MCUboot bootloader is required for ``img_mgmt`` to function * The MCUboot bootloader is required for ``img_mgmt`` to function
properly. More information about the Device Firmware Upgrade subsystem and properly. More information about the Device Firmware Upgrade subsystem and
MCUboot can be found in :ref:`mcuboot`. MCUboot can be found in :ref:`mcuboot`.
@ -36,8 +34,18 @@ Caveats
on Linux and macOS. On Windows there is no support for Device Firmware on Linux and macOS. On Windows there is no support for Device Firmware
Upgrade over BLE yet. Upgrade over BLE yet.
Building a BLE Controller (optional) Prerequisites
************************************ *************
Installing the mcumgr cli
=========================
To interact remotely with the management subsystem on a device, we need to have the
:file:`mcumgr` installed. Follow the instructions in the :ref:`mcumgr_cli` section
of the Management subsystem documentation.
Building a BLE Controller
=========================
.. note:: .. note::
This section is only relevant for Linux users This section is only relevant for Linux users
@ -47,175 +55,179 @@ Bluetooth Low Energy (BLE) and do not have a built-in or pluggable BLE radio,
you can build one and use it following the instructions in you can build one and use it following the instructions in
:ref:`bluetooth-hci-uart-bluez`. :ref:`bluetooth-hci-uart-bluez`.
Building and Running Building and flashing MCUboot
******************** *****************************
The below steps describe how to build and run the MCUboot bootloader.
Detailed instructions can be found in the :ref:`mcuboot` documentation page.
The Zephyr port of MCUboot is essentially a normal Zephyr application, which means that
we can build and flash it like normal using ``west``, like so:
.. code-block:: console
west build -b <board> -d build_mcuboot bootloader/mcuboot/boot/zephyr
west flash -d build_mcuboot
Substitute <board> for one of the boards supported by the sample, see
:file:`sample.yaml`.
.. _smp_svr_sample_build:
Building the sample application
*******************************
The below steps describe how to build and run the ``smp_svr`` sample in The below steps describe how to build and run the ``smp_svr`` sample in
Zephyr. Where examples are given, they assume the sample is being built for Zephyr. The ``smp_svr`` sample comes in different flavours.
the Nordic nRF52 Development Kit (``BOARD=nrf52dk_nrf52832``).
If you would like to use a more constrained platform, such as the nRF51 DK, you .. tabs::
should use the :file:`prj_tiny.conf` configuration file rather than the default
:file:`prj.conf`.
Step 1: Build MCUboot .. group-tab:: Bluetooth
=====================
Build MCUboot by following the instructions in the :ref:`mcuboot` The sample application comes in two bluetooth flavours: a normal one and a tiny one
documentation page. for resource constrained bluetooth devices.
Step 2: Flash MCUboot To build the normal bluetooth sample:
======================
Flash the resulting image file to address 0x0 of flash memory. .. code-block:: console
This can be done in multiple ways.
Using make or ninja: west build \
-b nrf52dk_nrf52832 \
samples/subsys/mgmt/mcumgr/smp_svr \
-- \
-DOVERLAY_CONFIG=overlay-bt.conf
.. code-block:: console And to build the tiny bluetooth sample:
make flash .. code-block:: console
# or
ninja flash
Using GDB: west build \
-b nrf51dk_nrf51422 \
samples/subsys/mgmt/mcumgr/smp_svr \
-- \
-DOVERLAY_CONFIG=overlay-bt-tiny.conf
.. code-block:: console .. group-tab:: UDP
restore <path-to-mcuboot-zephyr.bin> binary 0 The UDP transport for SMP supports both IPv4 and IPv6.
In the sample, both IPv4 and IPv6 are enabled, but they can be
enabled and disabled separately.
Step 3: Build smp_svr To build the UDP sample:
=====================
``smp_svr`` can be built for the nRF52 as follows: .. code-block:: console
.. zephyr-app-commands:: west build \
:zephyr-app: samples/subsys/mgmt/mcumgr/smp_svr -b frdm_k64f \
:board: nrf52dk_nrf52832 samples/subsys/mgmt/mcumgr/smp_svr \
:build-dir: nrf52dk_nrf52832 -- \
:goals: build -DOVERLAY_CONFIG=overlay-udp.conf
.. _smp_svr_sample_sign: .. _smp_svr_sample_sign:
Step 4: Sign the image Signing the sample image
====================== ************************
.. note:: A key feature of MCUboot is that images must be signed before they can be successfully
From this section onwards you can use either a binary (``.bin``) or an uploaded and run on a target. To sign images, the MCUboot tool :file:`imgtool` can be used.
Intel Hex (``.hex``) image format. This is written as ``(bin|hex)`` in this
document.
Using MCUboot's :file:`imgtool.py` script, sign the :file:`zephyr.(bin|hex)` To sign the sample image we built in a previous step:
file you built in Step 3. In the below example, the MCUboot repo is located at
:file:`~/src/mcuboot`.
.. code-block:: console .. code-block:: console
~/src/mcuboot/scripts/imgtool.py sign \ west sign -t imgtool -- --key bootloader/mcuboot/root-rsa-2048.pem
--key ~/src/mcuboot/root-rsa-2048.pem \
--header-size 0x200 \
--align 8 \
--version 1.0 \
--slot-size <image-slot-size> \
<path-to-zephyr.(bin|hex)> signed.(bin|hex)
The above command creates an image file called :file:`signed.(bin|hex)` in the The above command creates an image file called :file:`zephyr.signed.bin` in the
current directory. build directory.
Step 5: Flash the smp_svr image For more information on image signing and ``west sign``, see the :ref:`west-sign`
=============================== documentation.
Upload the :file:`signed.(bin|hex)` file from Step 4 to image slot-0 of your Flashing the sample image
*************************
Upload the :file:`zephyr.signed.bin` file from the previous to image slot-0 of your
board. The location of image slot-0 varies by board, as described in board. The location of image slot-0 varies by board, as described in
:ref:`mcuboot_partitions`. For the nRF52 DK, slot-0 is located at address :ref:`mcuboot_partitions`.
``0xc000``.
Using :file:`nrfjprog` you don't need to specify the slot-0 starting address, To upload the initial image file to an empty slot-0, we simply use ``west flash``
since :file:`.hex` files already contain that information: like normal. ``west flash`` will automatically detect slot-0 address and confirm
the image.
.. code-block:: console .. code-block:: console
nrfjprog --program <path-to-signed.hex> west flash --bin-file build/zephyr/zephyr.signed.bin
Using GDB: We need to explicity specify the *signed* image file, otherwise the non-signed version
will be used and the image wont be runnable.
.. code-block:: console
restore <path-to-signed.bin> binary 0xc000
Step 6: Run it!
===============
.. note::
If you haven't installed :file:`mcumgr` yet, then do so by following the
instructions in the :ref:`mcumgr_cli` section of the Management subsystem
documentation.
.. note::
The :file:`mcumgr` command-line tool requires a connection string in order
to identify the remote target device. In this sample we use a BLE-based
connection string, and you might need to modify it depending on the
BLE controller you are using.
Sample image: hello world!
==========================
The ``smp_svr`` app is ready to run. Just reset your board and test the app The ``smp_svr`` app is ready to run. Just reset your board and test the app
with the :file:`mcumgr` command-line tool's ``echo`` functionality, which will with the :file:`mcumgr` command-line tool's ``echo`` functionality, which will
send a string to the remote target device and have it echo it back: send a string to the remote target device and have it echo it back:
.. code-block:: console .. tabs::
sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' echo hello .. group-tab:: Bluetooth
hello
.. code-block:: console
Step 7: Device Firmware Upgrade sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' echo hello
=============================== hello
.. group-tab:: UDP
Using IPv4:
.. code-block:: console
mcumgr --conntype udp --connstring=[192.168.1.1]:1337 echo hello
hello
And using IPv6
.. code-block:: console
mcumgr --conntype udp --connstring=[2001:db8::1]:1337 echo hello
hello
.. note::
The :file:`mcumgr` command-line tool requires a connection string in order
to identify the remote target device. In the BT sample we use a BLE-based
connection string, and you might need to modify it depending on the
BLE controller you are using.
.. note::
In the following sections, examples will use ``<connection string>`` to represent
the ``--conntype <type>`` and ``--connstring=<string>`` :file:`mcumgr` parameters.
Device Firmware Upgrade (DFU)
*****************************
Now that the SMP server is running on your board and you are able to communicate Now that the SMP server is running on your board and you are able to communicate
with it using :file:`mcumgr`, you might want to test what is commonly called with it using :file:`mcumgr`, you might want to test what is commonly called
"OTA DFU", or Over-The-Air Device Firmware Upgrade. "OTA DFU", or Over-The-Air Device Firmware Upgrade. This works for both BT and UDP.
To do this, build a second sample (following the steps below) to verify The general sequence of a DFU process is as follows:
it is sent over the air and properly flashed into slot-1, and then
swapped into slot-0 by MCUboot.
Build a second sample * Build an MCUboot enabled application, see :ref:`smp_svr_sample_build`
--------------------- * Sign the application image, see :ref:`smp_svr_sample_sign`
* Upload the signed image using :file:`mcumgr`
* Listing the images on the device using :file:`mcumgr`
* Mark the uploaded image for testing using :file:`mcumgr`
* Reset the device remotely using :file:`mcumgr`
* Confirm the uploaded image using :file:`mcumgr` (optional)
Perhaps the easiest sample to test with is the :zephyr_file:`samples/hello_world` Upload the signed image
sample provided by Zephyr, documented in the :ref:`hello_world` section. =======================
Edit :zephyr_file:`samples/hello_world/prj.conf` and enable the required MCUboot To upload the signed image, use the following command:
Kconfig option as described in :ref:`mcuboot` by adding the following line to
it:
.. code-block:: console .. code-block:: console
CONFIG_BOOTLOADER_MCUBOOT=y sudo mcumgr <connection string> image upload build/zephyr/zephyr.signed.bin
Then build the sample as usual (see :ref:`hello_world`).
Sign the second sample
----------------------
Next you will need to sign the sample just like you did for :file:`smp_svr`,
since it needs to be loaded by MCUboot.
Follow the same instructions described in :ref:`smp_svr_sample_sign`,
but this time you must use a :file:`.bin` image, since :file:`mcumgr` does not
yet support :file:`.hex` files.
Upload the image over BLE
-------------------------
Now we are ready to send or upload the image over BLE to the target remote
device.
.. code-block:: console
sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image upload signed.bin
If all goes well the image will now be stored in slot-1, ready to be swapped
into slot-0 and executed.
.. note:: .. note::
@ -226,54 +238,54 @@ into slot-0 and executed.
``mcumgr`` command line tool if this occurs. ``mcumgr`` command line tool if this occurs.
List the images List the images
--------------- ===============
We can now obtain a list of images (slot-0 and slot-1) present in the remote We can now obtain a list of images (slot-0 and slot-1) present in the remote
target device by issuing the following command: target device by issuing the following command:
.. code-block:: console .. code-block:: console
sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image list sudo mcumgr <connection string> image list
This should print the status and hash values of each of the images present. This should print the status and hash values of each of the images present.
Test the image Test the image
-------------- ==============
In order to instruct MCUboot to swap the images we need to test the image first, In order to instruct MCUboot to swap the images we need to test the image first,
making sure it boots: making sure it boots:
.. code-block:: console .. code-block:: console
sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image test <hash of slot-1 image> sudo mcumgr <connection string> image test <hash of slot-1 image>
Now MCUBoot will swap the image on the next reset. Now MCUBoot will swap the image on the next reset.
.. note::
There is not yet any way of getting the image hash without actually uploading the
image and getting the hash by using the ``image list`` command of :file:`mcumgr`.
Reset remotely Reset remotely
-------------- ==============
We can reset the device remotely to observe (use the console output) how We can reset the device remotely to observe (use the console output) how
MCUboot swaps the images: MCUboot swaps the images:
.. code-block:: console .. code-block:: console
sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' reset sudo mcumgr <connection string> reset
Upon reset MCUboot will swap slot-0 and slot-1. Upon reset MCUboot will swap slot-0 and slot-1.
The new image is the basic ``hello_world`` sample that does not contain Confirm new image
SMP or BLE functionality, so we cannot communicate with it using =================
:file:`mcumgr`. Instead simply reset the board manually to force MCUboot
to revert (i.e. swap back the images) due to the fact that the new image has
not been confirmed.
If you had instead built and uploaded a new image based on ``smp_svr`` The new image is now loaded into slot-0, but it will be swapped back into slot-1
(or another BLE and SMP enabled sample), you could confirm the on the next reset unless the image is confirmed. To confirm the new image:
new image and make the swap permanent by using this command:
.. code-block:: console .. code-block:: console
sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image confirm sudo mcumgr <connection string> image confirm
Note that if you try to send the very same image that is already flashed in Note that if you try to send the very same image that is already flashed in
slot-0 then the procedure will not complete successfully since the hash values slot-0 then the procedure will not complete successfully since the hash values

View file

@ -0,0 +1,17 @@
# Enable the UDP mcumgr transports.
CONFIG_MCUMGR_SMP_UDP=y
CONFIG_MCUMGR_SMP_UDP_IPV4=y
CONFIG_MCUMGR_SMP_UDP_IPV6=y
# Network settings
CONFIG_NETWORKING=y
CONFIG_NET_UDP=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_NET_CONNECTION_MANAGER=y
CONFIG_NET_BUF_USER_DATA_SIZE=24
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.168.1.1"
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"

View file

@ -11,3 +11,6 @@ tests:
sample.mcumg.smp_svr.bt: sample.mcumg.smp_svr.bt:
extra_args: OVERLAY_CONFIG="overlay-bt.conf" extra_args: OVERLAY_CONFIG="overlay-bt.conf"
platform_whitelist: nrf52dk_nrf52832 nrf52840dk_nrf52840 platform_whitelist: nrf52dk_nrf52832 nrf52840dk_nrf52840
sample.mcumg.smp_svr.udp:
extra_args: OVERLAY_CONFIG="overlay-udp.conf"
platform_whitelist: frdm_k64f

View file

@ -60,7 +60,7 @@ void main(void)
if (rc < 0) { if (rc < 0) {
LOG_ERR("Error initializing stats system [%d]", rc); LOG_ERR("Error initializing stats system [%d]", rc);
} }
/* Register the built-in mcumgr command handlers. */ /* Register the built-in mcumgr command handlers. */
#ifdef CONFIG_MCUMGR_CMD_FS_MGMT #ifdef CONFIG_MCUMGR_CMD_FS_MGMT
@ -83,7 +83,14 @@ void main(void)
#ifdef CONFIG_MCUMGR_SMP_BT #ifdef CONFIG_MCUMGR_SMP_BT
start_smp_bluetooth(); start_smp_bluetooth();
#endif #endif
#ifdef CONFIG_MCUMGR_SMP_UDP
start_smp_udp();
#endif
/* using __TIME__ ensure that a new binary will be built on every
* compile which is convient when testing firmware upgrade.
*/
LOG_INF("build time: " __DATE__ " " __TIME__);
/* The system work queue handles all incoming mcumgr requests. Let the /* The system work queue handles all incoming mcumgr requests. Let the
* main thread idle while the mcumgr server runs. * main thread idle while the mcumgr server runs.

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2020 Prevas A/S
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mgmt/smp_udp.h>
#include <net/net_mgmt.h>
#include <net/net_event.h>
#include <net/net_conn_mgr.h>
#define LOG_LEVEL LOG_LEVEL_DBG
#include <logging/log.h>
LOG_MODULE_REGISTER(smp_udp_sample);
#define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
static struct net_mgmt_event_callback mgmt_cb;
static void event_handler(struct net_mgmt_event_callback *cb,
u32_t mgmt_event, struct net_if *iface)
{
if ((mgmt_event & EVENT_MASK) != mgmt_event) {
return;
}
if (mgmt_event == NET_EVENT_L4_CONNECTED) {
LOG_INF("Network connected");
if (smp_udp_open() < 0) {
LOG_ERR("could not open smp udp");
}
return;
}
if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
LOG_INF("Network disconnected");
smp_udp_close();
return;
}
}
void start_smp_udp(void)
{
net_mgmt_init_event_callback(&mgmt_cb, event_handler, EVENT_MASK);
net_mgmt_add_event_callback(&mgmt_cb);
net_conn_mgr_resend_status();
}