1.. _smp_svr_sample:
2
3SMP Server Sample
4#################
5
6Overview
7********
8
9This sample application implements a Simple Management Protocol (SMP) server.
10SMP is a basic transfer encoding for use with the MCUmgr management protocol.
11For more information about MCUmgr and SMP, please see :ref:`device_mgmt`.
12
13This sample application supports the following mcumgr transports by default:
14
15    * Shell
16    * Bluetooth
17
18``smp_svr`` enables support for the following command groups:
19
20    * ``fs_mgmt``
21    * ``img_mgmt``
22    * ``os_mgmt``
23    * ``stat_mgmt``
24
25Caveats
26*******
27
28* The Zephyr port of ``smp_svr`` is configured to run on a Nordic nRF52x MCU. The
29  application should build and run for other platforms without modification.
30
31* The MCUboot bootloader is required for ``img_mgmt`` to function
32  properly. More information about the Device Firmware Upgrade subsystem and
33  MCUboot can be found in :ref:`mcuboot`.
34
35* The :file:`mcumgr` command-line tool only works with Bluetooth Low Energy (BLE)
36  on Linux and macOS. On Windows there is no support for Device Firmware
37  Upgrade over BLE yet.
38
39Building a BLE Controller (optional)
40************************************
41
42.. note::
43   This section is only relevant for Linux users
44
45If you want to try out Device Firmware Upgrade (DFU) over the air using
46Bluetooth Low Energy (BLE) and do not have a built-in or pluggable BLE radio,
47you can build one and use it following the instructions in
48:ref:`bluetooth-hci-uart-bluez`.
49
50Building and Running
51********************
52
53The below steps describe how to build and run the ``smp_svr`` sample in
54Zephyr. Where examples are given, they assume the sample is being built for
55the Nordic nRF52 Development Kit (``BOARD=nrf52_pca10040``).
56
57If you would like to use a more constrained platform, such as the nRF51 DK, you
58should use the :file:`prj_tiny.conf` configuration file rather than the default
59:file:`prj.conf`.
60
61Step 1: Build MCUboot
62=====================
63
64Build MCUboot by following the instructions in the :ref:`mcuboot`
65documentation page.
66
67Step 2: Flash MCUboot
68======================
69
70Flash the resulting image file to address 0x0 of flash memory.
71This can be done in multiple ways.
72
73Using make or ninja:
74
75.. code-block:: console
76
77   make flash
78   # or
79   ninja flash
80
81Using GDB:
82
83.. code-block:: console
84
85   restore <path-to-mcuboot-zephyr.bin> binary 0
86
87Step 3: Build smp_svr
88=====================
89
90``smp_svr`` can be built for the nRF52 as follows:
91
92.. zephyr-app-commands::
93    :zephyr-app: samples/subsys/mgmt/mcumgr/smp_svr
94    :board: nrf52_pca10040
95    :build-dir: nrf52_pca10040
96    :goals: build
97
98.. _smp_svr_sample_sign:
99
100Step 4: Sign the image
101======================
102
103.. note::
104   From this section onwards you can use either a binary (``.bin``) or an
105   Intel Hex (``.hex``) image format. This is written as ``(bin|hex)`` in this
106   document.
107
108Using MCUboot's :file:`imgtool.py` script, sign the :file:`zephyr.(bin|hex)`
109file you built in Step 3. In the below example, the MCUboot repo is located at
110:file:`~/src/mcuboot`.
111
112.. code-block:: console
113
114   ~/src/mcuboot/scripts/imgtool.py sign \
115        --key ~/src/mcuboot/root-rsa-2048.pem \
116        --header-size 0x200 \
117        --align 8 \
118        --version 1.0 \
119        --slot-size <image-slot-size> \
120        <path-to-zephyr.(bin|hex)> signed.(bin|hex)
121
122The above command creates an image file called :file:`signed.(bin|hex)` in the
123current directory.
124
125Step 5: Flash the smp_svr image
126===============================
127
128Upload the :file:`signed.(bin|hex)` file from Step 4 to image slot-0 of your
129board.  The location of image slot-0 varies by board, as described in
130:ref:`mcuboot_partitions`.  For the nRF52 DK, slot-0 is located at address
131``0xc000``.
132
133Using :file:`nrfjprog` you don't need to specify the slot-0 starting address,
134since :file:`.hex` files already contain that information:
135
136.. code-block:: console
137
138    nrfjprog --program <path-to-signed.hex>
139
140Using GDB:
141
142.. code-block:: console
143
144    restore <path-to-signed.bin> binary 0xc000
145
146Step 6: Run it!
147===============
148
149.. note::
150   If you haven't installed :file:`mcumgr` yet, then do so by following the
151   instructions in the :ref:`mcumgr_cli` section of the Management subsystem
152   documentation.
153
154.. note::
155   The :file:`mcumgr` command-line tool requires a connection string in order
156   to identify the remote target device. In this sample we use a BLE-based
157   connection string, and you might need to modify it depending on the
158   BLE controller you are using.
159
160
161The ``smp_svr`` app is ready to run.  Just reset your board and test the app
162with the :file:`mcumgr` command-line tool's ``echo`` functionality, which will
163send a string to the remote target device and have it echo it back:
164
165.. code-block:: console
166
167   sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' echo hello
168   hello
169
170
171Step 7: Device Firmware Upgrade
172===============================
173
174Now that the SMP server is running on your board and you are able to communicate
175with it using :file:`mcumgr`, you might want to test what is commonly called
176"OTA DFU", or Over-The-Air Device Firmware Upgrade.
177
178To do this, build a second sample (following the steps below) to verify
179it is sent over the air and properly flashed into slot-1, and then
180swapped into slot-0 by MCUboot.
181
182Build a second sample
183---------------------
184
185Perhaps the easiest sample to test with is the :zephyr_file:`samples/hello_world`
186sample provided by Zephyr, documented in the :ref:`hello_world` section.
187
188Edit :zephyr_file:`samples/hello_world/prj.conf` and enable the required MCUboot
189Kconfig option as described in :ref:`mcuboot` by adding the following line to
190it:
191
192.. code-block:: console
193
194   CONFIG_BOOTLOADER_MCUBOOT=y
195
196Then build the sample as usual (see :ref:`hello_world`).
197
198Sign the second sample
199----------------------
200
201Next you will need to sign the sample just like you did for :file:`smp_svr`,
202since it needs to be loaded by MCUboot.
203Follow the same instructions described in :ref:`smp_svr_sample_sign`,
204but this time you must use a :file:`.bin` image, since :file:`mcumgr` does not
205yet support :file:`.hex` files.
206
207Upload the image over BLE
208-------------------------
209
210Now we are ready to send or upload the image over BLE to the target remote
211device.
212
213.. code-block:: console
214
215   sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image upload signed.bin
216
217If all goes well the image will now be stored in slot-1, ready to be swapped
218into slot-0 and executed.
219
220.. note::
221
222   At the beginning of the upload process, the target might start erasing
223   the image slot, taking several dozen seconds for some targets.  This might
224   cause an NMP timeout in the management protocol tool. Use the
225   ``-t <timeout-in-seconds`` option to increase the response timeout for the
226   ``mcumgr`` command line tool if this occurs.
227
228List the images
229---------------
230
231We can now obtain a list of images (slot-0 and slot-1) present in the remote
232target device by issuing the following command:
233
234.. code-block:: console
235
236   sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image list
237
238This should print the status and hash values of each of the images present.
239
240Test the image
241--------------
242
243In order to instruct MCUboot to swap the images we need to test the image first,
244making sure it boots:
245
246.. code-block:: console
247
248   sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image test <hash of slot-1 image>
249
250Now MCUBoot will swap the image on the next reset.
251
252Reset remotely
253--------------
254
255We can reset the device remotely to observe (use the console output) how
256MCUboot swaps the images:
257
258.. code-block:: console
259
260   sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' reset
261
262Upon reset MCUboot will swap slot-0 and slot-1.
263
264The new image is the basic ``hello_world`` sample that does not contain
265SMP or BLE functionality, so we cannot communicate with it using
266:file:`mcumgr`. Instead simply reset the board manually to force MCUboot
267to revert (i.e. swap back the images) due to the fact that the new image has
268not been confirmed.
269
270If you had instead built and uploaded a new image based on ``smp_svr``
271(or another BLE and SMP enabled sample), you could confirm the
272new image and make the swap permanent by using this command:
273
274.. code-block:: console
275
276   sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' image confirm
277
278Note that if you try to send the very same image that is already flashed in
279slot-0 then the procedure will not complete successfully since the hash values
280for both slots will be identical.
281