Note: From nRF Connect SDK v1.7.0 onwards, if you build for the thingy91_nrf9160_ns or thingy91_nrf52840, everything in this guide is already done automatically. Since that SDK release, the board files for the Thingy:91 include everything from all the steps in this guide.
The Thingy:91 is a great platform to develop your nRF9160 prototypes on, or to test the nRF9160 in the field. If the default application from the factory doesn't do what you want, you can use an external programmer, or the bootloader to program other applications to it. The Thingy:91 user guide explains both how to program the Thingy:91 with external programmers, and with DFU over USB. But, the guide assumes you already have compatible .hex files. In this guide, I will explain how to modify your project so it is compatible with the bootloader on the Thingy:91. I will be using the nrf9160/gps sample in NCS v1.4.2 as an example in this guide, but you can use any project that can run on the Thingy:91.
If you have removed the bootloader from the Thingy:91 (e.g. by programming a project without the bootloader with an external programmer), you can restore the bootloader by building and flashing the asset_tracker for the Thingy:91, or you can use one of the pre-compiled applications.
There are three steps we need to take to make it possible to do a DFU upgrade to our project possible:
1. Add a bootloader to our project.
2. Add correct bootloader settings.
3. Add static PM configuration.
1. Add a bootloader to our project
NCS uses the MCUBoot bootloader, and this is also what is on the Thingy:91. You can read more about the MCUBoot bootloader in the MCUBoot documentation. MCUBoot expects the DFU image to be formatted a correctly, with a header containing information about the image. The easiest way to create a DFU image is to add the bootloader to our project, and the build system will create the DFU image automatically.
You can add the bootloader to your project by adding the following line to your prj.conf file (for the gps sample, this is <your NCS installation>/nrf/samples/nrf9160/gps/prj.conf):
CONFIG_BOOTLOADER_MCUBOOT=y
Note that if you are building your project with SES, you must run 'Project -> Run CMake...' or re-open the project to make changes to project files (e.g. prj.conf, CMakeLists.txt or overlay files) to take effect.
Adding this line will do two things: It will add the bootloader to your project, so the bootloader also gets compiled; and it will cause the build system to output DFU images in addition to the normal images. You can find a list over the different images provided by the build system, and their uses here in the MCUBoot documentation.
The bootloader will be added to merged.hex, but in this case, we are more interested in the DFU image: app_signed.hex.
2. Add correct bootloader settings
If we were to try to program the DFU image now, it would not work, for two reasons: The image is signed with wrong algorithm, and not using the right flash partitioning scheme.
Let's handle the first issue first.
MCUBoot supports both ECDSA and RSA signatures, and on the nRF9160, it will use ECDSA signatures by default. However, this presents some issues, as explained in the MCUBoot documentation. Because of these problems, the Thingy:91 bootloader is using RSA signatures instead. We must therefore configure MCUBoot to sign our DFU images with RSA to make them compatible with the bootloader on the Thingy:91.
While we can change the MCUBoot configuration in several ways, the best way is to add a configuration overlay file. That way, we don't have to make any changes to MCUBoot, and can keep all our modification local to our project.
To make a configuration overlay file, create a new file in the project directory (e.g. nrf/samples/nrf9160/gps), and give it a fitting name, e.g. mcuboot_overlay-rsa.conf.
The configuration overlay file will contain the following configuration options:
CONFIG_BOOT_SIGNATURE_TYPE_RSA=y CONFIG_BOOT_SIGNATURE_KEY_FILE="root-rsa-2048.pem"
Note: This configures MCUBoot to use the default RSA keys, so that it is compatible with the bootloader present on the Thingy:91 from the factory. They should only be used for development. In production you should use your own keys, which are kept secret. See here for more information.
This will give us the following file:
5165.mcuboot_overlay-thingy91.conf
Note: DevZone has a tendency to add numbers to filenames to make them unique. If you want to use this file (without changing the name in the CMakeLists.txt file, you must remove these numbers from the file name.
Now, we need to add the file to our project. We can do that by adding the following lines to the CMakeLists.txt file, right below the line with cmake_minimum_required:
list(APPEND mcuboot_OVERLAY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/mcuboot_overlay-thingy91.conf" )
If you chose a different name for the configuration overlay file, or placed it in a different place, you must change the file path accordingly.
In the case of the gps sample, the CMakeLists.txt file should now look like this:
# # Copyright (c) 2019 Nordic Semiconductor # # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic # cmake_minimum_required(VERSION 3.13.1) list(APPEND mcuboot_OVERLAY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/mcuboot_overlay-thingy91.conf" ) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(gps_socket_sample) zephyr_library_sources(src/main.c) zephyr_library_sources_ifdef( CONFIG_SUPL_CLIENT_LIB src/supl_support.c )
3. Add static PM configuration
The last thing we need to do is to add a static Partition Manager (PM) configuration. When building multi-image projects (e.g. application and SPM; or application, SPM and bootloader), the Partition Manager script will partition the flash between each image. It will also reserve space for non-volatile storage if enabled, and reserve space for a second DFU bank if the bootloader is enabled. You can read more about the Partition Manager here: Partition Manager.
The PM runs for every build, and can therefore partition the flash differently for every build. Best case, that will just give use problems when doing DFU. For example, the DFU image is linked for the wrong place in flash. Another problem that can arise is if the application must mark itself as "okay" with boot_write_img_confirmed(), it will write that it is okay in the wrong place, so the bootloader rolls back the update on the next reboot. Worst case, we can overwrite important data stored in flash. Therefore, when we are building a project that must be compatible with a bootloader already programmed to a device, we must add a static partition manager configuration file.
When you are working on a project, and you want to preserve the PM configuration across different versions of the same project, the normal solution is to build the first version normally, then extract the pm.yml file from the build directory, and save it in the project directory as "pm_static.yml". But, in our case, we don't have the build folder from when the bootloader that is on the Thingy:91 was built. Instead, we will have to find it in the asset_tracker sample application, where the PM configuration has been stored.
The last step is therefore: Copy nrf/applications/asset_tracker/configuration/thingy91_nrf9160ns/pm_static.yml, into your project directory.
With these steps completed, you should now be able to build your project, and program the app_signed.hex image to the Thingy:91 as explained in the Thingy:91 user guide.
You can find my modified gps sample below, together with a Git diff file of the modifications.