samples/smp_svr: Update of Zephyr sample (#62)
The Zephyr version of mcumgr/smp_svr sample has been updated with current
(commit d380622a) version of source code from Zephyr repository:
zephyrpoject-rots/zephyr/tree/master/samples/subsys/mgmt/mcumgr/smp_svr
Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
diff --git a/samples/smp_svr/zephyr/CMakeLists.txt b/samples/smp_svr/zephyr/CMakeLists.txt
index 723108d..562ead4 100644
--- a/samples/smp_svr/zephyr/CMakeLists.txt
+++ b/samples/smp_svr/zephyr/CMakeLists.txt
@@ -1,3 +1,4 @@
+cmake_minimum_required(VERSION 3.13.1)
# Top-level CMakeLists.txt for the skeleton application.
#
# Copyright (c) 2017 Open Source Foundries Limited
@@ -7,23 +8,10 @@
# This provides a basic application structure suitable for communication using
# mcumgr. It can be used as a starting point for new applications.
-cmake_minimum_required(VERSION 3.14)
-
-# Zephyr uses Device Tree (DT) to describe some board hardware configuration.
-#
-# See the Zephyr documentation for more information on DT:
-# http://docs.zephyrproject.org/devices/dts/device_tree.html
-set(DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dts.overlay")
-
# Standard Zephyr application boilerplate.
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
-project(NONE)
-
-assert_exists(DTC_OVERLAY_FILE)
+project(smp_svr)
target_sources(app PRIVATE
src/main.c
)
-
-zephyr_link_libraries_ifdef(CONFIG_FILE_SYSTEM_NFFS NFFS)
-zephyr_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
diff --git a/samples/smp_svr/zephyr/README.rst b/samples/smp_svr/zephyr/README.rst
new file mode 100644
index 0000000..fefcb52
--- /dev/null
+++ b/samples/smp_svr/zephyr/README.rst
@@ -0,0 +1,280 @@
+.. _smp_svr_sample:
+
+SMP Server Sample
+#################
+
+Overview
+********
+
+This sample application implements a Simple Management Protocol (SMP) server.
+SMP is a basic transfer encoding for use with the MCUmgr management protocol.
+For more information about MCUmgr and SMP, please see :ref:`device_mgmt`.
+
+This sample application supports the following mcumgr transports by default:
+
+ * Shell
+ * Bluetooth
+
+``smp_svr`` enables support for the following command groups:
+
+ * ``fs_mgmt``
+ * ``img_mgmt``
+ * ``os_mgmt``
+ * ``stat_mgmt``
+
+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
+ properly. More information about the Device Firmware Upgrade subsystem and
+ MCUboot can be found in :ref:`mcuboot`.
+
+* The :file:`mcumgr` command-line tool only works with Bluetooth Low Energy (BLE)
+ on Linux and macOS. On Windows there is no support for Device Firmware
+ Upgrade over BLE yet.
+
+Building a BLE Controller (optional)
+************************************
+
+.. note::
+ This section is only relevant for Linux users
+
+If you want to try out Device Firmware Upgrade (DFU) over the air using
+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
+:ref:`bluetooth-hci-uart-bluez`.
+
+Building and Running
+********************
+
+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
+the Nordic nRF52 Development Kit (``BOARD=nrf52_pca10040``).
+
+If you would like to use a more constrained platform, such as the nRF51 DK, you
+should use the :file:`prj_tiny.conf` configuration file rather than the default
+:file:`prj.conf`.
+
+Step 1: Build MCUboot
+=====================
+
+Build MCUboot by following the instructions in the :ref:`mcuboot`
+documentation page.
+
+Step 2: Flash MCUboot
+======================
+
+Flash the resulting image file to address 0x0 of flash memory.
+This can be done in multiple ways.
+
+Using make or ninja:
+
+.. code-block:: console
+
+ make flash
+ # or
+ ninja flash
+
+Using GDB:
+
+.. code-block:: console
+
+ restore <path-to-mcuboot-zephyr.bin> binary 0
+
+Step 3: Build smp_svr
+=====================
+
+``smp_svr`` can be built for the nRF52 as follows:
+
+.. zephyr-app-commands::
+ :zephyr-app: samples/subsys/mgmt/mcumgr/smp_svr
+ :board: nrf52_pca10040
+ :build-dir: nrf52_pca10040
+ :goals: build
+
+.. _smp_svr_sample_sign:
+
+Step 4: Sign the image
+======================
+
+.. note::
+ From this section onwards you can use either a binary (``.bin``) or an
+ 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)`
+file you built in Step 3. In the below example, the MCUboot repo is located at
+:file:`~/src/mcuboot`.
+
+.. code-block:: console
+
+ ~/src/mcuboot/scripts/imgtool.py sign \
+ --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
+current directory.
+
+Step 5: Flash the smp_svr image
+===============================
+
+Upload the :file:`signed.(bin|hex)` file from Step 4 to image slot-0 of your
+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
+``0xc000``.
+
+Using :file:`nrfjprog` you don't need to specify the slot-0 starting address,
+since :file:`.hex` files already contain that information:
+
+.. code-block:: console
+
+ nrfjprog --program <path-to-signed.hex>
+
+Using GDB:
+
+.. 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.
+
+
+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
+send a string to the remote target device and have it echo it back:
+
+.. code-block:: console
+
+ sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' echo hello
+ hello
+
+
+Step 7: Device Firmware Upgrade
+===============================
+
+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
+"OTA DFU", or Over-The-Air Device Firmware Upgrade.
+
+To do this, build a second sample (following the steps below) to verify
+it is sent over the air and properly flashed into slot-1, and then
+swapped into slot-0 by MCUboot.
+
+Build a second sample
+---------------------
+
+Perhaps the easiest sample to test with is the :zephyr_file:`samples/hello_world`
+sample provided by Zephyr, documented in the :ref:`hello_world` section.
+
+Edit :zephyr_file:`samples/hello_world/prj.conf` and enable the required MCUboot
+Kconfig option as described in :ref:`mcuboot` by adding the following line to
+it:
+
+.. code-block:: console
+
+ CONFIG_BOOTLOADER_MCUBOOT=y
+
+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::
+
+ At the beginning of the upload process, the target might start erasing
+ the image slot, taking several dozen seconds for some targets. This might
+ cause an NMP timeout in the management protocol tool. Use the
+ ``-t <timeout-in-seconds`` option to increase the response timeout for the
+ ``mcumgr`` command line tool if this occurs.
+
+List the images
+---------------
+
+We can now obtain a list of images (slot-0 and slot-1) present in the remote
+target device by issuing the following command:
+
+.. code-block:: console
+
+ sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image list
+
+This should print the status and hash values of each of the images present.
+
+Test the image
+--------------
+
+In order to instruct MCUboot to swap the images we need to test the image first,
+making sure it boots:
+
+.. code-block:: console
+
+ sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image test <hash of slot-1 image>
+
+Now MCUBoot will swap the image on the next reset.
+
+Reset remotely
+--------------
+
+We can reset the device remotely to observe (use the console output) how
+MCUboot swaps the images:
+
+.. code-block:: console
+
+ sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' reset
+
+Upon reset MCUboot will swap slot-0 and slot-1.
+
+The new image is the basic ``hello_world`` sample that does not contain
+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``
+(or another BLE and SMP enabled sample), you could confirm the
+new image and make the swap permanent by using this command:
+
+.. code-block:: console
+
+ sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image confirm
+
+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
+for both slots will be identical.
diff --git a/samples/smp_svr/zephyr/dts.overlay b/samples/smp_svr/zephyr/dts.overlay
deleted file mode 100644
index 7e73db7..0000000
--- a/samples/smp_svr/zephyr/dts.overlay
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Basic Device Tree overlay file.
- */
-
-/ {
- chosen {
- /* Use uart0 for the mcumgr UART transport. */
- zephyr,uart-mcumgr = &uart0;
- };
-};
diff --git a/samples/smp_svr/zephyr/prj.conf b/samples/smp_svr/zephyr/prj.conf
index dfa64c1..fe7fdcd 100644
--- a/samples/smp_svr/zephyr/prj.conf
+++ b/samples/smp_svr/zephyr/prj.conf
@@ -11,20 +11,18 @@
CONFIG_BT_L2CAP_TX_MTU=260
CONFIG_BT_RX_BUF_LEN=260
-# Enable the Bluetooth and shell mcumgr transports.
+# Enable the Bluetooth (unauthenticated) and shell mcumgr transports.
CONFIG_MCUMGR_SMP_BT=y
+CONFIG_MCUMGR_SMP_BT_AUTHEN=n
CONFIG_MCUMGR_SMP_SHELL=y
#CONFIG_MCUMGR_SMP_UART=y
-# Bluetooth support requires a net_buf user_data size >= 7.
-CONFIG_NET_BUF_USER_DATA_SIZE=8
-
# Enable flash operations.
CONFIG_FLASH=y
-# Enable the NFFS file system.
+# Enable the LittleFS file system.
CONFIG_FILE_SYSTEM=y
-CONFIG_FILE_SYSTEM_NFFS=y
+CONFIG_FILE_SYSTEM_LITTLEFS=y
# Required by the `taskstat` command.
CONFIG_THREAD_MONITOR=y
@@ -38,8 +36,3 @@
CONFIG_MCUMGR_CMD_IMG_MGMT=y
CONFIG_MCUMGR_CMD_OS_MGMT=y
CONFIG_MCUMGR_CMD_STAT_MGMT=y
-
-### nRF5 specific settings
-
-# Specify the location of the NFFS file system.
-CONFIG_FS_NFFS_FLASH_DEV_NAME="NRF5_FLASH_DRV_NAME"
diff --git a/samples/smp_svr/zephyr/prj.conf.tiny b/samples/smp_svr/zephyr/prj_tiny.conf
similarity index 71%
rename from samples/smp_svr/zephyr/prj.conf.tiny
rename to samples/smp_svr/zephyr/prj_tiny.conf
index c078980..9f526ba 100644
--- a/samples/smp_svr/zephyr/prj.conf.tiny
+++ b/samples/smp_svr/zephyr/prj_tiny.conf
@@ -15,21 +15,18 @@
CONFIG_BT_L2CAP_TX_MTU=260
CONFIG_BT_RX_BUF_LEN=260
-# Enable the Bluetooth and UART mcumgr transports.
+# Enable the Bluetooth (unauthenticated) and UART mcumgr transports.
CONFIG_MCUMGR_SMP_BT=y
+CONFIG_MCUMGR_SMP_BT_AUTHEN=n
#CONFIG_MCUMGR_SMP_SHELL=y
CONFIG_MCUMGR_SMP_UART=y
-# Bluetooth support requires a net_buf user_data size >= 7.
-CONFIG_NET_BUF_USER_DATA_SIZE=7
+# Disable Bluetooth unused features
+CONFIG_BT_GATT_READ_MULTIPLE=n
# Enable flash operations.
CONFIG_FLASH=y
-# Enable the NFFS file system.
-#CONFIG_FILE_SYSTEM=y
-#CONFIG_FILE_SYSTEM_NFFS=y
-
# Required by the `taskstat` command.
CONFIG_THREAD_MONITOR=y
@@ -42,8 +39,3 @@
CONFIG_MCUMGR_CMD_IMG_MGMT=y
CONFIG_MCUMGR_CMD_OS_MGMT=y
CONFIG_MCUMGR_CMD_STAT_MGMT=y
-
-### nRF5 specific settings
-
-# Specify the location of the NFFS file system.
-#CONFIG_FS_NFFS_FLASH_DEV_NAME="NRF5_FLASH"
diff --git a/samples/smp_svr/zephyr/sample.yaml b/samples/smp_svr/zephyr/sample.yaml
new file mode 100644
index 0000000..0bde1d8
--- /dev/null
+++ b/samples/smp_svr/zephyr/sample.yaml
@@ -0,0 +1,12 @@
+sample:
+ description: Simple Management Protocol sample
+ name: smp svr
+common:
+ harness: bluetooth
+ tags: bluetooth
+tests:
+ sample.mcumg.smp_svr.nrf51:
+ extra_args: CONF_FILE="prj_tiny.conf"
+ platform_whitelist: nrf51_pca10028
+ sample.mcumg.smp_svr.nrf52:
+ platform_whitelist: nrf52_pca10040 nrf52840_pca10056
diff --git a/samples/smp_svr/zephyr/src/main.c b/samples/smp_svr/zephyr/src/main.c
index 4a21974..b3023ea 100644
--- a/samples/smp_svr/zephyr/src/main.c
+++ b/samples/smp_svr/zephyr/src/main.c
@@ -8,18 +8,14 @@
#include <zephyr.h>
#include <string.h>
#include <stdlib.h>
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/conn.h>
-#include <bluetooth/gatt.h>
#include <stats/stats.h>
-#include <mgmt/smp_bt.h>
#include <mgmt/buf.h>
#ifdef CONFIG_MCUMGR_CMD_FS_MGMT
#include <device.h>
#include <fs/fs.h>
-#include <nffs/nffs.h>
#include "fs_mgmt/fs_mgmt.h"
+#include <fs/littlefs.h>
#endif
#ifdef CONFIG_MCUMGR_CMD_OS_MGMT
#include "os_mgmt/os_mgmt.h"
@@ -31,8 +27,12 @@
#include "stat_mgmt/stat_mgmt.h"
#endif
-#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
-#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
+#ifdef CONFIG_MCUMGR_SMP_BT
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/gatt.h>
+#include <mgmt/smp_bt.h>
+#endif
/* Define an example stats group; approximates seconds since boot. */
STATS_SECT_START(smp_svr_stats)
@@ -48,15 +48,18 @@
STATS_SECT_DECL(smp_svr_stats) smp_svr_stats;
#ifdef CONFIG_MCUMGR_CMD_FS_MGMT
-static struct nffs_flash_desc flash_desc;
-
-static struct fs_mount_t nffs_mnt = {
- .type = FS_NFFS,
- .mnt_point = "/nffs",
- .fs_data = &flash_desc,
+FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(cstorage);
+static struct fs_mount_t littlefs_mnt = {
+ .type = FS_LITTLEFS,
+ .fs_data = &cstorage,
+ .storage_dev = (void *)DT_FLASH_AREA_STORAGE_ID,
+ .mnt_point = "/lfs"
};
#endif
+#ifdef CONFIG_MCUMGR_SMP_BT
+static struct k_work advertise_work;
+
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA_BYTES(BT_DATA_UUID128_ALL,
@@ -64,18 +67,13 @@
0xd3, 0x4c, 0xb7, 0x1d, 0x1d, 0xdc, 0x53, 0x8d),
};
-static const struct bt_data sd[] = {
- BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
-};
-
-static void advertise(void)
+static void advertise(struct k_work *work)
{
int rc;
bt_le_adv_stop();
- rc = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
- sd, ARRAY_SIZE(sd));
+ rc = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
if (rc) {
printk("Advertising failed to start (rc %d)\n", rc);
return;
@@ -87,7 +85,7 @@
static void connected(struct bt_conn *conn, u8_t err)
{
if (err) {
- printk("Connection failed (err %u)\n", err);
+ printk("Connection failed (err 0x%02x)\n", err);
} else {
printk("Connected\n");
}
@@ -95,8 +93,8 @@
static void disconnected(struct bt_conn *conn, u8_t reason)
{
- printk("Disconnected (reason %u)\n", reason);
- advertise();
+ printk("Disconnected (reason 0x%02x)\n", reason);
+ k_work_submit(&advertise_work);
}
static struct bt_conn_cb conn_callbacks = {
@@ -113,12 +111,12 @@
printk("Bluetooth initialized\n");
- advertise();
+ k_work_submit(&advertise_work);
}
+#endif
void main(void)
{
- struct device *flash_dev;
int rc;
rc = STATS_INIT_AND_REG(smp_svr_stats, STATS_SIZE_32, "smp_svr_stats");
@@ -126,17 +124,9 @@
/* Register the built-in mcumgr command handlers. */
#ifdef CONFIG_MCUMGR_CMD_FS_MGMT
- flash_dev = device_get_binding(CONFIG_FS_NFFS_FLASH_DEV_NAME);
- if (!flash_dev) {
- printk("Error getting NFFS flash device binding\n");
- } else {
- /* set backend storage dev */
- nffs_mnt.storage_dev = flash_dev;
-
- rc = fs_mount(&nffs_mnt);
- if (rc < 0) {
- printk("Error mounting nffs [%d]\n", rc);
- }
+ rc = fs_mount(&littlefs_mnt);
+ if (rc < 0) {
+ printk("Error mounting littlefs [%d]\n", rc);
}
fs_mgmt_register_group();
@@ -151,6 +141,9 @@
stat_mgmt_register_group();
#endif
+#ifdef CONFIG_MCUMGR_SMP_BT
+ k_work_init(&advertise_work, advertise);
+
/* Enable Bluetooth. */
rc = bt_enable(bt_ready);
if (rc != 0) {
@@ -161,12 +154,13 @@
/* Initialize the Bluetooth mcumgr transport. */
smp_bt_register();
+#endif
/* The system work queue handles all incoming mcumgr requests. Let the
* main thread idle while the mcumgr server runs.
*/
while (1) {
- k_sleep(1000);
+ k_sleep(K_MSEC(1000));
STATS_INC(smp_svr_stats, ticks);
}
}