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    * UDP
18
19``smp_svr`` enables support for the following command groups:
20
21    * ``fs_mgmt``
22    * ``img_mgmt``
23    * ``os_mgmt``
24    * ``stat_mgmt``
25    * ``shell_mgmt``
26
27Caveats
28*******
29
30* The MCUboot bootloader is required for ``img_mgmt`` to function
31  properly. More information about the Device Firmware Upgrade subsystem and
32  MCUboot can be found in :ref:`mcuboot`.
33
34* The :file:`mcumgr` command-line tool only works with Bluetooth Low Energy (BLE)
35  on Linux and macOS. On Windows there is no support for Device Firmware
36  Upgrade over BLE yet.
37
38Prerequisites
39*************
40
41Installing the mcumgr cli
42=========================
43
44To interact remotely with the management subsystem on a device, we need to have the
45:file:`mcumgr` installed. Follow the instructions in the :ref:`mcumgr_cli` section
46of the Management subsystem documentation.
47
48Building a BLE Controller
49=========================
50
51.. note::
52   This section is only relevant for Linux users
53
54If you want to try out Device Firmware Upgrade (DFU) over the air using
55Bluetooth Low Energy (BLE) and do not have a built-in or pluggable BLE radio,
56you can build one and use it following the instructions in
57:ref:`bluetooth-hci-uart-bluez`.
58
59Building and flashing MCUboot
60*****************************
61
62The below steps describe how to build and run the MCUboot bootloader.
63Detailed instructions can be found in the :ref:`mcuboot` documentation page.
64
65The Zephyr port of MCUboot is essentially a normal Zephyr application, which means that
66we can build and flash it like normal using ``west``, like so:
67
68.. code-block:: console
69
70   west build -b <board> -d build_mcuboot bootloader/mcuboot/boot/zephyr
71   west flash -d build_mcuboot
72
73Substitute <board> for one of the boards supported by the sample, see
74:file:`sample.yaml`.
75
76.. _smp_svr_sample_build:
77
78Building the sample application
79*******************************
80
81The below steps describe how to build and run the ``smp_svr`` sample in
82Zephyr. The ``smp_svr`` sample comes in different flavours.
83
84.. tabs::
85
86   .. group-tab:: Bluetooth
87
88      The sample application comes in two bluetooth flavours: a normal one and a tiny one
89      for resource constrained bluetooth devices.
90
91      To build the normal bluetooth sample:
92
93      .. code-block:: console
94
95         west build \
96            -b nrf52dk_nrf52832 \
97            samples/subsys/mgmt/mcumgr/smp_svr \
98            -- \
99            -DOVERLAY_CONFIG=overlay-bt.conf
100
101      And to build the tiny bluetooth sample:
102
103      .. code-block:: console
104
105         west build \
106            -b nrf51dk_nrf51422 \
107            samples/subsys/mgmt/mcumgr/smp_svr \
108            -- \
109            -DOVERLAY_CONFIG=overlay-bt-tiny.conf
110
111   .. group-tab:: Serial
112
113      To build the serial sample with file-system and shell management support:
114
115      .. code-block:: console
116
117         west build \
118            -b frdm_k64f \
119            samples/subsys/mgmt/mcumgr/smp_svr \
120            -- \
121            -DOVERLAY_CONFIG='overlay-serial.conf;overlay-fs.conf;overlay-shell-mgmt.conf'
122
123   .. group-tab:: USB CDC_ACM
124
125      To build the serial sample with USB CDC_ACM backend:
126
127      .. code-block:: console
128
129         west build \
130            -b nrf52840dk_nrf52840 \
131            samples/subsys/mgmt/mcumgr/smp_svr \
132            -- \
133            -DOVERLAY_CONFIG=overlay-cdc.conf
134
135   .. group-tab:: Shell
136
137      To build the shell sample:
138
139      .. code-block:: console
140
141         west build \
142            -b frdm_k64f \
143            samples/subsys/mgmt/mcumgr/smp_svr \
144            -- \
145            -DOVERLAY_CONFIG='overlay-shell.conf'
146
147   .. group-tab:: UDP
148
149      The UDP transport for SMP supports both IPv4 and IPv6.
150      In the sample, both IPv4 and IPv6 are enabled, but they can be
151      enabled and disabled separately.
152
153      To build the UDP sample:
154
155      .. code-block:: console
156
157         west build \
158            -b frdm_k64f \
159            samples/subsys/mgmt/mcumgr/smp_svr \
160            -- \
161            -DOVERLAY_CONFIG=overlay-udp.conf
162
163.. _smp_svr_sample_sign:
164
165Signing the sample image
166************************
167
168A key feature of MCUboot is that images must be signed before they can be successfully
169uploaded and run on a target. To sign images, the MCUboot tool :file:`imgtool` can be used.
170
171To sign the sample image we built in a previous step:
172
173.. code-block:: console
174
175    west sign -t imgtool -- --key bootloader/mcuboot/root-rsa-2048.pem
176
177The above command creates an image file called :file:`zephyr.signed.bin` in the
178build directory.
179
180For more information on image signing and ``west sign``, see the :ref:`west-sign`
181documentation.
182
183Flashing the sample image
184*************************
185
186Upload the :file:`zephyr.signed.bin` file from the previous to image slot-0 of your
187board.  See :ref:`flash_map_api` for details on flash partitioning.
188
189To upload the initial image file to an empty slot-0, we simply use ``west flash``
190like normal. ``west flash`` will automatically detect slot-0 address and confirm
191the image.
192
193.. code-block:: console
194
195    west flash --bin-file build/zephyr/zephyr.signed.bin
196
197We need to explicity specify the *signed* image file, otherwise the non-signed version
198will be used and the image wont be runnable.
199
200Sample image: hello world!
201==========================
202
203The ``smp_svr`` app is ready to run.  Just reset your board and test the app
204with the :file:`mcumgr` command-line tool's ``echo`` functionality, which will
205send a string to the remote target device and have it echo it back:
206
207.. tabs::
208
209   .. group-tab:: Bluetooth
210
211      .. code-block:: console
212
213         sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' echo hello
214         hello
215
216   .. group-tab:: Shell
217
218      .. code-block:: console
219
220         mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" echo hello
221         hello
222
223   .. group-tab:: UDP
224
225      Using IPv4:
226
227      .. code-block:: console
228
229         mcumgr --conntype udp --connstring=[192.168.1.1]:1337 echo hello
230         hello
231
232      And using IPv6
233
234      .. code-block:: console
235
236         mcumgr --conntype udp --connstring=[2001:db8::1]:1337 echo hello
237         hello
238
239.. note::
240   The :file:`mcumgr` command-line tool requires a connection string in order
241   to identify the remote target device. In the BT sample we use a BLE-based
242   connection string, and you might need to modify it depending on the
243   BLE controller you are using.
244
245.. note::
246   In the following sections, examples will use ``<connection string>`` to represent
247   the ``--conntype <type>`` and ``--connstring=<string>`` :file:`mcumgr` parameters.
248
249J-Link Virtual MSD Interaction Note
250***********************************
251
252On boards where a J-Link OB is present which has both CDC and MSC (virtual Mass
253Storage Device, also known as drag-and-drop) support, the MSD functionality can
254prevent mcumgr commands over the CDC UART port from working due to how USB
255endpoints are configured in the J-Link firmware (for example on the Nordic
256``nrf52840dk``) because of limiting the maximum packet size (most likely to occur
257when using image management commands for updating firmware). This issue can be
258resolved by disabling MSD functionality on the J-Link device, follow the
259instructions on :ref:`nordic_segger_msd` to disable MSD support.
260
261Device Firmware Upgrade (DFU)
262*****************************
263
264Now that the SMP server is running on your board and you are able to communicate
265with it using :file:`mcumgr`, you might want to test what is commonly called
266"OTA DFU", or Over-The-Air Device Firmware Upgrade. This works for both BT and UDP.
267
268The general sequence of a DFU process is as follows:
269
270* Build an MCUboot enabled application, see :ref:`smp_svr_sample_build`
271* Sign the application image, see :ref:`smp_svr_sample_sign`
272* Upload the signed image using :file:`mcumgr`
273* Listing the images on the device using :file:`mcumgr`
274* Mark the uploaded image for testing using :file:`mcumgr`
275* Reset the device remotely using :file:`mcumgr`
276* Confirm the uploaded image using :file:`mcumgr` (optional)
277
278Direct image upload and Image mapping to MCUboot slot
279=====================================================
280
281Currently the mcumgr supports, for direct upload, 4 target images, of which first two are mapped
282into MCUboot primary (slot-0) and secondary (slot-1) respectively.
283
284The mcumgr ``image upload`` command may be provided optional ``-e -n <image>`` parameter that will
285select target image for upload; when parameter is no provided, 0 is assumed, which means "default
286behaviour", and it performs upload to the "image-1", the MCUboot secondary slot.
287
288For clarity, here is DTS label to slot to ``<image>`` translation table:
289
290    +-----------+--------+------------+
291    | DTS label | Slot   | -n <image> |
292    +===========+========+============+
293    | "image-0" | slot-0 |     1      |
294    +-----------+--------+------------+
295    | "image-1" | slot-1 |     0, 1   |
296    +-----------+--------+------------+
297    | "image-2" |        |     2      |
298    +-----------+--------+------------+
299    | "image-3" |        |     3      |
300    +-----------+--------+------------+
301
302.. note::
303
304   The ``-e`` option actually means "no erase", and is provided to the mcumgr
305   to prevent it from sending erase command to target, before updating image.
306   The options is always needed when ``-n`` is used for image selection,
307   as the erase command is hardcoded to erase slot-1 ("image-1"),
308   regardless of which slot is uploaded at the time.
309
310Upload the signed image
311=======================
312
313To upload the signed image, use the following command:
314
315.. code-block:: console
316
317   sudo mcumgr <connection string> image upload build/zephyr/zephyr.signed.bin
318
319.. note::
320
321   At the beginning of the upload process, the target might start erasing
322   the image slot, taking several dozen seconds for some targets.  This might
323   cause an NMP timeout in the management protocol tool. Use the
324   ``-t <timeout-in-seconds`` option to increase the response timeout for the
325   ``mcumgr`` command line tool if this occurs.
326
327List the images
328===============
329
330We can now obtain a list of images (slot-0 and slot-1) present in the remote
331target device by issuing the following command:
332
333.. code-block:: console
334
335   sudo mcumgr <connection string> image list
336
337This should print the status and hash values of each of the images present.
338
339Test the image
340==============
341
342In order to instruct MCUboot to swap the images we need to test the image first,
343making sure it boots:
344
345.. code-block:: console
346
347   sudo mcumgr <connection string> image test <hash of slot-1 image>
348
349Now MCUBoot will swap the image on the next reset.
350
351.. note::
352   There is not yet any way of getting the image hash without actually uploading the
353   image and getting the hash by using the ``image list`` command of :file:`mcumgr`.
354
355Reset remotely
356==============
357
358We can reset the device remotely to observe (use the console output) how
359MCUboot swaps the images:
360
361.. code-block:: console
362
363   sudo mcumgr <connection string> reset
364
365Upon reset MCUboot will swap slot-0 and slot-1.
366
367Confirm new image
368=================
369
370The new image is now loaded into slot-0, but it will be swapped back into slot-1
371on the next reset unless the image is confirmed. To confirm the new image:
372
373.. code-block:: console
374
375   sudo mcumgr <connection string> image confirm
376
377Note that if you try to send the very same image that is already flashed in
378slot-0 then the procedure will not complete successfully since the hash values
379for both slots will be identical.
380
381Download file from File System
382******************************
383
384SMP server supports downloading files from File System on device via
385:file:`mcumgr`. This is useful with FS log backend, when files are stored in
386non-volatile memory. Build and flash both MCUboot and smp_svr applications and
387then use :file:`mcumgr` with :file:`download` command, e.g.:
388
389.. code-block:: console
390
391   mcumgr --conntype serial --connstring='dev=/dev/ttyACM0,baud=115200' \
392   fs download /lfs/log.0000 ~/log.txt
393