This exercise is not yet supported in nRF Connect SDK v2.7.0 or v2.8.0. The support is ongoing.
Apologies for any inconvenience.
There are multiple ways to create applications for the nRF91 Series. Two of the main choices a developer must make are:
We covered a lot of these topics in the Cellular IoT Fundamentals course.
With this in mind, in this exercise we will learn how to update the firmware of an nRF9160 DK or nRF91x1 DK over a cellular connection (LTE-M or NB-IoT). MCUboot and the swapping of firmware is the same here as we learned in the theory part of this section, so all we need to do is move the new firmware to the mcuboot_secondary
slot in the flash memory of the nRF91 Series.
We will split the “travel” of the firmware package into two steps:
mcuboot_secondary
slotThe nRF Connect SDK FOTA Download library is used to download firmware from a URL. If this update is an MCUboot update, it will automatically be downloaded into the mcuboot_secondary
slot. After the download is complete, it is automatically tagged as “test” by the library.
The FOTA Download library may be called directly from our application. However, several of the cloud libraries in the nRF Connect SDK has FOTA support built-in where FOTA Download is called automatically from the cloud library. See specific documentation for each cloud library for how they handle FOTA.
To download the firmware to the device, we must have uploaded the firmware somewhere. As with the previous exercises, we will use build/zephyr/app_update.bin
as our new firmware image. The FOTA Download library does not really care where this file is, as long as it has an URL and a filename. Because of this, it is possible to upload app_update.bin
to a public page and download it directly from this page, as done by our HTTP Update sample. However, this solution does not scale very well. With multiple different devices connected to the internet, we want a way to get an overview over our devices and a way to push updates to subsets of the devices. The different cloud providers have FOTA solutions which give us such functionality. Because of this, we will learn how to use the Device Management in NRF Cloud to host our FOTA firmware updates in this exercise. Other cloud providers will have similar functionality.
Open the code base of the exercise by navigating to Create a new application in the nRF Connect for VS Code extension, select Copy a sample, and search for Lesson 8 – Exercise 4.
Alternatively, in the GitHub repository for this course, go to the base code for this exercise, found in l8/l8_e4
or l8/v2.5.x/l8_e4
.
There exists two code bases for this exercise.
nRF Connect SDK v2.6.x: l8/l8_e4
.
nRF Connect SDK v2.5.x: l8/v2.5.x/l8_e4
.
This exercise contains a slimmed-down version of the cloud connection part of our Cellular: nRF Cloud multi-service sample. The provided code contains the source code needed to connect to nRF Cloud with MQTT using the nRF Cloud library. The application does not need any source code to receive updates via nRF Clouds. Instead, when we enable CONFIG_NRF_CLOUD_FOTA
in the application, the library will automatically receive FOTA for us.
Disclaimer: If you want to base your own code on this exercise, we recommend comparing the exercise sample on our Cellular: nRF Cloud multi-service sample to learn the differences between them.
This exercise assumes that you have already completed Cellular IoT Fundamentals, Lesson 1 – Exercise 1 to provision the nRF91 Series DK to nRF Cloud.
1. Build the application and flash it to your board.
Build the sample for nrf9160dk_nrf9160_ns
, nrf9161dk_nrf9161_ns
or nrf9151dk_nrf9151_ns
and flash it to the board. Observe that the sample successfully connects to nRF Cloud from the logs.
You should see the following:
*** Booting nRF Connect SDK 2.6.1-3758bcbfa5cd ***
I: Starting bootloader
I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Boot source: none
I: Image index: 0, Swap type: none
I: Bootloader chainload address offset: 0x10000
*** Booting nRF Connect SDK v2.5.0 ***
[00:00:00.506,561] <inf> cloud_connection: Setting up nRF Cloud library...
[00:00:00.514,190] <inf> cloud_connection: Waiting for network ready...
[00:00:03.239,227] <inf> cloud_connection: Network connectivity gained!
[00:00:04.239,440] <inf> cloud_connection: Network is ready
[00:00:04.239,471] <inf> cloud_connection: Connecting to nRF Cloud
[00:00:04.239,532] <inf> cloud_connection: Connected to nRF Cloud
[00:00:04.239,532] <dbg> cloud_connection: start_readiness_timeout: Starting cloud connection readiness timeout for 50 seconds
[00:00:04.239,562] <dbg> cloud_connection: cloud_connection_thread_fn: Awaiting disconnection from nRF Cloud
[00:00:04.288,360] <dbg> cloud_connection: cloud_event_handler: NRF_CLOUD_EVT_TRANSPORT_CONNECTING
[00:00:06.877,166] <dbg> cloud_connection: cloud_event_handler: NRF_CLOUD_EVT_TRANSPORT_CONNECTED
[00:00:07.459,930] <inf> nrf_cloud_codec_internal: AlertsEn changed to 0
[00:00:07.459,960] <inf> nrf_cloud_codec_internal: LogLvl changed to 1
[00:00:07.460,632] <dbg> cloud_connection: cloud_event_handler: NRF_CLOUD_EVT_RX_DATA_SHADOW
[00:00:07.509,185] <dbg> cloud_connection: cloud_event_handler: NRF_CLOUD_EVT_USER_ASSOCIATED
[00:00:08.153,381] <dbg> cloud_connection: cloud_event_handler: NRF_CLOUD_EVT_READY
[00:00:08.153,411] <dbg> cloud_connection: clear_readiness_timeout: Stopping cloud connection readiness timeout
[00:00:08.153,442] <dbg> cloud_connection: update_shadow: Updating shadow
[00:00:08.154,968] <dbg> cloud_connection: update_shadow: Updated shadow
Hello World! nrf9160dk_nrf9160
Terminal2. Enable FOTA for nRF Cloud.
Add the following line in the prj.conf
file
CONFIG_NRF_CLOUD_FOTA=y
Kconfig3. Build and flash the sample again.
4. Change something in the application.
Change something in the application, so we can confirm that the firmware has been updated, for example, add a print statement. Build the application again, but do not flash it to the DK.
5. Setup FOTA in nRF Cloud.
For this next step, we will set up the FOTA in nRF Cloud. Documentation on how to do this can be found at nRF Cloud docs: Updating device firmware.
5.1 First, we will have to add the nRF91 Series device to a group in nRF Cloud. Since the device has already been provisioned to nRF Cloud, we should see it in the Devices tab:
From here, click “Manage Group” and type in the name of a device group to create a new group. Then click “Save”.
5.2 Next up, we will add a new firmware bundle, with the firmware we will upload. Go to Device Management → Firmware Updates and select the “+” symbol under Bundles:
In the following Create Update Bundle window, upload build/zephyr/app_update.bin
or build/zephyr/dfu_application.zip
. Then fill out the rest of the fields. We can choose what we want for the name and version, but it is a good idea to make something that makes sense, and that we can increment later.
5.3 We will now create an update. For this we use the “Create Update” button at the top of the Firmware Updates page:
In the Create Update window, we fill in a name and description for the update. Then we choose the bundle that we just created and finally choose the group which we have our DK in:
Leave “Deploy now” unchecked and press “Create Update”.
5.4 Connect the nRF Terminal to the nRF91 device so we can watch the logs when the update starts.
5.5 After step 5.3, we get to a page for the Update:
Next up, we can deploy the update by pressing the large green button. Then we wait a little, and we should be able to see all devices in the group being queued for the update:
When the update has been deployed, nRF Cloud will publish an MQTT message to the device to tell it to start the download. Then all we have to do is wait, and the update should happen automatically. You can see that the update happens both in the status bar at nRF Cloud and in the logs from the nRF91 device.
5.6 When the update is finished, we can see the following logs:
[00:01:11.930,450] <inf> download_client: Downloaded 231200/236991 bytes (97%)
[00:01:12.343,994] <inf> download_client: Downloaded 232900/236991 bytes (98%)
[00:01:12.673,156] <inf> download_client: Downloaded 234600/236991 bytes (98%)
[00:01:13.074,157] <inf> download_client: Downloaded 236300/236991 bytes (99%)
[00:01:13.341,613] <inf> download_client: Downloaded 236991/236991 bytes (100%)
[00:01:13.348,907] <inf> download_client: Download complete
[00:01:13.441,650] <inf> dfu_target_mcuboot: MCUBoot image-0 upgrade scheduled. Reset device to apply
[00:01:13.443,542] <inf> nrf_cloud_fota: Download complete
[00:01:13.511,993] <dbg> cloud_connection: cloud_event_handler: NRF_CLOUD_EVT_FOTA_DONE, FOTA type: Application
[00:01:13.729,125] <dbg> cloud_connection: cloud_event_handler: NRF_CLOUD_EVT_FOTA_DONE, FOTA type: Application
TerminalAs we can see, we must restart the device to apply the update. Reset the nRF91 Series DK and observe the swap. The nRF Cloud library will then see that it has a pending update again, but when it realizes that its update is already completed, it will confirm the update, as to not swap back on its next reboot.
[00:00:21.164,031] <inf> nrf_cloud_fota: Job 50371521-dbe1-40b0-9e1c-ffffffffffff already completed... skipping
TerminalWith this, we have successfully updated the nRF91 Series DK application with FOTA.
6. Get notifications from the FOTA update.
We want to get notifications from the FOTA update, and we can handle these in src/cloud_connection.c
and the function cloud_event_handler()
.
6.1 To show what can be implemented, we can set the device to automatically restart after FOTA.
6.1.1 Add the following line in cloud_connection.c
#include <zephyr/sys/reboot.h>
C6.1.2 Add the following line in cloud_connection.c
sys_reboot(SYS_REBOOT_COLD);
CAdd sys_reboot()
inside the NRF_CLOUD_EVT_FOTA_DONE
case.
6.2 Follow steps 4 and 5 again to test this, and observe that the device will now automatically reboot after the FOTA update.
7. Update the modem firmware over FOTA:
It is also possible to update the modem firmware using this exercise. This is possible for modem delta updates without external flash. For full modem updates, external flash must be added. See the source code for the nRF Cloud multi service sample if you need to enable full modem updates.
7.1 First, we check the current modem firmware version. To do this in nRF Cloud, we select the device from the Devices menu:
Then we can find the modem version information under Device Info:
7.2 If the device needs updating, add a modem firmware update and deploy it, as we did in step 5.
7.3 As with the application update, an MQTT message should be received by the nRF91 Series device, automatically starting the modem delta update.
The solution for this exercise can be found in the GitHub repository, l8/l8_e4_sol
or l8/v2.5.x/l8_e4_sol
.