├── .gitignore ├── .images ├── after_swap.png ├── before_swap.png ├── both_core_update.png ├── detailed_swap.png ├── flash_addresses.png ├── flash_app.png ├── flash_boot_into_app.png ├── header_trailer.png ├── metadata.png ├── net_core_update.png ├── new_firmware.png ├── nrf5340_bootloaders.png ├── nrf_connect_app_connect.png ├── nrf_connect_app_dfu.png ├── overview_dfu.png ├── public_key.png ├── register_size.png ├── revert.png ├── serial_recovery.png ├── sign_image.png ├── smp_client_server.png ├── smp_vs_serial_recovery.png ├── swap.gif ├── swap.png └── two_slots.png ├── LICENSE ├── README.md ├── bootloader_samples ├── README.md ├── client_smp │ └── smp_client_ble │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── app_update.bin │ │ ├── cbor_module_patch_dfu_mcumgr.patch │ │ ├── prj.conf │ │ ├── sample.yaml │ │ └── src │ │ └── main.c ├── custom_image_hooks │ ├── CMakeLists.txt │ ├── README.md │ ├── boards │ │ ├── nrf5340dk_nrf5340_cpuapp.conf │ │ └── nrf5340dk_nrf5340_cpuapp_ns.conf │ ├── child_image │ │ └── mcuboot.conf │ ├── mcuboot_patch.diff │ ├── prj.conf │ └── src │ │ ├── main.c │ │ └── mcuboot_action_hooks.c ├── keys_and_signatures │ ├── README.md │ ├── mcuboot_detached_signature │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── keys_and_data │ │ │ ├── data │ │ │ │ └── .gitignore │ │ │ └── keys │ │ │ │ └── .gitignore │ │ ├── prj.conf │ │ ├── scripts │ │ │ ├── black_box │ │ │ │ ├── .gitignore │ │ │ │ ├── README.md │ │ │ │ ├── init.sh │ │ │ │ ├── sign_digest.sh │ │ │ │ └── sign_payload.sh │ │ │ └── detached_signature.sh │ │ ├── src │ │ │ └── main.c │ │ ├── sysbuild.conf │ │ └── sysbuild │ │ │ └── mcuboot.conf │ ├── mcuboot_manual_sign │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── auto_build.sh │ │ ├── auto_flash.sh │ │ ├── child_image │ │ │ └── mcuboot │ │ │ │ ├── custom_priv.pem │ │ │ │ └── prj.conf │ │ ├── keys │ │ │ └── test_priv.pem │ │ ├── prj.conf │ │ └── src │ │ │ └── main.c │ ├── mcuboot_smp_custom_key │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── child_image │ │ │ └── mcuboot.conf │ │ ├── custom_key_dir │ │ │ └── custom_priv.pem │ │ ├── prj.conf │ │ └── src │ │ │ └── main.c │ └── mcuboot_smp_encryption │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── child_image │ │ └── mcuboot.conf │ │ ├── custom_key_dir │ │ └── encryption_key.pem │ │ ├── nrf.patch │ │ ├── prj.conf │ │ └── src │ │ └── main.c ├── nrf5340 │ ├── README.md │ ├── mcuboot_smp_ble_nonsimultaneous │ │ └── README.md │ └── mcuboot_smp_ble_simultaneous │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── app.overlay │ │ ├── child_image │ │ ├── mcuboot.conf │ │ └── mcuboot.overlay │ │ ├── prj.conf │ │ └── src │ │ └── main.c ├── serial_recovery │ ├── README.md │ ├── mcuboot_netcore_serial_recovery │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── boards │ │ │ ├── nrf5340dk_nrf5340_cpuapp.conf │ │ │ └── nrf5340dk_nrf5340_cpuapp_ns.conf │ │ ├── child_image │ │ │ └── mcuboot.conf │ │ ├── prj.conf │ │ └── src │ │ │ └── main.c │ ├── mcuboot_serial_recovery_cdc_acm │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── prj.conf │ │ ├── src │ │ │ └── main.c │ │ ├── sysbuild.conf │ │ └── sysbuild │ │ │ ├── mcuboot.conf │ │ │ └── mcuboot.overlay │ ├── mcuboot_serial_recovery_cdc_acm_wait │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── prj.conf │ │ ├── src │ │ │ └── main.c │ │ ├── sysbuild.conf │ │ └── sysbuild │ │ │ ├── mcuboot.conf │ │ │ └── mcuboot.overlay │ └── mcuboot_serial_recovery_uart │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── prj.conf │ │ ├── src │ │ └── main.c │ │ ├── sysbuild.conf │ │ └── sysbuild │ │ └── mcuboot.conf ├── smp │ ├── README.md │ ├── mcuboot_smp_ble │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── prj.conf │ │ ├── src │ │ │ ├── bluetooth_smp.c │ │ │ ├── bluetooth_smp.h │ │ │ └── main.c │ │ └── sysbuild.conf │ ├── mcuboot_smp_uart │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── boards │ │ │ ├── nrf5340dk_nrf5340_cpuapp.conf │ │ │ └── nrf5340dk_nrf5340_cpuapp_ns.conf │ │ ├── prj.conf │ │ ├── src │ │ │ └── main.c │ │ └── sysbuild.conf │ ├── mcuboot_smp_uart_feat_external_flash │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── app.overlay │ │ ├── boards │ │ │ ├── nrf5340dk_nrf5340_cpuapp.conf │ │ │ └── nrf5340dk_nrf5340_cpuapp_ns.conf │ │ ├── prj.conf │ │ ├── src │ │ │ └── main.c │ │ ├── sysbuild.conf │ │ └── sysbuild │ │ │ ├── mcuboot.conf │ │ │ └── mcuboot.overlay │ └── mcuboot_smp_uart_feat_rtt │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── prj.conf │ │ ├── src │ │ └── main.c │ │ ├── sysbuild.conf │ │ └── sysbuild │ │ └── mcuboot.conf └── updatable_bootloader │ ├── README.md │ └── nsib_mcuboot_smp │ ├── CMakeLists.txt │ ├── README.md │ ├── VERSION │ ├── child_image │ └── mcuboot.conf │ ├── nsib_priv.pem │ ├── prj.conf │ └── src │ └── main.c ├── build_system └── custom_hex_partition │ ├── CMakeLists.txt │ ├── Kconfig │ ├── README.md │ ├── aci │ └── CMakeLists.txt │ ├── custom.hex │ ├── custom │ ├── CMakeLists.txt │ ├── pm.yml │ ├── prj.conf │ └── src │ │ └── main.c │ ├── pm_static.yml │ ├── prj.conf │ ├── sample.yaml │ ├── src │ └── main.c │ └── zephyr │ └── module.yml ├── crypto └── psa_csr │ ├── CMakeLists.txt │ ├── README.md │ ├── boards │ ├── nrf52840dk_nrf52840.conf │ ├── nrf5340dk_nrf5340_cpuapp.conf │ ├── nrf5340dk_nrf5340_cpuapp_ns.conf │ ├── nrf54l15pdk_nrf54l15_cpuapp.conf │ ├── nrf9151dk_nrf9151.conf │ ├── nrf9151dk_nrf9151_ns.conf │ ├── nrf9160dk_nrf9160.conf │ ├── nrf9160dk_nrf9160_ns.conf │ ├── nrf9161dk_nrf9161.conf │ └── nrf9161dk_nrf9161_ns.conf │ ├── csr_fixes_nrf.patch │ ├── prj.conf │ ├── sample.yaml │ └── src │ └── main.c ├── lowlevel ├── eraseprotect │ ├── CMakeLists.txt │ ├── README.md │ ├── prj.conf │ ├── sample.yaml │ ├── scripts │ │ ├── disable_eraseprotect.py │ │ ├── enable_eraseprotect.py │ │ └── read_eraseprotect_status.py │ └── src │ │ └── main.c └── uicr_write_customer │ ├── CMakeLists.txt │ ├── README.md │ ├── prj.conf │ └── src │ └── main.c ├── openthread_samples └── autojoin │ ├── commissioner │ ├── CMakeLists.txt │ ├── README.md │ ├── prj.conf │ ├── sample.yaml │ └── src │ │ └── main.c │ └── joiner │ ├── CMakeLists.txt │ ├── README.rst │ ├── prj.conf │ ├── sample.yaml │ └── src │ └── main.c └── peripherals └── lpcomp_system_off ├── CMakeLists.txt ├── app.overlay ├── prj.conf └── src └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | **/build/ 2 | **/.vscode/ 3 | hello_world/ 4 | -------------------------------------------------------------------------------- /.images/after_swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/after_swap.png -------------------------------------------------------------------------------- /.images/before_swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/before_swap.png -------------------------------------------------------------------------------- /.images/both_core_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/both_core_update.png -------------------------------------------------------------------------------- /.images/detailed_swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/detailed_swap.png -------------------------------------------------------------------------------- /.images/flash_addresses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/flash_addresses.png -------------------------------------------------------------------------------- /.images/flash_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/flash_app.png -------------------------------------------------------------------------------- /.images/flash_boot_into_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/flash_boot_into_app.png -------------------------------------------------------------------------------- /.images/header_trailer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/header_trailer.png -------------------------------------------------------------------------------- /.images/metadata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/metadata.png -------------------------------------------------------------------------------- /.images/net_core_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/net_core_update.png -------------------------------------------------------------------------------- /.images/new_firmware.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/new_firmware.png -------------------------------------------------------------------------------- /.images/nrf5340_bootloaders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/nrf5340_bootloaders.png -------------------------------------------------------------------------------- /.images/nrf_connect_app_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/nrf_connect_app_connect.png -------------------------------------------------------------------------------- /.images/nrf_connect_app_dfu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/nrf_connect_app_dfu.png -------------------------------------------------------------------------------- /.images/overview_dfu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/overview_dfu.png -------------------------------------------------------------------------------- /.images/public_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/public_key.png -------------------------------------------------------------------------------- /.images/register_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/register_size.png -------------------------------------------------------------------------------- /.images/revert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/revert.png -------------------------------------------------------------------------------- /.images/serial_recovery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/serial_recovery.png -------------------------------------------------------------------------------- /.images/sign_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/sign_image.png -------------------------------------------------------------------------------- /.images/smp_client_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/smp_client_server.png -------------------------------------------------------------------------------- /.images/smp_vs_serial_recovery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/smp_vs_serial_recovery.png -------------------------------------------------------------------------------- /.images/swap.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/swap.gif -------------------------------------------------------------------------------- /.images/swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/swap.png -------------------------------------------------------------------------------- /.images/two_slots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/.images/two_slots.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2023 Sigurd Hellesvik 2 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 3 | 4 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 5 | 6 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 7 | 8 | 9 | # Some of the code I use here is based on code from the nRF Connect SDK. 10 | 11 | LicenseID: LicenseRef-Nordic-5-Clause 12 | 13 | ExtractedText: 14 | Copyright (c) 2018, Nordic Semiconductor ASA 15 | 16 | All rights reserved. 17 | 18 | Redistribution and use in source and binary forms, with or without modification, 19 | are permitted provided that the following conditions are met: 20 | 21 | 1. Redistributions of source code must retain the above copyright notice, this 22 | list of conditions and the following disclaimer. 23 | 24 | 2. Redistributions in binary form, except as embedded into a Nordic 25 | Semiconductor ASA integrated circuit in a product or a software update for 26 | such product, must reproduce the above copyright notice, this list of 27 | conditions and the following disclaimer in the documentation and/or other 28 | materials provided with the distribution. 29 | 30 | 3. Neither the name of Nordic Semiconductor ASA nor the names of its 31 | contributors may be used to endorse or promote products derived from this 32 | software without specific prior written permission. 33 | 34 | 4. This software, with or without modification, must only be used with a 35 | Nordic Semiconductor ASA integrated circuit. 36 | 37 | 5. Any software provided in binary form under this license must not be reverse 38 | engineered, decompiled, modified and/or disassembled. 39 | 40 | THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 41 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 42 | OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 43 | DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 44 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 45 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 46 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 49 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Samples for the nRF Connect SDK 2 | Here I will post samples I work on for the nRF Connect SDK. 3 | They are mostly for my own use, but sometimes I might post them to showcase functionality for DevZone users. 4 | The samples will not be activly maintained, so do not excpect them to be up to date. 5 | The samples will be here as they are made, so do not excpect them to work (unless I have told you they should work). 6 | -------------------------------------------------------------------------------- /bootloader_samples/README.md: -------------------------------------------------------------------------------- 1 | # Bootloader Samples 2 | These are my bootloader samples. 3 | The official Bootloader sample from the nRF Connect SDK is the [SMP Server Sample](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/samples/subsys/mgmt/mcumgr/smp_svr/README.html). That one is properly tested. 4 | For some proper theory on Bootloaders and Device Firmware Upgrade (DFU), see the nRF Connect SDK on [Security](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/security_chapter.html). 5 | 6 | ## Version 7 | This repo is for the most part not updated to Sysbuild. This means that samples are not expected to work that well from NCS v2.7.0 and onwards. However, there are a lot of good samples on DevAcademy. See below: 8 | 9 | ## DevAcademy 10 | This git repo is starting to become a bit old. I have since helped writing a [Lesson on Bootloaders and DFU on DevAacademy](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-8-bootloaders-and-dfu-fota/). I recommend that you check out the lesson as well. 11 | 12 | 13 | ## Requirements 14 | Most of the samples here use [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/services/device_mgmt/mcumgr.html) to perform DFU. I recommend that you install it before starting. 15 | Find which serial connection the Developement Kit is connected to. This sample assumes /dev/ttyACM0. 16 | Linux: 17 | ``` 18 | mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" 19 | ``` 20 | Windows: 21 | ``` 22 | mcumgr conn add com20 type="serial" connstring="COM20,baud=115200,mtu=512" 23 | ``` 24 | 25 | ## Quick Start 26 | Are you here to just get the simplest possible bootloader sample work with a nRF chip? 27 | Start with the [Simple MCUboot SMP sample](smp/mcuboot_smp/) 28 | 29 | ## NSIB vs MCUboot 30 | In general, the nRF Connect SDK uses MCUboot for its bootloader. 31 | If you need an Upgradable Bootloader, the Nordic Secure Immutable Bootloader (NSIB) is generally used in addition to MCUboot. 32 | For more information on this, see [Bootloaders and Device Firmware Upgrade](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/app_bootloaders.html#app-bootloaders). 33 | 34 | ## SMP Server and Serial Recovery 35 | There are two versions of updating a device using MCUboot: SMP Server and Serial Recovery. 36 | Samples for these can be found in [Samples for SMP Server](smp/) and [Samples for Serial Recovery](serial_recovery/), respectivley. 37 | 38 | # Theory 39 | Disclaimer: This is unofficial, and just my understanding on how things works. I can be wrong. 40 | I will cover some of the basics very briefly. I recommend reading more up on these on The Internet. 41 | 42 | ## Why do a bootloader? 43 | The two main reasons for having a bootloaders are: 44 | 45 | ** 1. To verify that the firmware running on the microcontroller is yours and have not changed. ** 46 | 47 | ** 2. To update the microcontroller in the field. ** 48 | 49 | ![usecases](../.images/overview_dfu.png) 50 | 51 | ## Memory 52 | nRF microcontroller has two kinds of storage: 53 | **RAM**: Volatile memory. This is deleted on each reset. 54 | **Flash**: Non-Volatile memory. This is kept between resets. 55 | 56 | All data stored in nRF microcontrollers are saved in registers. Since the nRF chips are 32 bit, all registers are 32 bit. These are counted in hexatecimal(hex) numbers, and the first address is 0 and so on. Flash size will vary between microcontrollers, so in this theory part, I will use an imaginary flash with addresses from 0x0000 to 0xffff. 57 | The flash is parted into different registers as such: 58 | ![Register Addresses](../.images/flash_addresses.png) 59 | And each of these registers are 32 bit, as such: 60 | ![Register Size](../.images/register_size.png) 61 | 62 | ## Where is a program stored on a microcontroller? 63 | To make sure that your program(App) runs on the microcontroller each time you boot it, it will be stored in flash. 64 | When a nrf chip is powered on, it will begin by executing the code in the flash address 0 (0x0000): 65 | ![App stored in flash](../.images/flash_app.png) 66 | 67 | ## What is a bootloader? 68 | Simply put, a bootloader can be explained from the name: A bootloader starts at Boot and Loads your application. 69 | In other words, the bootloader will start at 0x0000. Then it will point to the start address of your application, and continue to run from there. 70 | ![Bootloader will boot into App](../.images/flash_boot_into_app.png) 71 | 72 | The nRF Connect SDK use the [Partition Manager](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html) to partition the flash into different areas. It has a tool which helps us visualize how the flash is partitioned for our applications: 73 | ``` 74 | west build -t partition_manager_report 75 | ``` 76 | If we run this command on the [Simple MCUboot SMP Server sample](smp/mcuboot_smp), the output will look like this: 77 | ``` 78 | -- west build: running target partition_manager_report 79 | flash_primary (0x100000 - 1024kB): 80 | +-------------------------------------------------+ 81 | | 0x0: mcuboot (0xc000 - 48kB) | 82 | +---0xc000: mcuboot_primary (0x7a000 - 488kB)-----+ 83 | | 0xc000: mcuboot_pad (0x200 - 512B) | 84 | +---0xc200: mcuboot_primary_app (0x79e00 - 487kB)-+ 85 | | 0xc200: app (0x79e00 - 487kB) | 86 | +-------------------------------------------------+ 87 | | 0x86000: mcuboot_secondary (0x7a000 - 488kB) | 88 | +-------------------------------------------------+ 89 | 90 | sram_primary (0x40000 - 256kB): 91 | +--------------------------------------------+ 92 | | 0x20000000: sram_primary (0x40000 - 256kB) | 93 | +--------------------------------------------+ 94 | ``` 95 | The format here is START\_ADDRESS: NAME (SIZE_HEX - SIZE_BYTE). 96 | 97 | You can also use the "Memory Report" functionality in VS Code to see a similar partition overview. 98 | 99 | In bootloader lingo, a partitioned parts of flash that the bootloader use for applications is often reffered to as **Image** or **Slot**. 100 | So in the above report, there are three main parts: The bootloader, a primary slot and a secondary slot. As such: 101 | ![Two Slots](../.images/two_slots.png) 102 | 103 | There is a reason for having two slots, which I will cover it in [SMP Samples](./smp). 104 | 105 | ## Basic Bootloader Features 106 | Now you might think: "Okey, so a bootloader starts the application. But what is the point of that?" 107 | This functionality lets us add some features to our program. The two most important features are to **Validate Images** and to allow for a **Device Firmare Upgrade (DFU)**. 108 | 109 | To read more about DFU, see the [SMP Samples](./smp). 110 | To read more about Validation and Keys, see [Keys and Signatures Samples](./keys_and_signatures). 111 | 112 | ## NSIB and MCUboot 113 | The nRF Connect SDK has support for two different bootloaders: Nordic Secure Immutable Bootloader and MCUboot. See [Secure Boot](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/security_chapter.html#secure-boot) for more information on these. 114 | This git project contains samples for both. 115 | 116 | ## How to configure the bootloader? 117 | As you already know, you can configure your project by using prj.conf. 118 | When you use a bootloader, it is added to your project as a [child image](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/ug_multi_image.html). 119 | MCUboot has a child image named "mcuboot" and NSIB has a child image named "b0". 120 | The configurations of a child image is separate from the configurations of the application. 121 | So you can not configure the bootloader by changing prj.conf. 122 | To overlay child image configurations, see [Image Specific Variables](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_multi_image.html#image-specific-variables). 123 | But for simplicity, you do it by creating a child\_image folder in your project. Then create for example "child\_image/mcuboot.conf" to configure mcuboot. 124 | These files can be seen in various samples in this git. 125 | 126 | ## Should I change the source code for MCUboot or NSIB? 127 | If you can avoid it, you should not. 128 | But if you need to change them for specific needs, I think the simplest solution will be to create a git fork of the bootloader and change nrf/west.yml to point the nRF Connect SDK to your bootloader. 129 | -------------------------------------------------------------------------------- /bootloader_samples/client_smp/smp_client_ble/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | cmake_minimum_required(VERSION 3.20.0) 7 | 8 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 9 | project(NONE) 10 | 11 | FILE(GLOB app_sources src/*.c) 12 | 13 | # NORDIC SDK APP START 14 | target_sources(app PRIVATE ${app_sources}) 15 | # NORDIC SDK APP END 16 | -------------------------------------------------------------------------------- /bootloader_samples/client_smp/smp_client_ble/README.md: -------------------------------------------------------------------------------- 1 | # Bluetooth: Central SMP Client DFU 2 | This example is copied from [https://github.com/simon-iversen/ncs_samples/tree/master/central_smp_client\_dfu](https://github.com/simon-iversen/ncs_samples/tree/master/central_smp_client\_dfu). 3 | I also have changed it some. 4 | 5 | With this sample you will be able to perform a DFU from one nRF52840DK to another nRF52840DK over Bluetooth Low Energy. 6 | 7 | ## Requirements 8 | This sample is tested with two nRF52840DK's and NCS v2.2.0 9 | 10 | ## Preparations 11 | 12 | This patch should be applied to _< ncs location >/modules/lib/zcbor/src/zcbor_decode.c_ in order to be able to parse cbor fields. I was not able to get _zcbor_bool_decode()_ to work, but after applying the below patch I was able to use zcbor_bool_expect() to parse cbor bool fields. 13 | ```diff 14 | diff --git a/src/zcbor_decode.c b/src/zcbor_decode.c 15 | index 09c3aa4..ece1466 100644 16 | --- a/src/zcbor_decode.c 17 | +++ b/src/zcbor_decode.c 18 | @@ -624,7 +624,8 @@ static bool primx_expect(zcbor_state_t *state, uint8_t result) 19 | } 20 | 21 | if (value != result) { 22 | - ERNG_R_RESTORE(ZCBOR_ERR_WROVALUE); 23 | + return false; 24 | + //ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE); 25 | } 26 | return true; 27 | } 28 | @@ -666,7 +667,7 @@ bool zcbor_bool_decode(zcbor_state_t *state, bool *result) 29 | bool zcbor_bool_expect(zcbor_state_t *state, bool result) 30 | { 31 | if (!primx_expect(state, (uint8_t)(!!result) + ZCBOR_BOOL_TO_PRIM)) { 32 | - ZCBOR_FAIL(); 33 | + return false; 34 | } 35 | return true; 36 | } 37 | 38 | ``` 39 | 40 | ## Instructions for updating the nRF52840 from another nRF52840 41 | 42 | I'm using the name nRF52840DK_client for the DK where the sample central_smp_client_dfu runs and the name nRF52840DK_server where the sample smp_svr runs 43 | 44 | 1. Program this sample (central_smp_client_dfu) to nRF52840DK_client 45 | 2. You will use mcumgr to upload the new image for the SMP Server to the Secondary slot of the SMP Client to test. See [SMP](../../smp) on how to set up mcumgr. 46 | 3. Run the following command: mcumgr -c acm0 image upload app_update.bin 47 | 4. Build and program the sample _\zephyr\samples\subsys\mgmt\mcumgr\smp_svr_ to nRF52840DK_server with the Kconfig fragment _\smp_svr\overlay-bt.conf_ applied 48 | 5. Reset both of the chips and open two serial terminal to se the logs. Make sure you see "connected" from both of the 52840's. You may get an error about failed security, but it doesn't matter 49 | 6. Press button 1 on nRF52840DK_client, to run the image list command, you should see something like this: 50 | 51 | ``` 52 | -----------PRIMARY IMAGE----------- 53 | slot: 0 54 | version: 0.0.0 55 | hash: 0xfe8db57ddd8f695ea11a9c626f156094818a9faf639b3580fe6e5d43a44be 56 | bootable: true 57 | pending: false 58 | confirmed: true 59 | active: true 60 | permanent: false 61 | ``` 62 | 7. Press button 2 on nRF52840DK_client to run the upload command. The progress bar should appear: 63 | ``` 64 | [ 55% ] |=========================== | (124000/222464 bytes) 65 | ``` 66 | 8. After the whole binary is transferred over to nRF52840DK_server, run the image list command again. You should see something like this: 67 | 68 | ``` 69 | -----------PRIMARY IMAGE----------- 70 | slot: 0 71 | version: 0.0.0 72 | hash: 0xfe8db57ddd8f695ea11a9c626f156094818a9faf639b3580fe6e5d43a44be 73 | bootable: true 74 | pending: false 75 | confirmed: true 76 | active: true 77 | permanent: false 78 | 79 | -----------SECONDARY IMAGE----------- 80 | slot: 1 81 | version: 0.0.0 82 | hash: 0xa54378a590f6615be1673d4162d312ef39f5c77631eb1d7a49607bafe1617eb4 83 | bootable: true 84 | pending: false 85 | confirmed: false 86 | active: false 87 | permanent: false 88 | ``` 89 | You can see that the pending field of the secondary image is set to false. 90 | 91 | 9. In order to test the image on reboot, press button 3 on nRF52840DK_client. The pending field of the secondary image should now be true 92 | 93 | ``` 94 | -----------PRIMARY IMAGE----------- 95 | slot: 0 96 | version: 0.0.0 97 | hash: 0xfe8db57ddd8f695ea11a9c626f156094818a9faf639b3580fe6e5d43a44be 98 | bootable: true 99 | pending: false 100 | confirmed: true 101 | active: true 102 | permanent: false 103 | 104 | -----------SECONDARY IMAGE----------- 105 | slot: 1 106 | version: 0.0.0 107 | hash: 0xa54378a590f6615be1673d4162d312ef39f5c77631eb1d7a49607bafe1617eb4 108 | bootable: true 109 | pending: true 110 | confirmed: false 111 | active: false 112 | permanent: false 113 | ``` 114 | 10. In order to swap the images, the smp_svr needs to be reset. Press button 4 on nRF52840DK_client to reset the nRF52840DK_server. You should see the following log on the nRF52840DK_server, if the update was successful: 115 | 116 | ``` 117 | *** Booting Zephyr OS build v3.0.99-ncs1 *** 118 | I: Starting bootloader 119 | I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 120 | I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3 121 | I: Boot source: none 122 | I: Swap type: test 123 | I: Starting swap using move algorithm. 124 | I: Bootloader chainload address offset: 0xc000 125 | *** Booting Zephyr OS build v3.0.99-ncs1 *** 126 | UPDATE SUCCESSFUL! 127 | 128 | 129 | [00:00:00.234,039] smp_bt_sample: Connected 130 | ``` 131 | 132 | The function boot_write_img_confirmed() is added to main() of the smp_svr update, so if you reset the nRF52840DK_server again, it won't revert back. 133 | -------------------------------------------------------------------------------- /bootloader_samples/client_smp/smp_client_ble/app_update.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellesvik-nordic/samples_for_nrf_connect_sdk/6c1af3c857e5d051754648ca2e50fb80a65b5cef/bootloader_samples/client_smp/smp_client_ble/app_update.bin -------------------------------------------------------------------------------- /bootloader_samples/client_smp/smp_client_ble/cbor_module_patch_dfu_mcumgr.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/zcbor_decode.c b/src/zcbor_decode.c 2 | index 09c3aa4..ece1466 100644 3 | --- a/src/zcbor_decode.c 4 | +++ b/src/zcbor_decode.c 5 | @@ -624,7 +624,8 @@ static bool primx_expect(zcbor_state_t *state, uint8_t result) 6 | } 7 | 8 | if (value != result) { 9 | - ERNG_R_RESTORE(ZCBOR_ERR_WROVALUE); 10 | + return false; 11 | + //ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE); 12 | } 13 | return true; 14 | } 15 | @@ -666,7 +667,7 @@ bool zcbor_bool_decode(zcbor_state_t *state, bool *result) 16 | bool zcbor_bool_expect(zcbor_state_t *state, bool result) 17 | { 18 | if (!primx_expect(state, (uint8_t)(!!result) + ZCBOR_BOOL_TO_PRIM)) { 19 | - ZCBOR_FAIL(); 20 | + return false; 21 | } 22 | return true; 23 | } 24 | -------------------------------------------------------------------------------- /bootloader_samples/client_smp/smp_client_ble/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | CONFIG_BT=y 7 | CONFIG_BT_DEBUG_LOG=y 8 | CONFIG_BT_CENTRAL=y 9 | CONFIG_BT_SMP=y 10 | CONFIG_BT_GATT_CLIENT=y 11 | CONFIG_BT_GATT_DM=y 12 | CONFIG_HEAP_MEM_POOL_SIZE=2048 13 | CONFIG_BT_DFU_SMP=y 14 | 15 | CONFIG_BT_L2CAP_TX_MTU=498 16 | CONFIG_BT_BUF_ACL_RX_SIZE=502 17 | CONFIG_BT_BUF_ACL_TX_SIZE=502 18 | CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 19 | 20 | CONFIG_BT_SCAN=y 21 | CONFIG_BT_SCAN_FILTER_ENABLE=y 22 | CONFIG_BT_SCAN_UUID_CNT=1 23 | 24 | CONFIG_ZCBOR=y 25 | CONFIG_ZCBOR_STOP_ON_ERROR=y 26 | 27 | CONFIG_DK_LIBRARY=y 28 | 29 | CONFIG_DEBUG_OPTIMIZATIONS=y 30 | 31 | CONFIG_FLASH=y 32 | 33 | CONFIG_BOOTLOADER_MCUBOOT=y 34 | CONFIG_MCUMGR=y 35 | CONFIG_MCUMGR_TRANSPORT_UART=y 36 | CONFIG_MCUMGR_GRP_IMG=y 37 | 38 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 39 | CONFIG_BASE64=y 40 | 41 | # CONFIG_MCUMGR_GRP_IMG dependencies 42 | CONFIG_FLASH=y 43 | CONFIG_IMG_MANAGER=y 44 | 45 | # CONFIG_IMG_MANAGER dependencies 46 | CONFIG_STREAM_FLASH=y 47 | 48 | # CONFIG_MCUMGR dependencies 49 | CONFIG_NET_BUF=y 50 | CONFIG_ZCBOR=y 51 | 52 | # Required for CONFIG_IMG_MANAGER 53 | CONFIG_FLASH_MAP=y 54 | -------------------------------------------------------------------------------- /bootloader_samples/client_smp/smp_client_ble/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Bluetooth Low Energy Central Device Firmware Update sample 3 | name: BLE Central DFU SMP 4 | tests: 5 | sample.bluetooth.central_dfu_smp: 6 | harness: bluetooth 7 | integration_platforms: 8 | - nrf51dk_nrf51422 9 | - nrf52dk_nrf52832 10 | - nrf52840dk_nrf52840 11 | platform_allow: nrf51dk_nrf51422 nrf52dk_nrf52832 nrf52840dk_nrf52840 12 | tags: bluetooth 13 | sample.bluetooth.central_dfu_smp.build: 14 | build_only: true 15 | integration_platforms: 16 | - nrf51dk_nrf51422 17 | - nrf52dk_nrf52832 18 | - nrf52840dk_nrf52840 19 | - nrf5340dk_nrf5340_cpuapp 20 | - nrf5340dk_nrf5340_cpuapp_ns 21 | platform_allow: nrf51dk_nrf51422 nrf52dk_nrf52832 nrf52840dk_nrf52840 nrf5340dk_nrf5340_cpuapp 22 | nrf5340dk_nrf5340_cpuapp_ns 23 | tags: bluetooth ci_build 24 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | set(mcuboot_CONFIG_MCUBOOT_ACTION_HOOKS_FILE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/src/mcuboot_action_hooks.c\") 6 | 7 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 8 | project(hello_world) 9 | 10 | target_sources(app PRIVATE src/main.c) 11 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/README.md: -------------------------------------------------------------------------------- 1 | # Custom MCUboot action hooks sample 2 | 3 | This is a sample showing how you can change MCUboot to add the ability to add attach a callback from your project to MCUboot Action Hooks. 4 | For the changes need to MCUboot, see [mcuboot_patch.diff](./mcuboot_patch.diff). 5 | 6 | ## Disclaimer 7 | This code/configuration is not thoroughly tested or qualified and should be considered provided “as-is”. Please test it with your application and let me know if you find any issues. 8 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/boards/nrf5340dk_nrf5340_cpuapp.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/boards/nrf5340dk_nrf5340_cpuapp_ns.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/child_image/mcuboot.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MCUBOOT_ACTION_HOOKS=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/mcuboot_patch.diff: -------------------------------------------------------------------------------- 1 | diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt 2 | index 2d6a6035..3e64c61f 100644 3 | --- a/boot/zephyr/CMakeLists.txt 4 | +++ b/boot/zephyr/CMakeLists.txt 5 | @@ -365,3 +365,33 @@ zephyr_library_sources( 6 | ${BOOT_DIR}/zephyr/nrf_cleanup.c 7 | ) 8 | endif() 9 | + 10 | +if(CONFIG_MCUBOOT_ACTION_HOOKS) 11 | + if(NOT CONFIG_MCUBOOT_ACTION_HOOKS_FILE_PATH STREQUAL "") 12 | + # CONF_FILE points to the KConfig configuration files of the bootloader. 13 | + foreach (filepath ${CONF_FILE}) 14 | + file(READ ${filepath} temp_text) 15 | + string(FIND "${temp_text}" ${CONFIG_MCUBOOT_ACTION_HOOKS_FILE_PATH} match) 16 | + if (${match} GREATER_EQUAL 0) 17 | + if (NOT DEFINED CONF_DIR) 18 | + get_filename_component(CONF_DIR ${filepath} DIRECTORY) 19 | + else() 20 | + message(FATAL_ERROR "Signature key file defined in multiple conf files") 21 | + endif() 22 | + endif() 23 | + endforeach() 24 | + 25 | + if(IS_ABSOLUTE ${CONFIG_MCUBOOT_ACTION_HOOKS_FILE_PATH}) 26 | + set(ACTION_HOOKS_FILE ${CONFIG_MCUBOOT_ACTION_HOOKS_FILE_PATH}) 27 | + elseif((DEFINED CONF_DIR) AND 28 | + (EXISTS ${CONF_DIR}/${CONFIG_MCUBOOT_ACTION_HOOKS_FILE_PATH})) 29 | + set(ACTION_HOOKS_FILE ${CONF_DIR}/${CONFIG_MCUBOOT_ACTION_HOOKS_FILE_PATH}) 30 | + else() 31 | + set(ACTION_HOOKS_FILE ${MCUBOOT_DIR}/${CONFIG_MCUBOOT_ACTION_HOOKS_FILE_PATH}) 32 | + endif() 33 | + message("Custom MCUboot Action hooks file: ${ACTION_HOOKS_FILE}") 34 | + zephyr_library_sources( 35 | + ${ACTION_HOOKS_FILE} 36 | + ) 37 | + endif() 38 | +endif() 39 | diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig 40 | index 3c443d04..067c569f 100644 41 | --- a/boot/zephyr/Kconfig 42 | +++ b/boot/zephyr/Kconfig 43 | @@ -607,6 +607,19 @@ config MCUBOOT_ACTION_HOOKS 44 | 'mcuboot_status_type_t' is listed in 45 | boot/bootutil/include/bootutil/mcuboot_status.h 46 | 47 | +config MCUBOOT_ACTION_HOOKS_FILE_PATH 48 | + string "File for MCUboot action hooks" 49 | + depends on MCUBOOT_ACTION_HOOKS 50 | + help 51 | + Must be a .c file. 52 | + You can use either absolute or relative path. 53 | + In case relative path is used, the build system assumes that it starts 54 | + from the directory where the MCUBoot KConfig configuration file is 55 | + located. If the key file is not there, the build system uses relative 56 | + path that starts from the MCUBoot repository root directory. 57 | + The .c file will be added to the MCUboot project source files. 58 | + The .c file should include 'bootutil/mcuboot_status.h'. 59 | + 60 | endmenu 61 | 62 | config MCUBOOT_DEVICE_SETTINGS 63 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BOOTLOADER_MCUBOOT=y 2 | CONFIG_MCUMGR=y 3 | CONFIG_MCUMGR_SMP_UART=y 4 | CONFIG_MCUMGR_CMD_IMG_MGMT=y 5 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | 9 | 10 | void main(void) 11 | { 12 | printk("Change this to see it change.\n"); 13 | } 14 | -------------------------------------------------------------------------------- /bootloader_samples/custom_image_hooks/src/mcuboot_action_hooks.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bootutil/mcuboot_status.h" 3 | 4 | LOG_MODULE_REGISTER(custom_mcuboot_action_hooks,4); 5 | 6 | 7 | void mcuboot_status_change(mcuboot_status_type_t status){ 8 | switch(status) 9 | { 10 | case MCUBOOT_STATUS_STARTUP: 11 | LOG_INF("MCUBOOT_STATUS_STARTUP\n"); 12 | break; 13 | 14 | case MCUBOOT_STATUS_UPGRADING: 15 | LOG_INF("MCUBOOT_STATUS_UPGRADING\n"); 16 | break; 17 | 18 | case MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND: 19 | LOG_INF("MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND\n"); 20 | break; 21 | 22 | case MCUBOOT_STATUS_NO_BOOTABLE_IMAGE_FOUND: 23 | LOG_INF("MCUBOOT_STATUS_NO_BOOTABLE_IMAGE_FOUND\n"); 24 | break; 25 | 26 | case MCUBOOT_STATUS_BOOT_FAILED: 27 | LOG_INF("MCUBOOT_STATUS_BOOT_FAILED\n"); 28 | break; 29 | 30 | case MCUBOOT_STATUS_USB_DFU_WAITING: 31 | LOG_INF("MCUBOOT_STATUS_USB_DFU_WAITING\n"); 32 | break; 33 | 34 | case MCUBOOT_STATUS_USB_DFU_ENTERED: 35 | LOG_INF("MCUBOOT_STATUS_USB_DFU_ENTERED\n"); 36 | break; 37 | 38 | case MCUBOOT_STATUS_USB_DFU_TIMED_OUT: 39 | LOG_INF("MCUBOOT_STATUS_USB_DFU_TIMED_OUT\n"); 40 | break; 41 | 42 | case MCUBOOT_STATUS_SERIAL_DFU_ENTERED: 43 | LOG_INF("MCUBOOT_STATUS_SERIAL_DFU_ENTERED\n"); 44 | break; 45 | default: 46 | LOG_WRN("Unexpected state\n"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/README.md: -------------------------------------------------------------------------------- 1 | # Keys and Signatures 2 | If you build a sample for MCUboot, for example my [Simple SMP Sample](../smp/mcuboot_smp), you might have seen the following warning in the build log: 3 | ``` 4 | --------------------------------------------------------- 5 | --- WARNING: Using default MCUBoot key, it should not --- 6 | --- be used for production. --- 7 | --------------------------------------------------------- 8 | ``` 9 | 10 | This folder has samples for fixing this, and for other key/signature related use-cases of bootloaders. 11 | 12 | ## Frequently Asked Questions 13 | Q. How do I add a custom key to MCUboot? 14 | A. See the [MCUBoot Custom Key with SMP Server sample](mcuboot_smp_custom_key). 15 | 16 | Q. Do I need to sign images manually using [imgtool.py](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/mcuboot/imgtool.html)? 17 | A. Most likely no. Building projects will automatically generate signed files for you in build/zephyr. See [Using MCUboot in nRF Connect SDK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/mcuboot/readme-ncs.html). 18 | 19 | 20 | # Theory 21 | Disclaimer: This is unofficial, and just my understanding on how things works. I can be wrong. 22 | MCUboot has some detailed documentation on how it is built, including security features at [MCUboot docs](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/mcuboot/wrapper.html). 23 | The nRF Connect SDK also has some information about bootloaders and security at [Secure Boot](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/security_chapter.html#secure-boot). 24 | Before reading further, I recommend having a look at the more basic theory under [Bootloader samples](../). 25 | 26 | ## Hash and verification 27 | You can calculate a hash of an image to verify that the image has not changed. 28 | For example google "sha256 tutorial" if you want to know more. 29 | 30 | ## Why Sign images? 31 | So that you know that **only you** can send firmware updates to your devices. 32 | 33 | ## How are images signed? 34 | Using Asymmetric Keys. 35 | If you do not know how asymmetric keys work, google it. 36 | You have two keys: A Private Key and a Public Key. 37 | The firmware image is signed with the Private Key. 38 | The bootloader has the Public Key. 39 | The bootloader can use the Public Key to verify that the firmware image is signed with the Private Key. 40 | Only you have the Private Key. Only you could have signed the firmware image. 41 | 42 | The signature is added to the [metadata](../smp#image-header-and-trailer) of the firmware update. 43 | 44 | ## How can I know that the image was not changed? 45 | The signature from the above explanation is generated from a hash of the firmware image. 46 | This is used to verify that the image has not changed since you signed it. 47 | 48 | ## MCUboot documentation 49 | MCUboot explains its signing operation in its [design docs](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/mcuboot/design.html). 50 | I recommend reading that if you want to know how it is really done. 51 | In this theory I mostly explain the concept in a simplified way. 52 | 53 | ## Signing visualized 54 | First a public key is generated: 55 | ![Generate a public key](../../.images/public_key.png) 56 | 57 | Then the new firmware is signed: 58 | ![Sign new firmware](../../.images/sign_image.png) 59 | 60 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | *.hex 3 | **/*.hex 4 | **/*.bin 5 | 6 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/README.md: -------------------------------------------------------------------------------- 1 | # MCUboot detached signature DFU 2 | 3 | This sample answers the question "How can I sign an image with MCUboot if I cannot access my private key directly?" 4 | 5 | See the scripts/ folder for how to sign with detached signatures. This script should be quite self-explanetory. Let me know if it is not. 6 | 7 | This sample uses UART for transport, so see [Simple SMP Sample over UART](../../smp/mcuboot_smp_uart) for how to do DFU with it. 8 | 9 | 10 | ## Explanation 11 | This sample has `scripts/detached_signature.sh` that shows what you can do on your PC, but then it also has `scripts/black_box` that uses openssl with generic cryptographic operations, showing how a black box can be used alongside imgtool to sign your MCUboot updates without having direct access to your private key. 12 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/keys_and_data/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/keys_and_data/keys/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MCUMGR=y 2 | CONFIG_MCUMGR_TRANSPORT_UART=y 3 | CONFIG_MCUMGR_GRP_IMG=y 4 | 5 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 6 | CONFIG_BASE64=y 7 | CONFIG_CRC=y 8 | 9 | # CONFIG_MCUMGR_GRP_IMG dependencies 10 | CONFIG_FLASH=y 11 | CONFIG_IMG_MANAGER=y 12 | 13 | # CONFIG_IMG_MANAGER dependencies 14 | CONFIG_STREAM_FLASH=y 15 | 16 | # CONFIG_MCUMGR dependencies 17 | CONFIG_NET_BUF=y 18 | CONFIG_ZCBOR=y 19 | 20 | # Required for CONFIG_IMG_MANAGER 21 | CONFIG_FLASH_MAP=y 22 | 23 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/scripts/black_box/.gitignore: -------------------------------------------------------------------------------- 1 | *.pem 2 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/scripts/black_box/README.md: -------------------------------------------------------------------------------- 1 | # Black box scripts 2 | 3 | In here I will put scripts that use generic openssl commands to work with keys. 4 | This is to simulate a "black box HSM" 5 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/scripts/black_box/init.sh: -------------------------------------------------------------------------------- 1 | KEYS_PATH="keys_and_data/keys" 2 | BLACK_BOX_PATH="scripts/black_box" 3 | 4 | openssl genpkey -algorithm RSA -out ${BLACK_BOX_PATH}/private_key.pem -pkeyopt rsa_keygen_bits:2048 5 | openssl rsa -pubout -in ${BLACK_BOX_PATH}/private_key.pem -out ${KEYS_PATH}/public_key.pem 6 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/scripts/black_box/sign_digest.sh: -------------------------------------------------------------------------------- 1 | KEYS_PATH="keys_and_data/keys" 2 | DATA_PATH="keys_and_data/data" 3 | BLACK_BOX_PATH="scripts/black_box" 4 | 5 | openssl dgst -sha256 -sign ${BLACK_BOX_PATH}/private_key.pem -out ${DATA_PATH}/signature.sig ${DATA_PATH}/digest.bin 6 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/scripts/black_box/sign_payload.sh: -------------------------------------------------------------------------------- 1 | KEYS_PATH="keys_and_data/keys" 2 | DATA_PATH="keys_and_data/data" 3 | BLACK_BOX_PATH="scripts/black_box" 4 | 5 | openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 -sign ${BLACK_BOX_PATH}/private_key.pem -out ${DATA_PATH}/signature.sig ${DATA_PATH}/payload.bin 6 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/scripts/detached_signature.sh: -------------------------------------------------------------------------------- 1 | ( 2 | 3 | if [ ! -d build ]; then 4 | cd .. # Temporarily go to the project folder 5 | if [ ! -d build ]; then 6 | echo "No build folder found. Remember to build first." 7 | exit 1 8 | fi 9 | fi 10 | 11 | alias imgtool="${HOME}/nrf_connect_sdk/bootloader/mcuboot/scripts/imgtool.py" 12 | 13 | KEYS_PATH="keys_and_data/keys" 14 | DATA_PATH="keys_and_data/data" 15 | 16 | PROJECT_NAME="$(basename "$PWD")" 17 | DEBUGGER_SNR=683304854 18 | 19 | APP_HEX="build/$PROJECT_NAME/zephyr/zephyr.hex" 20 | APP_BIN="build/$PROJECT_NAME/zephyr/zephyr.bin" 21 | MCUBOOT_HEX="build/mcuboot/zephyr/zephyr.hex" 22 | APP_SIGNED_HEX=$DATA_PATH/zephyr.signed.hex 23 | APP_SIGNED_BIN=$DATA_PATH/zephyr.signed.bin 24 | 25 | 26 | build_clean() { 27 | echo "------------build_clean--------------------" 28 | rm -r build/ 29 | west build -p -b nrf52840dk/nrf52840 30 | } 31 | 32 | flash_clean() { 33 | echo "------------flash_clean--------------------" 34 | nrfutil device erase 35 | nrfutil device recover 36 | nrfutil device program --serial-number $DEBUGGER_SNR --firmware $MCUBOOT_HEX 37 | nrfutil device program --serial-number $DEBUGGER_SNR --firmware $APP_SIGNED_HEX --options chip_erase_mode=ERASE_RANGES_TOUCHED_BY_FIRMWARE 38 | nrfutil device reset 39 | } 40 | 41 | BLACK_BOX_PATH="scripts/black_box" 42 | black_box_init() { 43 | echo "------------black_box_init--------------------" 44 | source ${BLACK_BOX_PATH}/init.sh # Will generate a public key inside the keys dir 45 | } 46 | 47 | black_box_sign_digest() { 48 | echo "------------black_box_sign_digest--------------------" 49 | source ${BLACK_BOX_PATH}/sign_digest.sh # Will generate a signature inside the data dir 50 | } 51 | 52 | black_box_sign_payload() { 53 | echo "------------black_box_sign_digest--------------------" 54 | source ${BLACK_BOX_PATH}/sign_payload.sh # Will generate a signature inside the data dir 55 | } 56 | 57 | write_public_key_to_build() { 58 | echo "------------write_public_key_to_build--------------------" 59 | imgtool getpub -k $KEYS_PATH/public_key.pem > $KEYS_PATH/pub.c # Convert .pem to .c for MCUboot 60 | cp $KEYS_PATH/pub.c build/mcuboot/zephyr/autogen-pubkey.c 61 | west build # Rebuild to compile in the new key 62 | } 63 | 64 | 65 | VERSION="1.0.0" 66 | HEADER_SIZE=0x200 67 | MCUBOOT_PRIMARY_SIZE=0x7a000 # From device partitioning. 68 | ALIGN=4 69 | 70 | DIGEST=${DATA_PATH}/digest.bin 71 | generate_app_digest() { 72 | echo "------------generate_app_digest--------------------" 73 | imgtool sign -v ${VERSION} -H ${HEADER_SIZE} -S ${MCUBOOT_PRIMARY_SIZE} --align ${ALIGN} --pad-header --vector-to-sign digest ${APP_HEX} ${DIGEST} 74 | } 75 | 76 | PAYLOAD=${DATA_PATH}/payload.bin 77 | generate_app_payload() { 78 | echo "------------generate_app_payload--------------------" 79 | imgtool sign -v ${VERSION} -H ${HEADER_SIZE} -S ${MCUBOOT_PRIMARY_SIZE} --align ${ALIGN} --pad-header --vector-to-sign payload ${APP_HEX} ${PAYLOAD} 80 | } 81 | 82 | sign_hex_with_signature() { 83 | echo "------------sign_hex_with_signature--------------------" 84 | openssl base64 -in ${DATA_PATH}/signature.sig -out ${DATA_PATH}/signature.b64 85 | imgtool sign -v ${VERSION} -H ${HEADER_SIZE} -S ${MCUBOOT_PRIMARY_SIZE} --align ${ALIGN} --pad-header --fix-sig-pubkey ${KEYS_PATH}/public_key.pem --fix-sig ${DATA_PATH}/signature.b64 ${APP_HEX} ${APP_SIGNED_HEX} 86 | } 87 | 88 | sign_bin_with_signature() { 89 | echo "------------sign_hex_with_signature--------------------" 90 | openssl base64 -in ${DATA_PATH}/signature.sig -out ${DATA_PATH}/signature.b64 91 | imgtool sign -v ${VERSION} -H ${HEADER_SIZE} -S ${MCUBOOT_PRIMARY_SIZE} --align ${ALIGN} --pad-header --fix-sig-pubkey ${KEYS_PATH}/public_key.pem --fix-sig ${DATA_PATH}/signature.b64 ${APP_BIN} ${APP_SIGNED_BIN} 92 | } 93 | 94 | 95 | # Debug functions below -------------------- 96 | 97 | cheat_sign_image(){ 98 | APP_SIGNED_HEX=$DATA_PATH/cheat.signed.hex 99 | APP_SIGNED_BIN=$DATA_PATH/cheat.signed.bin 100 | echo "------------manually_generate_signed_hex_for_programming--------------------" 101 | # Only for testing. If we do not have access to the private key, this method can not be used. 102 | # imgtool sign [options] INFILE OUTFILE 103 | imgtool sign -v ${VERSION} -H ${HEADER_SIZE} --pad-header -S ${MCUBOOT_PRIMARY_SIZE} --align ${ALIGN} -k ${BLACK_BOX_PATH}/private_key.pem ${APP_HEX} ${APP_SIGNED_HEX} 104 | imgtool sign -v ${VERSION} -H ${HEADER_SIZE} --pad-header -S ${MCUBOOT_PRIMARY_SIZE} --align ${ALIGN} -k ${BLACK_BOX_PATH}/private_key.pem ${APP_BIN} ${APP_SIGNED_BIN} 105 | } 106 | 107 | cheat_flash() { 108 | APP_SIGNED_HEX=$DATA_PATH/cheat.signed.hex 109 | APP_SIGNED_BIN=$DATA_PATH/cheat.signed.bin 110 | echo "------------flash_clean--------------------" 111 | nrfutil device erase 112 | nrfutil device recover 113 | nrfutil device program --serial-number $DEBUGGER_SNR --firmware $MCUBOOT_HEX 114 | nrfutil device program --serial-number $DEBUGGER_SNR --firmware $APP_SIGNED_HEX --options chip_erase_mode=ERASE_RANGES_TOUCHED_BY_FIRMWARE 115 | nrfutil device reset 116 | } 117 | 118 | dumpinfo(){ 119 | imgtool dumpinfo $DATA_PATH/zephyr.signed.bin > $DATA_PATH/zephyr.signed.dump 120 | imgtool dumpinfo $DATA_PATH/cheat.signed.bin > $DATA_PATH/cheat.signed.dump 121 | } 122 | 123 | # Runs script. Remember to comment out functions when not needed anymore 124 | black_box_init # Generate keys. Use only once 125 | write_public_key_to_build 126 | generate_app_payload 127 | black_box_sign_payload 128 | sign_hex_with_signature # Only use this on first flash 129 | flash_clean # Only use this on first flash. 130 | sign_bin_with_signature # Generate zephyr.signed.bin for DFU 131 | 132 | # Debugging functions below 133 | # cheat_sign_image 134 | # cheat_flash 135 | # dumpinfo 136 | 137 | ) 138 | 139 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | 9 | int main(void) 10 | { 11 | printk("Change this to see change\n"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/sysbuild.conf: -------------------------------------------------------------------------------- 1 | SB_CONFIG_BOOTLOADER_MCUBOOT=y 2 | SB_CONFIG_BOOT_SIGNATURE_TYPE_RSA=y 3 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_detached_signature/sysbuild/mcuboot.conf: -------------------------------------------------------------------------------- 1 | #STEP 3.1 - Enable Serial Recovery over UART 2 | # CONFIG_MCUBOOT_SERIAL=y 3 | # CONFIG_BOOT_SERIAL_UART=y 4 | # 5 | # # STEP 3.2 - Disable console UART, since Serial Recovery uses UART 6 | # CONFIG_UART_CONSOLE=n 7 | # 8 | # # STEP 3.3 - Turn on a LED so we can see when Serial Recovery mode is active 9 | # CONFIG_MCUBOOT_INDICATION_LED=y 10 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/.gitignore: -------------------------------------------------------------------------------- 1 | *.hex 2 | *.bin 3 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/README.md: -------------------------------------------------------------------------------- 1 | # MCUBoot sample using SMP Server and manually signed images 2 | Disclaimer: It is recommended to not do this manually, and instead use our build system and its automatically generated files. See [Using MCUBoot in nRF Connect SDK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/mcuboot/readme-ncs.html) 3 | 4 | ## Preparation of Developement Kits 5 | Disable the Mass Storage feature on the device, so that it does not interfere with mcumgr through the debugger: 6 | ``` 7 | JLinkExe -device NRF52840_XXAA -if SWD -speed 4000 -autoconnect 1 -SelectEmuBySN SEGGER_ID 8 | J-Link>MSDDisable 9 | Probe configured successfully. 10 | J-Link>exit 11 | ``` 12 | 13 | ## Manual signing 14 | First, generate private and public keys using imgtool: 15 | ``` 16 | mkdir keys 17 | cd keys 18 | $NRF_CONNECT_SDK/bootloader/mcuboot/scripts/imgtool.py keygen -k test_priv.pem -t rsa-2048 19 | $NRF_CONNECT_SDK/bootloader/mcuboot/scripts/imgtool.py getpub -k test_priv.pem > test_pub.c 20 | ``` 21 | 22 | Initially build the sample to generate a build folder. The private key in "child_image/mcuboot/tmp_priv.pem" is not important here. 23 | Copy the test_pub.c into mcuboot. This will make it use your key instead of the one generated from child_image/mcuboot/tmp_priv.pem: 24 | ``` 25 | cp keys/test_pub.c build/mcuboot/zephyr/autogen-pubkey.c 26 | ``` 27 | 28 | Then build and flash the applicaion using west. This build must not be pristine. 29 | The application you have flashed is signed by a private key not fitting the MCUBoot public key. The application will not start. 30 | Next we will sign and program your application. 31 | 32 | Now use imgtool to sign your application, both for hex file and for bin file. 33 | ``` 34 | $NRF_CONNECT_PATH/bootloader/mcuboot/scripts/imgtool.py sign --header-size 0x200 --align 4 --slot-size 0x79e00 --version 1.0.0 --pad-header --key keys/test_priv.pem build/zephyr/app_to_sign.bin app_manually_signed.bin 35 | $NRF_CONNECT_PATH/bootloader/mcuboot/scripts/imgtool.py sign --header-size 0x200 --align 4 --slot-size 0x79e00 --version 1.0.0 --pad-header --key keys/test_priv.pem build/zephyr/zephyr.hex app_manually_signed.hex 36 | ``` 37 | DISCLAIMER: You should make sure the arguments for this signing command are right for your application. See the [imgtool.py documentation](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/mcuboot/imgtool.html). 38 | You can see the command used to sign app_update.bin and other generated binaries by using "west -vvv build ...". 39 | 40 | First time, you need to use nrfjprog to program your application. You can not use mcumgr, as the application must run to have SMP Server active. 41 | An alternative could be to use serial recovery mode instead. 42 | Program the signed hex using nrfjprog: 43 | ``` 44 | nrfjprog --sectorerase --reset --program app_manually_signed.hex 45 | ``` 46 | 47 | ## Use mcumgr to program new image 48 | Program the new image using [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/zephyr/guides/device_mgmt/mcumgr.html): 49 | ``` 50 | mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" 51 | mcumgr -c acm0 image list 52 | mcumgr -c acm0 image upload build/zephyr/app_update.bin 53 | mcumgr -c acm0 image list 54 | ``` 55 | Then tell MCUBoot to boot from the new slot next reboot: 56 | ``` 57 | mcumgr -c acm0 image test 58 | ``` 59 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/auto_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | NRF_CONNECT_SDK=$HOME/ncs 3 | (cd keys 4 | $NRF_CONNECT_SDK/bootloader/mcuboot/scripts/imgtool.py getpub -k test_priv.pem > test_pub.c 5 | ) 6 | west build -p -b nrf52840dk_nrf52840 7 | cp keys/test_pub.c build/mcuboot/zephyr/autogen-pubkey.c 8 | 9 | $NRF_CONNECT_SDK/bootloader/mcuboot/scripts/imgtool.py sign --header-size 0x200 --align 4 --slot-size 0x79e00 --version 1.0.0 --pad-header --key keys/test_priv.pem build/zephyr/app_to_sign.bin app_manually_signed.bin 10 | $NRF_CONNECT_SDK/bootloader/mcuboot/scripts/imgtool.py sign --header-size 0x200 --align 4 --slot-size 0x79e00 --version 1.0.0 --pad-header --key keys/test_priv.pem build/zephyr/zephyr.hex app_manually_signed.hex 11 | 12 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/auto_flash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | west flash --erase 3 | nrfjprog --sectorerase --reset --program app_manually_signed.hex 4 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/child_image/mcuboot/custom_priv.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCz/qA2qeXmP5l 3 | FhK6dKr2nrD1MUyC520E+HotNG12P4hj90dG1vKYHqRB6aSLbPINQxmtxMEx4mxf 4 | OaV0R1St0cQmwM34/7d+EMazF08SiSdq1PYtn6rcsrq0r1BpAtqw4s+w9MrQ3YhD 5 | BkT/lOBdBEJYfIDo8/WbfrD8mbGrRsLTKugZu5bRaOznJUJPp68mjbcm2Lg33bu6 6 | c14IHI0Z1z/Dg4g4iepeCORRWqfpWsTFvCu2P0yelle6FbLPcDOKNT+lZu8z7OSd 7 | GFw5sfJwsHgCkeJu/zE5fhmWG2qSULnHg/Y2syjym4WRFOlrqNkKolavajqnNRnO 8 | jYGxZEO7AgMBAAECggEBALvHg1we53puA5DmpOjLOlv7/PBrM6fecSxgYkwehAB+ 9 | HvbUzQSQfkh5CLVsA6pNOkfkTOU9iUePTAzB4STi+NGPJ7Z/FEsWGgXPH+hS6Goi 10 | gDcuzZiOlkCjmuo9LpH6KVhlV/LnEnQfhY+thGajV1zxlQ37/LoPJchbZzgk4agI 11 | HzoVPxo/kyIaOa5G9a797b1zBmQ5bFPCRHMXPoVVI3Q4TqXXj/0hASxjiLYZXM7F 12 | LKnSPyi6sc2OWp71Y4VY1uceCOzfxDhBUUrgq6CP2+2r1TiQL/OZeEFq+ArqnPpC 13 | x3Ks+2xkOi81vqEORCBJCzlrYN7umbdZcMekp0/P1ikCgYEA6EfNTtda65nCkbVN 14 | H/6niiZ/J44ZYqXwzqmF1+4m2QRd+HP+X1uJxrdimIe69CftNo8fBgt1fkQiod4z 15 | 40TcZJuHy6a/ZNNPrZnVl3+Q7SwhceA6/nzuTPLG9Xh6vtvfPlum6YGxuvDR8He7 16 | m/UDVsRPWEQhX3Dz9Z66DS5msuUCgYEA1rSy+c/dFCuORONDi6ctqtHxzAbD5Sc0 17 | akt3omTBA4kc0kxg7U4X7iLfMEbWYwqi5IX5Y9pM4bxCHYIceP9S/Nnu31AvCg8n 18 | HWyspVkBRoG5UwZHPuaMDj6KZUjJvkHj+nYJnEXvsIsHiJTo5druz/aRlmLj1UiI 19 | 3KGx+khWkh8CgYBYzTKJhL2Guvbuu7BrnfCxWTxdg+7ijuw8JgU8YxjI+OlwFfBW 20 | xmkq5ms0QxfPRgBjTl4e8nyNtEDFP2z44xebAvbsfahIRJz+koRc8fEXKzryDTag 21 | mmSEWICF0fSjSO3VKjbqqKGpBW5Nj4jS+92160EmTo2vrkAmU/NvHKE4nQKBgQCc 22 | PL4IfzQ3W0KZ6m7ajvryVPgJKdsfQ5omx2f1KjAyLHJmreHSjYNobMPQ05tqUvEa 23 | Lku+V7qegWnzIx0pB1MSYFws8KJqRYCHLu+rGsuMzRVYzzbFFOtR6jy3W3JDGpuV 24 | RJPVviafZ2xB/WpE6T3i42Ap+SglqjS9qIRkxoMIrQKBgFTdzyK9M1i8Nw+1wCiY 25 | OsWq7Sj0mLnyPXUEOzW8nI/HUSLOFwc2Pyc2OlcH0UZd8PH4A5/ZbntOtOQ/I7OY 26 | a8RbVKjEOkE8//71xbER7LN1swPBwZ7sT6pVYq0AGDkDlR80Jeo5TVEtBjD3O6bC 27 | RTBvUR/Dm8g9LF3JQjkIe4Zp 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/child_image/mcuboot/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_FLASH=y 2 | 3 | CONFIG_BOOT_SIGNATURE_TYPE_RSA=y 4 | CONFIG_BOOT_SIGNATURE_KEY_FILE="custom_priv.pem" 5 | CONFIG_MAIN_STACK_SIZE=10240 6 | 7 | CONFIG_LOG=y 8 | CONFIG_LOG_MODE_MINIMAL=y 9 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/keys/test_priv.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDJAd/u96hWoTt 3 | 6Zs1DeKS7MFGU1Bj0DNsKuoOhukY8b2GdQZznOr90DnOr4rITX+1kdm/sqSYwDHP 4 | 4Hu36c/qBTd7/upVgjnW5uUsNtOP9TK4C34B/pvsTGCcf4Twp+5YbXNPsQDNJoHD 5 | hRRue1Qy8hHYFTX8Yo8flWxZTtTFLh3v7MXtnSOek1MqM3c0BltXxqijTVtdEidH 6 | i2wicdMzl1Vfbi4kTUmZQDM4RXeYAeXTGuD74k7dOSWhyQBAMCqQ55Tr10yztRjH 7 | aO6KAByKm30Boac+y65qp1QM0A8yAIut92Ug2CxlTdDjIYx8/YBVUbWwRCf3JQbw 8 | yUQ0gsb9AgMBAAECggEAHEAqj8JTNEPbtmpuoasoGpeI/D/n2v4Te7zovqqnCLPy 9 | pApsIS+zUNnPjKMa8e2k/VR8qYUuJr5oV7fK4XDJkg/S8ly7cHQBIKIJGodjcIC8 10 | firibAfVa0u8DtwNPck/YcY9U+kEUdmZyVm1AAZTGxRdeKLKz9uK7Ip1hvu5JO8h 11 | XAbVeIGn7w6FN4mUPLjDwcATd5iZuK8rkBCizy1ktAeN6xyFHUnGrL7Y01NdHF/w 12 | nuRkuLdwC0BGG44KdcGaCMfpH1tiC1ZPS5zwvE1U/hgMgO1N5EDZeOI04ZsAhd0P 13 | Ghmyjq5P9Teabajbuj0YlklbziDUeTszZxf8QguU1wKBgQDhqpK3uYzrQRTEnxdJ 14 | SWko1b1Li03wApunRHJNPJ6SCrir7Ez9nNaGjdWamZZ5cOB+f6GY99lq1w+Q53h5 15 | kdN5OXtBzDi+Od7/MthJKG4b07WEv10Jz5cgtKz3TJQi0MExC8JpA/edj0dhuMin 16 | a/t/GIM0O7PTLYsgXKv1GMZyHwKBgQDdXwmwnKRSMdWX1kz7dOaexJ1PBJ0n9nv6 17 | zhPpffiHXmLOqrSAEpJ6Ur88jq/ql/DHHvUiX317SL2hTlVYsiWZ7u/nl+Qh0XpB 18 | HrOdOwU0AlM+camXOhyh6yQa7dh90zeHu+4/WJZSi0wLLmntjLTsE+9c2acFL0ch 19 | SaykGJi7YwKBgBjMh+cMywGnW0LoQMTa/mVwZ6b/ngb8ImLVUMJQIRTnfLfX9fYA 20 | 4EpVF94vdqvNzb3ZBMcspYXqMFm6NjEV52lw+ayXZrzw2yKsUbxoZwFD2LTH2s+T 21 | MoZzlHZwwe65hiF/q1OjDfkQn8WLavGLGk4zQWfiD7brUFi0FmmO2W/9AoGBAKXk 22 | CobnW9ycq8vVNGtb91cTUC9e7cZ81/vjYtifJheLi9AD7K/tOwef6t+ergXHRxBx 23 | CpJvrMEuiazP3vVQywzIGdAb60HMkSkrsL4q9IM9GtS4qLZDPiG47J2hj5L7Lany 24 | E2A1KrFA4gOfDJKP1yTy63VRRfCEtXEknNN7+zixAoGAQufMzMi4ycauETxVul44 25 | 04wuGIPpVAIV820gyOwsVHrCEo/tfKA+/Tczlevnn8AQoReVpR7rAMxw1G6H/Yvl 26 | 0nHfA4ZYr+Y5bsQftLswfV5K1iTQ4SgtAUf79zQi7Lq+n6dCqMY2F+zy00gCG2nW 27 | zHBvCGE/rvB+AC+jZL12hQ4= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BOOTLOADER_MCUBOOT=y 2 | CONFIG_MCUMGR=y 3 | CONFIG_MCUMGR_TRANSPORT_UART=y 4 | CONFIG_MCUMGR_GRP_IMG=y 5 | 6 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 7 | CONFIG_BASE64=y 8 | 9 | # CONFIG_MCUMGR_GRP_IMG dependencies 10 | CONFIG_FLASH=y 11 | CONFIG_IMG_MANAGER=y 12 | 13 | # CONFIG_IMG_MANAGER dependencies 14 | CONFIG_STREAM_FLASH=y 15 | 16 | # CONFIG_MCUMGR dependencies 17 | CONFIG_NET_BUF=y 18 | CONFIG_ZCBOR=y 19 | 20 | # Required for CONFIG_IMG_MANAGER 21 | CONFIG_FLASH_MAP=y 22 | 23 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_manual_sign/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | 9 | void main(void) 10 | { 11 | printk("Change this to see it change\n"); 12 | } 13 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_custom_key/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | set(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/custom_key_dir/custom_priv.pem\") 6 | 7 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 8 | project(mcuboot_smp_custom_key) 9 | 10 | target_sources(app PRIVATE src/main.c) 11 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_custom_key/README.md: -------------------------------------------------------------------------------- 1 | # MCUBoot Custom Key with SMP Server 2 | 3 | See the [Simple SMP sample](../../smp/mcuboot_smp) for a guide on how to use the SMP Server. 4 | 5 | The `child_image/custom_priv.pem` key was generated using: 6 | ``` 7 | ${NCS_PATH}/bootloader/mcuboot/scripts/imgtool.py keygen -k custom_priv.pem -t ecdsa-p256 8 | ``` 9 | Also see the [Imgtool documentation](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/mcuboot/imgtool.html). 10 | 11 | ## Disclaimer 12 | This code/configuration is not thoroughly tested or qualified and should be considered provided “as-is”. Please test it with your application and let me know if you find any issues. 13 | 14 | 15 | ## Test that it fails 16 | After testing this once successfully, try to create a new key as described above. 17 | Then build the project with the new key(not flash). 18 | Perform DFU with the new app\_update.bin. 19 | Now the DFU should fail, since you have used the wrong key. 20 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_custom_key/child_image/mcuboot.conf: -------------------------------------------------------------------------------- 1 | # Force ECDSA-P256, since this is not nessecarily the default 2 | CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y 3 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_custom_key/custom_key_dir/custom_priv.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgdiJYhJlSj/e5KZuw 3 | 3u2fgv6z1fkBBr5fWTvQ4u2N0DKhRANCAASAyC69sKud5kULGkuNATqGyMIvffqu 4 | A1lHbcrS6A8y1q4mBubB5GEzk3XLgXiIDhqMrmojVeC8TTIBNqgezUq7 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_custom_key/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BOOTLOADER_MCUBOOT=y 2 | CONFIG_MCUMGR=y 3 | CONFIG_MCUMGR_TRANSPORT_UART=y 4 | CONFIG_MCUMGR_GRP_IMG=y 5 | 6 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 7 | CONFIG_BASE64=y 8 | 9 | # CONFIG_MCUMGR_GRP_IMG dependencies 10 | CONFIG_FLASH=y 11 | CONFIG_IMG_MANAGER=y 12 | 13 | # CONFIG_IMG_MANAGER dependencies 14 | CONFIG_STREAM_FLASH=y 15 | 16 | # CONFIG_MCUMGR dependencies 17 | CONFIG_NET_BUF=y 18 | CONFIG_ZCBOR=y 19 | 20 | # Required for CONFIG_IMG_MANAGER 21 | CONFIG_FLASH_MAP=y 22 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_custom_key/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | 9 | void main(void) 10 | { 11 | printk("Change this to see update.\n"); 12 | } 13 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_encryption/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | set(mcuboot_CONFIG_BOOT_ENCRYPTION_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/custom_key_dir/encryption_key.pem\") 6 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 7 | project(hello_world) 8 | 9 | target_sources(app PRIVATE src/main.c) 10 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_encryption/README.md: -------------------------------------------------------------------------------- 1 | # MCUboot with encryption 2 | The nRF Connect SDK does not have official support for encrypted DFU. 3 | However, upastream MCUboot have built-in support for this, so we can leverage this. 4 | Please read the disclaimer. 5 | 6 | ## Disclaimer 7 | This code/configuration is not thoroughly tested or qualified and should be considered provided “as-is”. Please test it with your application and let me know if you find any issues. 8 | This sample uses symmetric encryption. If someone breaks into a device and steals the key, they can decrypted firmware updates. 9 | Encryption does not replace signing of images, and this sample uses default mcuboot keys for signing. See [MCUBoot Custom Key with SMP Server](../mcuboot_smp_custom_key) for how a custom signing key can be added. 10 | 11 | ## Docs 12 | See [MCUboot: Encryped images](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/v2.4.0/mcuboot/encrypted_images.html) for an explanation on how MCUboot handles encryption. 13 | 14 | ## Patch the nRF repo 15 | The nRF Connect SDK generates [Build files](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/v2.4.0/nrf/config_and_build/config_and_build_system.html#output-build-files) so that developers have an easier time doing DFU. [nrf.patch](./nrf.patch) changes the nRF Connect SDK so that app\_update.bin is automatically encrypted (when encryption is enabled). 16 | To apply the patch, do this in a terminal or git bash: 17 | ``` 18 | cd /ncs/nrf 19 | git apply /nrf.patch 20 | ``` 21 | 22 | ## Key generation 23 | The `custom_key_dir/encryption_key.pem` key was generated using: 24 | ``` 25 | ${NCS_PATH}/bootloader/mcuboot/scripts/imgtool.py keygen -k custom_key_dir/encryption_key.pem -t ecdsa-p256 26 | ``` 27 | 28 | ## Run sample 29 | Due to the patch above, app\_update.bin is automatically encrypted. 30 | See steps in the [MCUBoot SMP simple sample](../../smp/mcuboot_smp_uart) for how to test this sample. 31 | To see imgtool command for encrypting images: 32 | ``` 33 | west -vvv build ... 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_encryption/child_image/mcuboot.conf: -------------------------------------------------------------------------------- 1 | # CONFIG_BOOT_SIGNATURE_KEY_FILE set in CMakeLists.txt to get relative path 2 | CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y 3 | CONFIG_BOOT_ECDSA_TINYCRYPT=y 4 | CONFIG_BOOT_ENCRYPT_IMAGE=y 5 | 6 | # Logging 7 | CONFIG_LOG=y 8 | CONFIG_LOG_DEFAULT_LEVEL=4 9 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_encryption/custom_key_dir/encryption_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoxQ6rqwIl8tSNf8Y 3 | HTE/vd+9Yn3RWWVr/gjcgM2bLTihRANCAAQn4pNJ9UIaxZCAvSC/IhrnTeVPn/8A 4 | 23c+ThAEr6X75pcNupa6cLA6bbUJo16t5vAe5aD7aOevEIHsybleNTYO 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_encryption/nrf.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/multi_image.cmake b/cmake/multi_image.cmake 2 | index 13b4d5d00..9b89b342d 100644 3 | --- a/cmake/multi_image.cmake 4 | +++ b/cmake/multi_image.cmake 5 | @@ -20,6 +20,13 @@ if(IMAGE_NAME) 6 | set_shared(IMAGE ${IMAGE_NAME} PROPERTY SIGNATURE_KEY_FILE ${CONFIG_BOOT_SIGNATURE_KEY_FILE}) 7 | endif() 8 | 9 | + # Share the encryption key file so that the parent image can use it to 10 | + # generate encrypted update candidates. 11 | + if(CONFIG_BOOT_ENCRYPTION_KEY_FILE) 12 | + set_shared(IMAGE ${IMAGE_NAME} PROPERTY ENCRYPTION_KEY_FILE ${CONFIG_BOOT_ENCRYPTION_KEY_FILE}) 13 | + endif() 14 | + 15 | + 16 | generate_shared(IMAGE ${IMAGE_NAME} FILE ${CMAKE_BINARY_DIR}/shared_vars.cmake) 17 | else() 18 | # Store a preload file with whatever configurations are required to create 19 | diff --git a/modules/mcuboot/CMakeLists.txt b/modules/mcuboot/CMakeLists.txt 20 | index 2b5c42168..228277a4a 100644 21 | --- a/modules/mcuboot/CMakeLists.txt 22 | +++ b/modules/mcuboot/CMakeLists.txt 23 | @@ -116,6 +116,10 @@ if(CONFIG_BOOTLOADER_MCUBOOT) 24 | set(sign_dependencies "-d;\"${SIGN_ARG_IMAGE_DEPENDENCIES}\"") 25 | endif() 26 | 27 | + if (DEFINED mcuboot_enc_key) 28 | + set(encryption_command --encrypt ${mcuboot_enc_key}) 29 | + endif() 30 | + 31 | add_custom_command( 32 | OUTPUT 33 | ${signed_hex} # Signed hex of input hex. 34 | @@ -131,6 +135,8 @@ if(CONFIG_BOOTLOADER_MCUBOOT) 35 | # to be applied by mcuboot, the application is required to write the 36 | # IMAGE_MAGIC into the image trailer. 37 | ${sign_cmd} 38 | + ${encryption_command} 39 | + --clear 40 | ${sign_dependencies} 41 | ${SIGN_ARG_ROM_FIXED} 42 | --slot-size ${SIGN_ARG_SLOT_SIZE} 43 | @@ -159,6 +159,7 @@ if(CONFIG_BOOTLOADER_MCUBOOT) 44 | COMMAND 45 | # Sign the binary version of the input hex file. 46 | ${sign_cmd} 47 | + ${encryption_command} 48 | ${sign_dependencies} 49 | ${SIGN_ARG_ROM_FIXED} 50 | --slot-size ${SIGN_ARG_SLOT_SIZE} 51 | @@ -280,6 +285,28 @@ if(CONFIG_BOOTLOADER_MCUBOOT) 52 | endif() 53 | endif() 54 | 55 | + if (NOT DEFINED ${CONFIG_BOOT_ENCRYPTION_KEY_FILE}) 56 | + get_shared(mcuboot_enc_key IMAGE mcuboot PROPERTY ENCRYPTION_KEY_FILE) 57 | + set(CONFIG_BOOT_ENCRYPTION_KEY_FILE ${mcuboot_enc_key}) 58 | +endif () 59 | + 60 | +foreach (filepath ${mcuboot_CONF_FILE}) 61 | + file(STRINGS ${filepath} mcuboot_CONFIG_BOOT_ENCRYPTION_KEY_FILE 62 | + REGEX "^CONFIG_BOOT_ENCRYPTION_KEY_FILE=") 63 | + if (mcuboot_CONFIG_BOOT_ENCRYPTION_KEY_FILE) 64 | + get_filename_component(mcuboot_CONF_DIR ${filepath} DIRECTORY) 65 | + endif() 66 | +endforeach() 67 | + 68 | +if(IS_ABSOLUTE ${CONFIG_BOOT_ENCRYPTION_KEY_FILE}) 69 | + set(mcuboot_enc_key ${CONFIG_BOOT_ENCRYPTION_KEY_FILE}) 70 | +elseif (DEFINED mcuboot_CONF_DIR) 71 | + if (EXISTS ${mcuboot_CONF_DIR}/${CONFIG_BOOT_ENCRYPTION_KEY_FILE}) 72 | + set(mcuboot_enc_key ${mcuboot_CONF_DIR}/${CONFIG_BOOT_ENCRYPTION_KEY_FILE}) 73 | + endif() 74 | +endif() 75 | + 76 | + 77 | if(CONFIG_SIGN_IMAGES) 78 | # Set default key 79 | if (NOT DEFINED mcuboot_key_file) 80 | @@ -293,6 +320,8 @@ if(CONFIG_BOOTLOADER_MCUBOOT) 81 | set(mcuboot_key_file ${ZEPHYR_MCUBOOT_MODULE_DIR}/${CONFIG_BOOT_SIGNATURE_KEY_FILE}) 82 | endif() 83 | 84 | + 85 | + 86 | set(app_core_binary_name app_update.bin) 87 | 88 | execute_process(COMMAND 89 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_encryption/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BOOTLOADER_MCUBOOT=y 2 | CONFIG_MCUMGR=y 3 | CONFIG_MCUMGR_TRANSPORT_UART=y 4 | CONFIG_MCUMGR_GRP_IMG=y 5 | 6 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 7 | CONFIG_BASE64=y 8 | 9 | # CONFIG_MCUMGR_GRP_IMG dependencies 10 | CONFIG_FLASH=y 11 | CONFIG_IMG_MANAGER=y 12 | 13 | # CONFIG_IMG_MANAGER dependencies 14 | CONFIG_STREAM_FLASH=y 15 | 16 | # CONFIG_MCUMGR dependencies 17 | CONFIG_NET_BUF=y 18 | CONFIG_ZCBOR=y 19 | 20 | # Required for CONFIG_IMG_MANAGER 21 | CONFIG_FLASH_MAP=y 22 | -------------------------------------------------------------------------------- /bootloader_samples/keys_and_signatures/mcuboot_smp_encryption/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | 9 | int main(void) 10 | { 11 | printk("Change this to see it change.\n"); 12 | return 1; 13 | } 14 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/README.md: -------------------------------------------------------------------------------- 1 | # nRF5340 samples 2 | 3 | # Theory 4 | Disclaimer: This is unofficial, and just my understanding on how things works. I can be wrong. 5 | 6 | ## Do I need to actually know the inner workings of the nRF5340 to do Firmware Update on it? 7 | No, not really. 8 | But it will help if you need to start debugging. 9 | 10 | ## Why is DFU more complicated for the nRF5340? 11 | Because it has two cores, and both cores should be upatable. 12 | 13 | ![nRF5340](../../.images/nrf5340_bootloaders.png) 14 | 15 | As you can see from this image, be net core flash and the app core flash are separated. 16 | Therefore, you can not just swap an image from the Secondary Slot to the net core flash. 17 | As you might guess from the figure, the solution to this is to use the shared SRAM. I will explain how later on. 18 | 19 | ## Two bootloaders 20 | The nRF5340 has two bootloaders. 21 | Usually MCUboot for for the app core. 22 | [b0n](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/samples/nrf5340/netboot/README.html) for the net core. 23 | 24 | ## Non-simultaneous update 25 | You can update the cores one at a time. 26 | This is good because it requires less flash than the alternative. 27 | However, if you update the interface between the net and app cores, you must update them at the same time. 28 | If not, you will not be able to update the second core after the first one has been updated. 29 | 30 | From [Output Build Files](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/app_build_system.html#output-build-files), you can use build/zephyr/app\_update.bin to update the application core, and build/zephyr/net\_core\_app\_update.bin to update the network core. 31 | Updating the application core will work as normal. 32 | When updating the network core, the new image will be saved to the secondary slot. On a reboot, the image will be swapped with the network core over the shared SRAM: 33 | 34 | ![nonsimultaneous nRF5340 update](../../.images/net_core_update.png) 35 | 36 | 37 | ## Simultaneous update 38 | Simultaneous update will update both cores at the same time. 39 | This requires an extra slot, for the new net core image. 40 | Then new images for each slot are updated to two different secondary slot. 41 | Lastly, the bootloaders will swap secondary with primary slots for both cores at the next reboot: 42 | 43 | ![simultaneous nRF5340 update](../../.images/both_core_update.png) 44 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/mcuboot_smp_ble_nonsimultaneous/README.md: -------------------------------------------------------------------------------- 1 | # Non-Simultaneous update of both the Application-core and the Network-core 2 | 3 | ## nRF5340DK Specific 4 | The nRF5340DK have two COM-ports. 5 | Make sure to specify the COM-port for the Application core for updates. 6 | 7 | ## DFU over UART 8 | See [The Simple SMP sample](../../smp/mcuboot_smp_uart). 9 | This sample can be used to update both cores in order. 10 | To change the upload for the network core, use 11 | ``` 12 | mcumgr -c acm1 image upload build/zephyr/net_core_app_update.bin 13 | ``` 14 | 15 | ## DFU over Bluetooth Low Energy 16 | See [MCUboot SMP Sample feat Bluetooth Low Energy sample](../../smp/mcuboot_smp_ble). 17 | As above, use app\_update.bin for the application core, and net\_core\_app\_update.bin for the network core. 18 | 19 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/mcuboot_smp_ble_simultaneous/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | 9 | target_sources(app PRIVATE src/main.c ) 10 | zephyr_library_include_directories(src) 11 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/mcuboot_smp_ble_simultaneous/README.md: -------------------------------------------------------------------------------- 1 | # Simultaneous DFU for app and net core of nRF5340 2 | Code to make this work comes from the official [Zigbee Light Switch Sample](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/samples/zigbee/light_switch/README.html). 3 | This sample will upload updates to both the network and application cores of the nRF5340 at the same time. 4 | Then it will update both on a reboot. 5 | 6 | ## Build and Flash 7 | 8 | ``` 9 | west build -b nrf5340dk_nrf5340_cpuapp 10 | west flash --recover 11 | ``` 12 | 13 | ## Test sample 14 | Change the print in src/main.c to see change. 15 | Rebuild: 16 | ``` 17 | west build 18 | ``` 19 | 20 | ## DFU over Bluetooth Low Energy 21 | Install the [nRF Connect for Mobile app](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-mobile) on a mobile phone. 22 | 23 | Move build/zephyr/[dfu\_application.zip](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/app_build_system.html#output-build-files) to your mobile phone. 24 | 25 | Use the nRF Connect to connect to the DK: 26 | 27 | ![App Connect](../../../.images/nrf_connect_app_connect.png) 28 | 29 | Click the DFU button: 30 | 31 | ![App DFU](../../../.images/nrf_connect_app_dfu.png) 32 | 33 | Then select dfu\_application.zip upload it using "Confirm Only". 34 | 35 | Lastly, reset the Developement Kit. Both cores will now be updated. 36 | ``` 37 | nrfjprog --reset 38 | ``` 39 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/mcuboot_smp_ble_simultaneous/app.overlay: -------------------------------------------------------------------------------- 1 | / { 2 | chosen { 3 | nordic,pm-ext-flash = &mx25r64; 4 | }; 5 | }; 6 | 7 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/mcuboot_smp_ble_simultaneous/child_image/mcuboot.conf: -------------------------------------------------------------------------------- 1 | # Enable flash simulator 2 | CONFIG_FLASH=y 3 | CONFIG_FPROTECT=y 4 | CONFIG_PCD_APP=y 5 | CONFIG_FLASH_SIMULATOR=y 6 | CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y 7 | CONFIG_FLASH_SIMULATOR_STATS=n 8 | CONFIG_NORDIC_QSPI_NOR=y 9 | CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 10 | CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 11 | 12 | CONFIG_MAIN_STACK_SIZE=10240 13 | CONFIG_BOOT_MAX_IMG_SECTORS=256 14 | 15 | 16 | CONFIG_NRF53_MULTI_IMAGE_UPDATE=y 17 | CONFIG_UPDATEABLE_IMAGE_NUMBER=2 18 | 19 | CONFIG_BOOT_UPGRADE_ONLY=y 20 | CONFIG_BOOT_IMAGE_ACCESS_HOOK_NRF5340=y 21 | CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y 22 | 23 | CONFIG_LOG=y 24 | CONFIG_LOG_DEFAULT_LEVEL=4 25 | 26 | CONFIG_FLASH=y 27 | CONFIG_FPROTECT=y 28 | CONFIG_PM=n 29 | 30 | CONFIG_BOOT_SIGNATURE_TYPE_RSA=y 31 | CONFIG_BOOT_SWAP_SAVE_ENCTLV=n 32 | 33 | CONFIG_BOOT_BOOTSTRAP=n 34 | 35 | CONFIG_ASSERT=n 36 | CONFIG_BOOT_BANNER=n 37 | CONFIG_CONSOLE=y 38 | CONFIG_CONSOLE_HANDLER=n 39 | CONFIG_GPIO=n 40 | CONFIG_I2C=n 41 | CONFIG_SPI=n 42 | CONFIG_KERNEL_MEM_POOL=n 43 | CONFIG_MINIMAL_LIBC_CALLOC=n 44 | CONFIG_MINIMAL_LIBC_MALLOC=n 45 | CONFIG_MINIMAL_LIBC_REALLOCARRAY=n 46 | CONFIG_NCS_SAMPLES_DEFAULTS=y 47 | CONFIG_NO_RUNTIME_CHECKS=y 48 | CONFIG_NRF_RTC_TIMER=y 49 | CONFIG_PRINTK=y 50 | CONFIG_REBOOT=y 51 | CONFIG_RESET_ON_FATAL_ERROR=y 52 | CONFIG_SECURE_BOOT_DEBUG=n 53 | CONFIG_SERIAL=y 54 | CONFIG_SIZE_OPTIMIZATIONS=y 55 | CONFIG_UART_CONSOLE=y 56 | 57 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/mcuboot_smp_ble_simultaneous/child_image/mcuboot.overlay: -------------------------------------------------------------------------------- 1 | / { 2 | chosen { 3 | nordic,pm-ext-flash = &mx25r64; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/mcuboot_smp_ble_simultaneous/prj.conf: -------------------------------------------------------------------------------- 1 | # Enable Bootloader 2 | CONFIG_BOOTLOADER_MCUBOOT=y 3 | 4 | # Enable SMP Server 5 | CONFIG_MCUMGR=y 6 | CONFIG_MCUMGR_GRP_IMG=y 7 | 8 | # CONFIG_MCUMGR_GRP_IMG dependencies 9 | CONFIG_FLASH=y 10 | CONFIG_IMG_MANAGER=y 11 | 12 | # CONFIG_IMG_MANAGER dependencies 13 | CONFIG_STREAM_FLASH=y 14 | 15 | # CONFIG_MCUMGR dependencies 16 | CONFIG_NET_BUF=y 17 | CONFIG_ZCBOR=y 18 | 19 | # Required for CONFIG_IMG_MANAGER 20 | CONFIG_FLASH_MAP=y 21 | 22 | # Enable BLE transfer 23 | CONFIG_BT=y 24 | CONFIG_BT_PERIPHERAL=y 25 | CONFIG_BT_DEVICE_NAME="Test SMP Server" 26 | CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y 27 | 28 | CONFIG_MCUBOOT_USE_ALL_AVAILABLE_RAM=y 29 | CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y 30 | CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP=y 31 | CONFIG_NRF53_UPGRADE_NETWORK_CORE=y 32 | CONFIG_UPDATEABLE_IMAGE_NUMBER=2 33 | CONFIG_ADD_MCUBOOT_MEDIATE_SIM_FLASH_DTS=y 34 | 35 | 36 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 37 | -------------------------------------------------------------------------------- /bootloader_samples/nrf5340/mcuboot_smp_ble_simultaneous/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define DEVICE_NAME CONFIG_BT_DEVICE_NAME 16 | #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) 17 | 18 | static const struct bt_data ad[] = { 19 | BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), 20 | BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), 21 | }; 22 | 23 | void main(void) 24 | { 25 | int err = 0; 26 | printk("Change this to see it change.\n"); 27 | 28 | err = bt_enable(NULL); 29 | if (err) { 30 | printk("Bluetooth init failed (err %d)\n", err); 31 | return; 32 | } 33 | 34 | printk("Bluetooth initialized\n"); 35 | 36 | err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), 37 | NULL, 0); 38 | if (err) { 39 | printk("Advertising failed to start (err %d)\n", err); 40 | return; 41 | } 42 | 43 | printk("Advertising successfully started\n"); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/README.md: -------------------------------------------------------------------------------- 1 | # Serial Recovery Samples 2 | Serial Recovery is when the bootloader will open for DFU at boot. 3 | This mode is usually activated if a pin is held high at boot, but the mode can also be activated for some time at each boot. 4 | This git have samples for serial recovery over both UART and USB(cdc_acm). 5 | 6 | # Theory 7 | Disclaimer: This is unofficial, and just my understanding on how things works. I can be wrong. 8 | Before reading this, I recommend having a look at the more basic theory under [Bootloader samples](../) and the DFU theoru under [SMP samples](../smp). 9 | 10 | ## Serial Recovery 11 | Previously I explained how the SMP Server can run in the Application. 12 | The other alternative is to have a SMP Server running in the bootloader. 13 | 14 | ![SMP Server in App vs Serial Recvoery](../../.images/smp_vs_serial_recovery.png) 15 | 16 | Generally, we want the bootloader to do as little as possible. Therefore the SMP Server running with Serial Recovery will have very limited functionality. 17 | However, this will still increase the flash requirements of the bootloader. 18 | 19 | ## Serial 20 | As in the name, Serial Recovery is usually done over a physical connection. 21 | Here I have examples to do it either over the UART connection on a Developement Kit or over the "nRF USB" connection. 22 | 23 | ## One slot 24 | The SMP Server in the application had two reasons for having two slots: 25 | 1. The application can not overwrite itself. 26 | 2. Enable reverting in case the application breaks on update. 27 | 28 | Both these are no longer relevant for Serial Recovery: 29 | 1. The bootloader is writing now, not the application. 30 | 2. Since the bootloader will not be updated, you can just enter Serial Recovery again if the application breaks. 31 | 32 | ![Serial Recovery flash](../../.images/serial_recovery.png) 33 | 34 | ## Enter Serial Recovery Mode 35 | Usually the bootloader use as little time as possible to boot the application. 36 | If we want to do DFU, we need some time. Here are two ways to make sure that we got enough time for DFU. 37 | 38 | ### Serial Recovery on Button 39 | The chip will enter Serial Recovery mode instead of the application if a button is held during boot. 40 | Explaied by psuedo code: 41 | ``` 42 | function bootloader(): 43 | if( get_button_pressed() ): 44 | serial_recovery_mode() 45 | else: 46 | application() 47 | ``` 48 | 49 | ### Serial Recovery on Wait 50 | On boot, the bootloader will "listen" for X seconds for SMP commands. 51 | If any SMP command is received, the bootloader will enter Serial Recovery mode instead of the application. 52 | Explaied by psuedo code: 53 | ``` 54 | TIMEOUT = 5 55 | function bootloader(): 56 | INPUT_FOUND = read_serial_for_smp_command(TIMEOUT) 57 | if( INPUT_FOUND ): 58 | serial_recovery_mode() 59 | else: 60 | application() 61 | ``` 62 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_netcore_serial_recovery/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_netcore_serial_recovery/README.md: -------------------------------------------------------------------------------- 1 | # MCUboot netcore serial recovery 2 | See [Serial Recovery feat UART sample](../mcuboot_serial_recovery_uart) sample, but use `build/zephyr/net_core_app_update.bin` instead. 3 | 4 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_netcore_serial_recovery/boards/nrf5340dk_nrf5340_cpuapp.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_netcore_serial_recovery/boards/nrf5340dk_nrf5340_cpuapp_ns.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_netcore_serial_recovery/child_image/mcuboot.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | CONFIG_MAIN_STACK_SIZE=10240 8 | # Flash 9 | CONFIG_FLASH=y 10 | 11 | # MCUBoot serial 12 | CONFIG_MCUBOOT_SERIAL=y 13 | CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y 14 | 15 | # Decrease memory footprint 16 | CONFIG_CBPRINTF_NANO=y 17 | CONFIG_TIMESLICING=n 18 | CONFIG_BOOT_BANNER=n 19 | CONFIG_CONSOLE=n 20 | CONFIG_CONSOLE_HANDLER=n 21 | CONFIG_UART_CONSOLE=n 22 | CONFIG_RTT_CONSOLE=n 23 | CONFIG_USE_SEGGER_RTT=n 24 | CONFIG_LOG=n 25 | CONFIG_RESET_ON_FATAL_ERROR=n 26 | 27 | # The following configurations are required to support serial recovery of the 28 | # network image 29 | CONFIG_PCD_APP=y 30 | 31 | CONFIG_FLASH_SIMULATOR=y 32 | CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y 33 | CONFIG_FLASH_SIMULATOR_STATS=n 34 | 35 | CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y 36 | CONFIG_NRF53_RECOVERY_NETWORK_CORE=y 37 | 38 | CONFIG_MCUBOOT_INDICATION_LED=y 39 | 40 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_netcore_serial_recovery/prj.conf: -------------------------------------------------------------------------------- 1 | # CONFIG_BOOTLOADER_MCUBOOT=y 2 | # CONFIG_MCUMGR=y 3 | # CONFIG_MCUMGR_SMP_UART=y 4 | # CONFIG_MCUMGR_CMD_IMG_MGMT=y 5 | CONFIG_BT=y 6 | 7 | CONFIG_MCUBOOT_IMAGE_VERSION="1.0.0+0" 8 | CONFIG_BOOTLOADER_MCUBOOT=y 9 | CONFIG_NRF53_UPGRADE_NETWORK_CORE=y 10 | CONFIG_ADD_MCUBOOT_MEDIATE_SIM_FLASH_DTS=y 11 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_netcore_serial_recovery/src/main.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012-2014 Wind River Systems, Inc. 2 | * 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | #include 7 | 8 | void main(void) 9 | { 10 | printk("Change this to see it change.\n"); 11 | } 12 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | #SET(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE "\"${CMAKE_SOURCE_DIR}/custom_priv.pem\"") 6 | 7 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 8 | project(mcuboot_serial_recivery_uart) 9 | 10 | target_sources(app PRIVATE src/main.c) 11 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm/README.md: -------------------------------------------------------------------------------- 1 | # MCUBoot Serial Recovery Sample over USB CDC 2 | 3 | ## DevAcademy 4 | I recommend following [Nordic DevAcademy on Bootloaders/DFU](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-9-bootloaders-and-dfu-fota/) instead of this sample. 5 | 6 | ## Prepare the Developement Kit 7 | Disable the Mass Storage feature on the device, so that it does not interfere: 8 | ``` 9 | JLinkExe -device NRF52840_XXAA -if SWD -speed 4000 -autoconnect 1 -SelectEmuBySN SEGGER_ID 10 | J-Link>MSDDisable 11 | Probe configured successfully. 12 | J-Link>exit 13 | ``` 14 | 15 | ## Run the sample 16 | Build and flash the program using west: 17 | ``` 18 | west build -b nrf52840dk_nrf52840 19 | west flash 20 | ``` 21 | 22 | ## Serial Recovery 23 | To activate the Serial Recovery Mode, hold Button 1 while restarting the Developement Kit. 24 | Now, you should be able communicate with the bootloader using [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/zephyr/guides/device_mgmt/mcumgr.html): 25 | ``` 26 | mcumgr conn add acm1 type="serial" connstring="dev=/dev/ttyACM1,baud=115200,mtu=512" 27 | mcumgr -c acm1 image list 28 | ``` 29 | The list command should print: 30 | ``` 31 | Images: 32 | image=0 slot=0 33 | version: 0.0.0.0 34 | bootable: false 35 | flags: 36 | hash: Unavailable 37 | Split status: N/A (0) 38 | ``` 39 | 40 | Change something in the sample to see a difference. Build the sample again and upload the image using mcumgr: 41 | ``` 42 | west build 43 | mcumgr -c acm1 image upload build/zephyr/app_update.bin 44 | mcumgr -c acm1 reset 45 | ``` 46 | 47 | After the reset, your new code should run on the nRF52. 48 | 49 | ## Over CDC_ACM 50 | The serial communication for mcumgr goes through CDC_ACM, so you need to connect an USB to the nRF_USB port. 51 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm/prj.conf: -------------------------------------------------------------------------------- 1 | # Nothing here 2 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | printk("Change this to see it change.\n"); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm/sysbuild.conf: -------------------------------------------------------------------------------- 1 | SB_CONFIG_BOOTLOADER_MCUBOOT=y 2 | 3 | SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y 4 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm/sysbuild/mcuboot.conf: -------------------------------------------------------------------------------- 1 | CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x10000 2 | 3 | # Enable MCUboot Serial Recovery 4 | CONFIG_MCUBOOT_SERIAL=y 5 | CONFIG_BOOT_SERIAL_UART=y 6 | CONFIG_UART_CONSOLE=n 7 | 8 | # Point Serial Recovery to CDC_ACM 9 | CONFIG_BOOT_SERIAL_CDC_ACM=y 10 | 11 | CONFIG_MCUBOOT_INDICATION_LED=y 12 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm/sysbuild/mcuboot.overlay: -------------------------------------------------------------------------------- 1 | &zephyr_udc0 { 2 | cdc_acm_uart0: cdc_acm_uart0 { 3 | compatible = "zephyr,cdc-acm-uart"; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm_wait/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | #SET(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE "\"${CMAKE_SOURCE_DIR}/custom_priv.pem\"") 6 | 7 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 8 | project(mcuboot_serial_recivery_uart) 9 | 10 | target_sources(app PRIVATE src/main.c) 11 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm_wait/README.md: -------------------------------------------------------------------------------- 1 | # MCUBoot Serial Recovery Sample over USB CDC with Wait For DFU 2 | 3 | ## DevAcademy 4 | I recommend following [Nordic DevAcademy on Bootloaders/DFU](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-9-bootloaders-and-dfu-fota/) instead of this sample. 5 | 6 | ## Prepare the Developement Kit 7 | Disable the Mass Storage feature on the device, so that it does not interfere: 8 | ``` 9 | JLinkExe -device NRF52840_XXAA -if SWD -speed 4000 -autoconnect 1 -SelectEmuBySN SEGGER_ID 10 | J-Link>MSDDisable 11 | Probe configured successfully. 12 | J-Link>exit 13 | ``` 14 | 15 | ## Run the sample 16 | Build and flash the program using west: 17 | ``` 18 | west build -b nrf52840dk_nrf52840 19 | west flash 20 | ``` 21 | 22 | ## Serial Recovery 23 | Serial Recovery Mode should be activated for 5 seconds(can be configured) before the application starts. If any mcumgr commands are run before these 5 seconds have passed, the device will enter Serial Recovery Mode. 24 | Now, you should be able communicate with the bootloader using [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.2/zephyr/guides/device_mgmt/mcumgr.html): 25 | ``` 26 | mcumgr conn add acm1 type="serial" connstring="dev=/dev/ttyACM1,baud=115200,mtu=512" 27 | mcumgr -c acm1 image list 28 | ``` 29 | The list command should print: 30 | ``` 31 | Images: 32 | image=0 slot=0 33 | version: 0.0.0.0 34 | bootable: false 35 | flags: 36 | hash: Unavailable 37 | Split status: N/A (0) 38 | ``` 39 | 40 | Change something in the sample to see a difference. Build the sample again and upload the image using mcumgr: 41 | ``` 42 | west build 43 | mcumgr -c acm1 image upload build/zephyr/app_update.bin 44 | mcumgr -c acm1 reset 45 | ``` 46 | 47 | After the reset, your new code should run on the nRF52. 48 | 49 | ## Over CDC_ACM 50 | The serial communication for mcumgr goes through CDC_ACM, so you need to connect an USB to the nRF_USB port. 51 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm_wait/prj.conf: -------------------------------------------------------------------------------- 1 | # Nothing here 2 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm_wait/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | printk("Change this to see it change.\n"); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm_wait/sysbuild.conf: -------------------------------------------------------------------------------- 1 | SB_CONFIG_BOOTLOADER_MCUBOOT=y 2 | 3 | SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y 4 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm_wait/sysbuild/mcuboot.conf: -------------------------------------------------------------------------------- 1 | CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x10000 2 | 3 | # Enable MCUboot Serial Recovery 4 | CONFIG_MCUBOOT_SERIAL=y 5 | CONFIG_BOOT_SERIAL_UART=y 6 | CONFIG_UART_CONSOLE=n 7 | 8 | # Point Serial Recovery to CDC_ACM 9 | CONFIG_BOOT_SERIAL_CDC_ACM=y 10 | 11 | CONFIG_MCUBOOT_INDICATION_LED=y 12 | 13 | # Enable wait for DFU functionality 14 | CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=y 15 | CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT=5000 16 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_cdc_acm_wait/sysbuild/mcuboot.overlay: -------------------------------------------------------------------------------- 1 | &zephyr_udc0 { 2 | cdc_acm_uart0: cdc_acm_uart0 { 3 | compatible = "zephyr,cdc-acm-uart"; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_uart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | #SET(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE "\"${CMAKE_SOURCE_DIR}/custom_priv.pem\"") 6 | 7 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 8 | project(mcuboot_serial_recivery_uart) 9 | 10 | target_sources(app PRIVATE src/main.c) 11 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_uart/README.md: -------------------------------------------------------------------------------- 1 | # MCUBoot Serial Recovery over UART Sample 2 | 3 | ## DevAcademy 4 | I recommend following [Nordic DevAcademy on Bootloaders/DFU](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-9-bootloaders-and-dfu-fota/) instead of this sample. 5 | 6 | ## Prepare the Developement Kit 7 | Disable the Mass Storage feature on the device, so that it does not interfere: 8 | ``` 9 | JLinkExe -device NRF52840_XXAA -if SWD -speed 4000 -autoconnect 1 -SelectEmuBySN SEGGER_ID 10 | J-Link>MSDDisable 11 | Probe configured successfully. 12 | J-Link>exit 13 | ``` 14 | 15 | ## Run the sample 16 | Build and flash the program using west: 17 | ``` 18 | west build -b nrf52840dk_nrf52840 19 | west flash 20 | ``` 21 | 22 | ## Serial Recovery 23 | To activate the Serial Recovery Mode, hold Button 1 while restarting the Developement Kit. 24 | Now, you should be able communicate with the bootloader using [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/zephyr/guides/device_mgmt/mcumgr.html): 25 | ``` 26 | mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" 27 | mcumgr -c acm0 image list 28 | ``` 29 | The list command should print: 30 | ``` 31 | Images: 32 | image=0 slot=0 33 | version: 0.0.0.0 34 | bootable: false 35 | flags: 36 | hash: Unavailable 37 | Split status: N/A (0) 38 | ``` 39 | 40 | Change something in the sample to see a difference. Build the sample again and upload the image using mcumgr: 41 | ``` 42 | west build 43 | mcumgr -c acm0 image upload build/zephyr/app_update.bin 44 | mcumgr -c acm0 reset 45 | ``` 46 | 47 | After the reset, your new code should run on the nRF52. 48 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_uart/prj.conf: -------------------------------------------------------------------------------- 1 | # Nothing here 2 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_uart/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | printk("Change this to see it change.\n"); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_uart/sysbuild.conf: -------------------------------------------------------------------------------- 1 | SB_CONFIG_BOOTLOADER_MCUBOOT=y 2 | 3 | SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y 4 | -------------------------------------------------------------------------------- /bootloader_samples/serial_recovery/mcuboot_serial_recovery_uart/sysbuild/mcuboot.conf: -------------------------------------------------------------------------------- 1 | CONFIG_SINGLE_APPLICATION_SLOT=y 2 | 3 | # Enable MCUboot Serial Recovery 4 | CONFIG_MCUBOOT_SERIAL=y 5 | CONFIG_UART_CONSOLE=n 6 | 7 | CONFIG_MCUBOOT_INDICATION_LED=y 8 | -------------------------------------------------------------------------------- /bootloader_samples/smp/README.md: -------------------------------------------------------------------------------- 1 | # SMP Samples 2 | The [Simple Management Protocol (SMP)](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/services/device_mgmt/smp_protocol.html) is an application layer protocol provided by [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/services/device_mgmt/mcumgr.html). 3 | SMP is transport layer agnostic, so you can run it on top of any transport protocol. But in the nRF Connect SDK, UART and Bluetooth Low Energy are mostly used for this. 4 | 5 | For an official sample, see the [Zephyr SMP Server sample](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/samples/subsys/mgmt/mcumgr/smp_svr/README.html). 6 | I created a minimal version of a SMP Server, with only serial communication and Image Management for DFU at [MCUboot Simple sample](./mcuboot_smp) 7 | If you want to add Bluetooth functionality to the SMP Server, see the [Zephyr SMP Server sample](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/samples/subsys/mgmt/mcumgr/smp_svr/README.html) or my colleguas [Add DFU support to your application guide](https://devzone.nordicsemi.com/guides/nrf-connect-sdk-guides/b/software/posts/ncs-dfu). 8 | 9 | # Theory 10 | Disclaimer: This is unofficial, and just my understanding on how things works. I can be wrong. 11 | There are some official documentation on DFU in the nRF Connect SDK under [Device Firmware Upgrade](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/security_chapter.html#device-firmware-upgrade-dfu) 12 | Before reading this, I recommend having a look at the more basic theory under [Bootloader samples](../). 13 | 14 | ## What is DFU and why do we need it? 15 | A Device Firmware Upgrade (DFU) is when new firmware is sent to a device, updating it. 16 | When developing, you can program a chip using a Debugger. A Debugger can write to more or less any register in the chip. 17 | DFU on the other hand can only send an image to the application running on a device. Then the application can write that image to flash. 18 | But the application can not write to the slot itself runs in, as that would break the application. 19 | Therefore, we need a **second slot** to write the new image to, as such: 20 | ![Sent To Secondary Slot](../../.images/new_firmware.png) 21 | 22 | ## DFU is not the same as a bootloader 23 | DFU is to send new firmware to a slot in flash. 24 | This is often handeled by the application. 25 | The bootloader do not need to be involved in the DFU. 26 | The bootloader will read what is in its slots on boot, but does not care about how the slots were populated. 27 | It is possible to have a chip with a bootloader and not DFU functionality. (For example [NSIB Simple sample](../updatable_bootloader/nsib_simple)) 28 | 29 | However, It is possible for a bootloader to have functionality for DFU. See [Serial Recovery](../serial_recovery) for more information on this. 30 | 31 | ## mcumgr and SMP 32 | To transfer new firmware to the application, the nRF Connect SDK supports the [Simple Management Protocol (SMP)](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/services/device_mgmt/smp_protocol.html). 33 | A SMP Server will run on the chip to be upgraded, and a SMP Client will run on the "upgrader", typically a PC: 34 | ![SMP Client and Server](../../.images/smp_client_server.png) 35 | 36 | SMP is transport layer agnostic, so you can run it on top of any transport protocol. But in the nRF Connect SDK, UART and Bluetooth Low Energy are mostly used for this. 37 | 38 | The Zephyr Project supplies [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/services/device_mgmt/mcumgr.html) as a SMP Client. 39 | mcumgr supports transport over Bluetooth Low Energy, UART and UDP over IP. 40 | 41 | Nordic Semiconductor supplies the [nRF Connect for Mobile app](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-mobile) and the [nRF Device Firmware Update app](https://play.google.com/store/apps/details?id=no.nordicsemi.android.dfu&gl=US) for mobile phones as SMP Clients. 42 | We can use either of these applications to perform DFU over Bluetooth Low Energy. 43 | 44 | SMP functionality for DFU is called Image Management. 45 | SMP has other functionality as well, such as file transfer, but I will not cover these. 46 | 47 | It is possible to use another nRF chip as a SMP Client. My colleague has a sample for this in his [Bluetooth: Central SMP Client DFU sample](https://github.com/simon-iversen/ncs_samples/tree/master/central_smp_client_dfu). 48 | 49 | Performing DFU over a wireless connection is known as Firmware Over The Air (FOTA). 50 | 51 | ## SMP support for MCUboot and NSIB 52 | MCUboot will work with SMP. 53 | From the [NSIB docs](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/samples/bootloader/README.html): 54 | > Currently, this immutable bootloader does not support firmware updates over the SMP transport for either an upgradable bootloader or an application. 55 | > If the application using this bootloader requires SMP-based firmware updates, such as Bluetooth® LE DFU, include [MCUboot as a second-stage bootloader](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/ug_bootloader_adding.html#ug-bootloader-adding-upgradable). 56 | 57 | ## SMP over Bluetooth Low Energy 58 | The official [Zephyr SMP Server sample](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/samples/subsys/mgmt/mcumgr/smp_svr/README.html) can use Bluetooth Low Energy for DFU. 59 | In addition, my collegua has written this neat [Add DFU support to your application guide](https://devzone.nordicsemi.com/guides/nrf-connect-sdk-guides/b/software/posts/ncs-dfu), so I recommend checking it out! 60 | 61 | ## Image header and trailer 62 | Before we go further, I must mention image headers and trailers. 63 | These are metadata connected to the start and/or end of an image for a firmware update. 64 | ![Header and Trailer](../../.images/metadata.png) 65 | 66 | The metadata can contain things such as booting information, image hash and signing key. 67 | For NSIB, this metatada can be seen in the [struct fw_validation_info](https://github.com/nrfconnect/sdk-nrf/blob/0ea5deb771513a9ef9ced24844e180e9fe8f9a64/subsys/bootloader/bl_validation/bl_validation.c#L76-L95). 68 | For MCUboot, the header and footer is documented in its documentation on [MCUboot Bootloader Design](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/mcuboot/design.html). 69 | I cover a bit on verification and signing in [Keys and Signatures](../keys_and_signatures). 70 | 71 | 72 | ## Firmware update 73 | So now we have new firmware in the Second Slot. How do we get it to the Application slot? 74 | ![Before Swap](../../.images/before_swap.png) 75 | 76 | When the chip boots and enters bootloader mode, the bootloader will check metadata and its settings. 77 | If the bootloader is instructed to do so, it will swap the images in the primary and secondary slots. 78 | To swap the images, some method is needed so that the images do not "crash". 79 | The figure below use a swap area, but there exist other methods for this as well. 80 | I highly recommend watching [David Browns MCUboot youtube playlist](https://www.youtube.com/watch?v=mlGduM1W-gA&list=PLHoBLXiNitjEZFbSsz9UN69L-Z5-3oaee) to learn how MCUboot swaps. 81 | After the images have been swapped, the bootloader may enter the primary slot, which now contains the new firmware. 82 | 83 | ![Swap Visualized](../../.images/swap.png) 84 | 85 | ## Test or Confirm 86 | You may have remarked that in the previous sentence I wrote "**may** enter the primary slot". 87 | This is because the bootloader do not automatically swap slots if there is new firmware in the secondary slot. 88 | The bootloader will check the image metadata to see if it should swap. See [Boot Swap Types](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/mcuboot/design.html#boot-swap-types). 89 | The image can be tagged with CONFIRM, TEST or REVERT. 90 | 91 | If an image in the secondary slot is tagged CONFIRM, the bootloader will perform a swap on next reboot. 92 | The new firmware is now permanently in the primary slot. 93 | 94 | If an image in the secondary slot is tagged TEST, the bootloader will perform a swap on next reboot. 95 | After the swap, the image will be tagged REVERT. 96 | Unless the image is tagged CONFIRM, it will swap back to the secondary slot on next reboot. 97 | 98 | As far as I know, the image should only be tagged REVERT from the TEST case. 99 | 100 | The simplest way to tag images is by using [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/services/device_mgmt/mcumgr.html). 101 | ``` 102 | mcumgr -c acm0 image test 103 | mcumgr -c acm0 image confirm 104 | 105 | ``` 106 | 107 | ## Two slots 108 | As mentioned above, the DFU Server can not overwrite its current slot, and therefore needs an extra slot. 109 | However, there is another reason for needing two slots as well. 110 | If you update your application with a faulty update, your SMP Server can crash. In this case, you will not be able to send a new update to the SMP Server to fix the issue. 111 | As you can see in the Firmware Update figure, the previous firmware is still saved in the Secondary Slot after a DFU. 112 | Because of this, if the new firmware fails, we can recover back into the previous firmware; Revert to a working state. 113 | Then a new DFU can be performed with new firmware than actually works. 114 | 115 | ![Revert](../../.images/revert.png) 116 | 117 | MCUboot requires that its slots are the same size. 118 | The downside of having two bootloader slots is that they require more flash space. Here are two possible solutions to this: 119 | 1. Use external flash to store the secondary slot. 120 | 2. Use only one slot. I would not recommend this for FOTA. But you can do it without issue with [Serial Recovery](../serial_recovery). 121 | 122 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_ble/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | 9 | target_sources(app PRIVATE src/main.c src/bluetooth_smp.c) 10 | zephyr_library_include_directories(src) 11 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_ble/README.md: -------------------------------------------------------------------------------- 1 | # MCUboot SMP Sample feat Bluetooth Low Energy 2 | Code to make this work comes from the official [Zephyr SMP Server Sample](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/samples/subsys/mgmt/mcumgr/smp_svr/README.html). 3 | 4 | ## DevAcademy 5 | I recommend following [Nordic DevAcademy on Bootloaders/DFU](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-9-bootloaders-and-dfu-fota/) instead of this sample. 6 | 7 | ## Prepare the Developement Kit 8 | Disable the Mass Storage feature on the Interface MCU, so that it does not interfere: 9 | ``` 10 | $ JLinkExe 11 | J-Link>MSDDisable 12 | Probe configured successfully. 13 | J-Link>SetHWFC Force 14 | New configuration applies immediately. 15 | J-Link>exit 16 | ``` 17 | 18 | ## Build and Flash 19 | 20 | ``` 21 | west build -b 22 | west flash --recover 23 | ``` 24 | 25 | ## Test sample for nRF5340 26 | Change the print in src/main.c to see change. 27 | Rebuild: 28 | ``` 29 | west build 30 | ``` 31 | 32 | ## DFU over UART 33 | Program the new image using [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/guides/device_mgmt/mcumgr.html): 34 | Find which serial connection the Developement Kit is connected to. This sample assumes /dev/ttyACM1. 35 | 36 | ### Update application core 37 | ``` 38 | mcumgr conn add acm1 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" 39 | mcumgr -c acm1 image list 40 | mcumgr -c acm1 image upload build/zephyr/app_update.bin 41 | mcumgr -c acm1 image list 42 | ``` 43 | Then tell MCUBoot to boot from the new slot next reboot: 44 | ``` 45 | mcumgr -c acm1 image confirm 46 | ``` 47 | 48 | Lastly, reset the Developement Kit: 49 | ``` 50 | nrfjprog --reset 51 | ``` 52 | 53 | ### Update network core 54 | ``` 55 | mcumgr conn add acm1 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" 56 | mcumgr -c acm1 image list 57 | mcumgr -c acm1 image upload build/zephyr/net_core_app_update.bin 58 | mcumgr -c acm1 image list 59 | ``` 60 | Then tell MCUBoot to boot from the new slot next reboot: 61 | ``` 62 | mcumgr -c acm1 image confirm 63 | ``` 64 | 65 | Lastly, reset the Developement Kit: 66 | ``` 67 | nrfjprog --reset 68 | ``` 69 | 70 | ## DFU over Bluetooth Low Energy 71 | 72 | Install the [nRF Connect for Mobile app](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-mobile) on a mobile phone. 73 | 74 | Move build/zephyr/app\_update.bin and build/zephyr/net\_core\_app\_update.bin to your mobile phone. 75 | 76 | Use the nRF Connect to connect to the DK: 77 | 78 | ![App Connect](../../../.images/nrf_connect_app_connect.png) 79 | 80 | Click the DFU button: 81 | 82 | ![App DFU](../../../.images/nrf_connect_app_dfu.png) 83 | 84 | Then select app\_update.bin or net\_core\_app\_update.bin upload it using "Confirm Only". 85 | 86 | Lastly, reset the Developement Kit. The selected core will be updated. 87 | ``` 88 | nrfjprog --reset 89 | ``` 90 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_ble/prj.conf: -------------------------------------------------------------------------------- 1 | # Enable SMP Server 2 | CONFIG_MCUMGR=y 3 | CONFIG_MCUMGR_GRP_IMG=y 4 | 5 | # CONFIG_MCUMGR_GRP_IMG dependencies 6 | CONFIG_FLASH=y 7 | CONFIG_IMG_MANAGER=y 8 | 9 | # CONFIG_IMG_MANAGER dependencies 10 | CONFIG_STREAM_FLASH=y 11 | 12 | # CONFIG_MCUMGR dependencies 13 | CONFIG_NET_BUF=y 14 | CONFIG_ZCBOR=y 15 | 16 | # Required for CONFIG_IMG_MANAGER 17 | CONFIG_FLASH_MAP=y 18 | 19 | # Enable BLE transfer 20 | CONFIG_BT=y 21 | CONFIG_BT_PERIPHERAL=y 22 | CONFIG_BT_DEVICE_NAME="Test SMP Server" 23 | CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y 24 | 25 | CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y 26 | CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP=y 27 | 28 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 29 | 30 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_ble/src/bluetooth_smp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * Copyright (c) 2020 Prevas A/S 4 | * 5 | * SPDX-License-Identifier: Apache-2.0 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "bluetooth_smp.h" 15 | 16 | #define LOG_LEVEL LOG_LEVEL_DBG 17 | #include 18 | LOG_MODULE_REGISTER(smp_bt_sample); 19 | 20 | static struct k_work advertise_work; 21 | 22 | static const struct bt_data ad[] = { 23 | BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), 24 | BT_DATA_BYTES(BT_DATA_UUID128_ALL, SMP_BT_SVC_UUID_VAL), 25 | }; 26 | 27 | static const struct bt_data sd[] = { 28 | BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), 29 | }; 30 | 31 | static void advertise(struct k_work *work) 32 | { 33 | int rc; 34 | 35 | rc = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); 36 | if (rc) { 37 | LOG_ERR("Advertising failed to start (rc %d)", rc); 38 | return; 39 | } 40 | 41 | LOG_INF("Advertising successfully started"); 42 | } 43 | 44 | static void connected(struct bt_conn *conn, uint8_t err) 45 | { 46 | if (err) { 47 | LOG_ERR("Connection failed, err 0x%02x %s", err, bt_hci_err_to_str(err)); 48 | k_work_submit(&advertise_work); 49 | } else { 50 | LOG_INF("Connected"); 51 | } 52 | } 53 | 54 | static void disconnected(struct bt_conn *conn, uint8_t reason) 55 | { 56 | LOG_INF("Disconnected, reason 0x%02x %s", reason, bt_hci_err_to_str(reason)); 57 | } 58 | 59 | static void on_conn_recycled(void) 60 | { 61 | k_work_submit(&advertise_work); 62 | } 63 | 64 | BT_CONN_CB_DEFINE(conn_callbacks) = { 65 | .connected = connected, 66 | .disconnected = disconnected, 67 | .recycled = on_conn_recycled, 68 | }; 69 | 70 | static void bt_ready(int err) 71 | { 72 | if (err != 0) { 73 | LOG_ERR("Bluetooth failed to initialise: %d", err); 74 | } else { 75 | k_work_submit(&advertise_work); 76 | } 77 | } 78 | 79 | void start_smp_bluetooth_adverts(void) 80 | { 81 | int rc; 82 | 83 | k_work_init(&advertise_work, advertise); 84 | rc = bt_enable(bt_ready); 85 | 86 | if (rc != 0) { 87 | LOG_ERR("Bluetooth enable failed: %d", rc); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_ble/src/bluetooth_smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Prevas A/S 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | void start_smp_bluetooth_adverts(void); 8 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_ble/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include "bluetooth_smp.h" 9 | 10 | int main(void) 11 | { 12 | start_smp_bluetooth_adverts(); 13 | printk("Change this to see it change.\n"); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_ble/sysbuild.conf: -------------------------------------------------------------------------------- 1 | SB_CONFIG_BOOTLOADER_MCUBOOT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart/README.md: -------------------------------------------------------------------------------- 1 | # MCUBoot SMP simple sample 2 | 3 | ## DevAcademy 4 | I recommend following [Nordic DevAcademy on Bootloaders/DFU](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-9-bootloaders-and-dfu-fota/) instead of this sample. 5 | 6 | ## Prepare the Developement Kit 7 | Disable the Mass Storage feature on the Interface MCU, so that it does not interfere: 8 | ``` 9 | $ JLinkExe 10 | J-Link>MSDDisable 11 | Probe configured successfully. 12 | J-Link>SetHWFC Force 13 | New configuration applies immediately. 14 | J-Link>exit 15 | ``` 16 | 17 | ## Build and Flash 18 | 19 | ``` 20 | west build -b 21 | west flash --recover 22 | ``` 23 | 24 | ## Run sample 25 | 26 | Change the print in src/main.c to see change. 27 | Rebuild: 28 | ``` 29 | west build 30 | ``` 31 | 32 | Program the new image using [mcumgr](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/guides/device_mgmt/mcumgr.html): 33 | Find which serial connection the Developement Kit is connected to. This sample assumes /dev/ttyACM0. 34 | 35 | ``` 36 | mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" 37 | mcumgr -c acm0 image list 38 | mcumgr -c acm0 image upload build/zephyr/app_update.bin 39 | mcumgr -c acm0 image list 40 | ``` 41 | 42 | Then tell MCUBoot to boot from the new slot next reboot using one of these commands: 43 | ``` 44 | mcumgr -c acm0 image test 45 | ``` 46 | or 47 | ``` 48 | mcumgr -c acm0 image confirm 49 | ``` 50 | 51 | Lastly, reset the Developement Kit: 52 | ``` 53 | nrfjprog --reset 54 | ``` 55 | 56 | ## Extra steps for the nRF5340 57 | 58 | To update the Network Core, follow the guide above, but for change the "upload" step with the following: 59 | ``` 60 | mcumgr -c acm1 image upload -e -n 3 build/zephyr/net_core_app_update.bin 61 | mcumgr -c acm1 image list 62 | mcumgr -c acm1 image test 63 | ``` 64 | Wait 2 minutes for the image to be copied to the netcore, and reset the nRF5340 after. 65 | 66 | The -n numbers are set as follows: 67 | ``` 68 | slot 0 - image 0 primary 69 | slot 1 - image 0 secondary 70 | slot 2 - image 1 primary ("Virtual" slot) 71 | slot 3 - image 1 secondary 72 | ``` 73 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart/boards/nrf5340dk_nrf5340_cpuapp.conf: -------------------------------------------------------------------------------- 1 | # Adding this to automatically add network core image 2 | CONFIG_BT=y 3 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart/boards/nrf5340dk_nrf5340_cpuapp_ns.conf: -------------------------------------------------------------------------------- 1 | # Adding this to automatically add network core image 2 | CONFIG_BT=y 3 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MCUMGR=y 2 | CONFIG_MCUMGR_TRANSPORT_UART=y 3 | CONFIG_MCUMGR_GRP_IMG=y 4 | 5 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 6 | CONFIG_BASE64=y 7 | CONFIG_CRC=y 8 | 9 | # CONFIG_MCUMGR_GRP_IMG dependencies 10 | CONFIG_FLASH=y 11 | CONFIG_IMG_MANAGER=y 12 | 13 | # CONFIG_IMG_MANAGER dependencies 14 | CONFIG_STREAM_FLASH=y 15 | 16 | # CONFIG_MCUMGR dependencies 17 | CONFIG_NET_BUF=y 18 | CONFIG_ZCBOR=y 19 | 20 | # Required for CONFIG_IMG_MANAGER 21 | CONFIG_FLASH_MAP=y 22 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | printk("Change this to see it change.\n"); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart/sysbuild.conf: -------------------------------------------------------------------------------- 1 | SB_CONFIG_BOOTLOADER_MCUBOOT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/README.md: -------------------------------------------------------------------------------- 1 | # MCUBoot SMP simple sample feat external flash 2 | This is the [Simple SMP Sample over UART](../mcuboot_smp_uart), but with external flash enabled. 3 | See that sample for instructions on how to build and run. 4 | See [Partition Manager docs](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#external-flash-memory-partitions) for how to enable external flash. 5 | For an official sample, see [this external flash test](https://github.com/nrfconnect/sdk-nrf/tree/main/tests/modules/mcuboot/external_flash) for an official sample. 6 | See [Multi-image builds](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/app_dev/multi_image/index.html) for folder structure. 7 | 8 | ## DevAcademy 9 | I recommend following [Nordic DevAcademy on Bootloaders/DFU](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-9-bootloaders-and-dfu-fota/) instead of this sample. 10 | 11 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/app.overlay: -------------------------------------------------------------------------------- 1 | / { 2 | chosen { 3 | nordic,pm-ext-flash = &mx25r64; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/boards/nrf5340dk_nrf5340_cpuapp.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/boards/nrf5340dk_nrf5340_cpuapp_ns.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MCUMGR=y 2 | CONFIG_MCUMGR_TRANSPORT_UART=y 3 | CONFIG_MCUMGR_GRP_IMG=y 4 | 5 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 6 | CONFIG_BASE64=y 7 | CONFIG_CRC=y 8 | 9 | # CONFIG_MCUMGR_GRP_IMG dependencies 10 | CONFIG_FLASH=y 11 | CONFIG_IMG_MANAGER=y 12 | 13 | # CONFIG_IMG_MANAGER dependencies 14 | CONFIG_STREAM_FLASH=y 15 | 16 | # CONFIG_MCUMGR dependencies 17 | CONFIG_NET_BUF=y 18 | CONFIG_ZCBOR=y 19 | 20 | # Required for CONFIG_IMG_MANAGER 21 | CONFIG_FLASH_MAP=y 22 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | printk("Change this to see it change.\n"); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/sysbuild.conf: -------------------------------------------------------------------------------- 1 | SB_CONFIG_BOOTLOADER_MCUBOOT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/sysbuild/mcuboot.conf: -------------------------------------------------------------------------------- 1 | CONFIG_NORDIC_QSPI_NOR=y 2 | CONFIG_BOOT_MAX_IMG_SECTORS=256 3 | 4 | # Enable logging 5 | CONFIG_LOG=y 6 | CONFIG_LOG_DEFAULT_LEVEL=4 7 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_external_flash/sysbuild/mcuboot.overlay: -------------------------------------------------------------------------------- 1 | / { 2 | chosen { 3 | nordic,pm-ext-flash = &mx25r64; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_rtt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_rtt/README.md: -------------------------------------------------------------------------------- 1 | # MCUBoot SMP simple sample feat RTT 2 | A sample to show how to enable RTT logging in the MCUboot child image. 3 | You might have to reconnect RTT viewer on DK reset. 4 | See [Simple SMP server feat UART sample](../mcuboot_smp_uart) for how to test the DFU in this sample. 5 | 6 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_rtt/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MCUMGR=y 2 | CONFIG_MCUMGR_TRANSPORT_UART=y 3 | CONFIG_MCUMGR_GRP_IMG=y 4 | 5 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 6 | CONFIG_BASE64=y 7 | 8 | # CONFIG_MCUMGR_GRP_IMG dependencies 9 | CONFIG_FLASH=y 10 | CONFIG_IMG_MANAGER=y 11 | 12 | # CONFIG_IMG_MANAGER dependencies 13 | CONFIG_STREAM_FLASH=y 14 | 15 | # CONFIG_MCUMGR dependencies 16 | CONFIG_NET_BUF=y 17 | CONFIG_ZCBOR=y 18 | 19 | # Required for CONFIG_IMG_MANAGER 20 | CONFIG_FLASH_MAP=y 21 | 22 | CONFIG_LOG_BACKEND_RTT=n 23 | CONFIG_USE_SEGGER_RTT=n 24 | 25 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_rtt/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | printk("Change this to see it change.\n"); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_rtt/sysbuild.conf: -------------------------------------------------------------------------------- 1 | SB_CONFIG_BOOTLOADER_MCUBOOT=y 2 | -------------------------------------------------------------------------------- /bootloader_samples/smp/mcuboot_smp_uart_feat_rtt/sysbuild/mcuboot.conf: -------------------------------------------------------------------------------- 1 | CONFIG_LOG=y 2 | CONFIG_LOG_DEFAULT_LEVEL=4 3 | CONFIG_LOG_PRINTK=y 4 | CONFIG_LOG_MODE_IMMEDIATE=y 5 | CONFIG_LOG_BACKEND_RTT=y 6 | CONFIG_LOG_BACKEND_UART=n 7 | 8 | CONFIG_CONSOLE=y 9 | CONFIG_UART_CONSOLE=n 10 | CONFIG_RTT_CONSOLE=y 11 | CONFIG_USE_SEGGER_RTT=y 12 | 13 | CONFIG_MULTITHREADING=y 14 | -------------------------------------------------------------------------------- /bootloader_samples/updatable_bootloader/README.md: -------------------------------------------------------------------------------- 1 | # Updatable Bootloader 2 | These samples show you how you can use [NSIB](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/samples/bootloader/README.html) in addition to MCUboot. 3 | This way NSIB will be the immutable bootloader and MCUboot will be an upgradable bootloader. 4 | 5 | # Theory 6 | See the official documentation on [Bootloaders and Device Firmware Update](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/nrf/app_bootloaders.html#app-bootloaders). 7 | -------------------------------------------------------------------------------- /bootloader_samples/updatable_bootloader/nsib_mcuboot_smp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /bootloader_samples/updatable_bootloader/nsib_mcuboot_smp/README.md: -------------------------------------------------------------------------------- 1 | # Sample on how to use NSIB(b0) to update MCUBoot feat. SMP Server 2 | ## Preparation of the Developement Kit 3 | Disable the Mass Storage feature on the device, so that it does not interfere: 4 | ``` 5 | JLinkExe -device NRF52840_XXAA -if SWD -speed 4000 -autoconnect 1 -SelectEmuBySN SEGGER_ID 6 | J-Link>MSDDisable 7 | Probe configured successfully. 8 | J-Link>exit 9 | ``` 10 | 11 | ## Build 12 | Build and flash the program using west. 13 | 14 | Now increment CONFIG_FW_INFO_FIRMWARE_VERSION in child_image/mcuboot/prj.conf. 15 | 16 | To make the change visible, make a change to MCUBoot, for example add a log in $NRF_CONNECT_SDK/bootloader/mcuboot/boot/zephyr/main.c. 17 | 18 | Build again, and upload the new image using mcumgr: 19 | ``` 20 | mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" 21 | mcumgr -c acm0 image list 22 | mcumgr -c acm0 image upload build/zephyr/signed_by_mcuboot_and_b0_s1_image_update.bin 23 | mcumgr -c acm0 image list 24 | ``` 25 | 26 | Copy the hash of the newly uploaded image, and use it to confirm it, making the new image run at next reboot, such as: 27 | ``` 28 | mcumgr -c acm0 image confirm 2348de4f84cb19c1c2721662ad1275da5c21eca749da9b32db20d2c9dffb47c0 29 | ``` 30 | 31 | Then reboot the Developement Kit. This will load the new MCUBoot image its slot. 32 | Reboot the Developement Kit again to load using the new version of MCUBoot. 33 | 34 | If you want to update MCUBoot multiple times, you should alternate between signed_by_mcuboot_and_b0_s1_image_update and signed_by_mcuboot_and_b0_s0_image_update. 35 | This is so that you will be able to boot back into the already functioning MCUBoot if the one you upload is not validated correctly. 36 | 37 | ## Key generation 38 | The keys in this sample was generated using: 39 | ``` 40 | ${NCS_PATH}/bootloader/mcuboot/scripts/imgtool.py keygen -k custom_priv.pem -t ecdsa-p256 41 | ``` 42 | Also see the [Imgtool documentation](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/mcuboot/imgtool.html). 43 | -------------------------------------------------------------------------------- /bootloader_samples/updatable_bootloader/nsib_mcuboot_smp/VERSION: -------------------------------------------------------------------------------- 1 | VERSION_MAJOR = 1 2 | VERSION_MINOR = 2 3 | PATCHLEVEL = 3 4 | VERSION_TWEAK = 4 5 | EXTRAVERSION = unstable 6 | -------------------------------------------------------------------------------- /bootloader_samples/updatable_bootloader/nsib_mcuboot_smp/child_image/mcuboot.conf: -------------------------------------------------------------------------------- 1 | CONFIG_LOG=y 2 | CONFIG_LOG_MODE_MINIMAL=y 3 | 4 | CONFIG_FW_INFO_FIRMWARE_VERSION=7 5 | -------------------------------------------------------------------------------- /bootloader_samples/updatable_bootloader/nsib_mcuboot_smp/nsib_priv.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgDE6cxEFdSPZvoKjy 3 | K4MAKLyL3jGiop+o9PjKDt8W7WqhRANCAAQT99KFk/nT5O1dnzJV3xIZvgJvxaBd 4 | Ndr3WPlIm6oaIWS4b/fTAmBPfKWQa+qA28bsNUWxSqUjYPqK4sMrcSD3 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /bootloader_samples/updatable_bootloader/nsib_mcuboot_smp/prj.conf: -------------------------------------------------------------------------------- 1 | 2 | CONFIG_BOOTLOADER_MCUBOOT=y 3 | CONFIG_MCUMGR=y 4 | CONFIG_MCUMGR_TRANSPORT_UART=y 5 | CONFIG_MCUMGR_GRP_IMG=y 6 | 7 | # CONFIG_MCUMGR_TRANSPORT_UART dependencies 8 | CONFIG_BASE64=y 9 | 10 | # CONFIG_MCUMGR_GRP_IMG dependencies 11 | CONFIG_FLASH=y 12 | CONFIG_IMG_MANAGER=y 13 | 14 | # CONFIG_IMG_MANAGER dependencies 15 | CONFIG_STREAM_FLASH=y 16 | 17 | # CONFIG_MCUMGR dependencies 18 | CONFIG_NET_BUF=y 19 | CONFIG_ZCBOR=y 20 | 21 | # Required for CONFIG_IMG_MANAGER 22 | CONFIG_FLASH_MAP=y 23 | 24 | CONFIG_SECURE_BOOT=y 25 | CONFIG_SB_SIGNING_KEY_FILE="nsib_priv.pem" 26 | CONFIG_BUILD_S1_VARIANT=y 27 | # Need to lower the number of counter slots to be able to update several times. Do not know the best number yet. 28 | CONFIG_SB_NUM_VER_COUNTER_SLOTS=120 29 | 30 | -------------------------------------------------------------------------------- /bootloader_samples/updatable_bootloader/nsib_mcuboot_smp/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | 9 | int main(void) 10 | { 11 | printk("Change this to see change\n"); 12 | return 1; 13 | } 14 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.20.0) 8 | 9 | set(ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}) 10 | 11 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 12 | project(app) 13 | 14 | target_sources(app PRIVATE src/main.c) 15 | 16 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/Kconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | source "Kconfig.zephyr" 7 | 8 | config INCLUDE_CUSTOM_IMAGE 9 | bool "Include net image as sub image" 10 | default y 11 | select PARTITION_MANAGER_ENABLED 12 | 13 | module=CUSTOM 14 | source "${ZEPHYR_BASE}/../nrf/subsys/partition_manager/Kconfig.template.build_strategy" 15 | 16 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/README.md: -------------------------------------------------------------------------------- 1 | # Custom hex file to custom partition sample 2 | Based on the [nRF5340 multicore sample](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/nrf5340/multicore/README.html). 3 | 4 | ## Disclaimer 5 | This code/configuration is not thoroughly tested or qualified and should be considered provided “as-is”. Please test it with your application and let me know if you find any issues. 6 | 7 | 8 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/aci/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # This check is needed to avoid infinite recursion. This module code will 8 | # be executed for all images in the build, also for the child image being 9 | # added below. 10 | if (CONFIG_INCLUDE_CUSTOM_IMAGE) 11 | add_child_image( 12 | NAME custom 13 | SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../custom 14 | ) 15 | endif() 16 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/custom/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.20.0) 8 | 9 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 10 | project(custom) 11 | 12 | target_sources(app PRIVATE ./src/main.c) 13 | 14 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/custom/pm.yml: -------------------------------------------------------------------------------- 1 | custom: 2 | size: 0x8000 3 | placement: 4 | after: [app] 5 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/custom/prj.conf: -------------------------------------------------------------------------------- 1 | # Decrease memory footprint 2 | CONFIG_CBPRINTF_NANO=y 3 | CONFIG_TIMESLICING=n 4 | CONFIG_BOOT_BANNER=n 5 | CONFIG_CONSOLE=n 6 | CONFIG_CONSOLE_HANDLER=n 7 | CONFIG_UART_CONSOLE=n 8 | CONFIG_USE_SEGGER_RTT=n 9 | CONFIG_LOG=n 10 | CONFIG_ERRNO=n 11 | CONFIG_PRINTK=y 12 | CONFIG_RESET_ON_FATAL_ERROR=n 13 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/custom/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | #include 8 | 9 | uint8_t return68(){ 10 | uint8_t ret = 68; 11 | printk("Hello world from child image built from hex\n"); 12 | 13 | return ret; 14 | } 15 | 16 | 17 | // Include main to stop compiler from optimizing out return68 18 | void main(void) 19 | { 20 | return68(); 21 | } 22 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/pm_static.yml: -------------------------------------------------------------------------------- 1 | app: 2 | address: 0x0 3 | end_address: 0xf8000 4 | region: flash_primary 5 | size: 0xf8000 6 | custom: 7 | address: 0xf8000 8 | end_address: 0x100000 9 | region: flash_primary 10 | size: 0x8000 11 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_PRINTK=y 2 | CONFIG_BOOTLOADER_MCUBOOT=n 3 | 4 | CONFIG_CUSTOM_BUILD_STRATEGY_USE_HEX_FILE=y 5 | CONFIG_CUSTOM_HEX_FILE="/home/bruk/git/samples_for_nrf_connect_sdk/build_system/custom_child_image/custom.hex" 6 | 7 | CONFIG_LOG=y 8 | CONFIG_RESET_ON_FATAL_ERROR=n 9 | CONFIG_THREAD_NAME=y 10 | 11 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: Child image from source template 3 | description: Template of application that builds cpunet from sources 4 | tests: 5 | sample.nrf5340.multicore: 6 | build_only: true 7 | platform_allow: nrf5340dk_nrf5340_cpuapp 8 | integration_platforms: 9 | - nrf5340dk_nrf5340_cpuapp 10 | tags: ci_build 11 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #define RETURN68_ADDR 0xf83d4 // Found from searching build/zephyr/zephyr.map for "return68" 11 | 12 | void main(void) 13 | { 14 | printk("Hello world from app\n"); 15 | 16 | void* function_ptr = (void*)(RETURN68_ADDR+1); 17 | 18 | uint8_t ret = ((uint8_t (*)(void*))function_ptr)(NULL); 19 | 20 | printk("Returned %d\n",ret); 21 | } 22 | -------------------------------------------------------------------------------- /build_system/custom_hex_partition/zephyr/module.yml: -------------------------------------------------------------------------------- 1 | build: 2 | cmake: aci 3 | -------------------------------------------------------------------------------- /crypto/psa_csr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.20.0) 8 | 9 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 10 | 11 | project(ecdsa) 12 | 13 | target_sources(app PRIVATE 14 | src/main.c) 15 | -------------------------------------------------------------------------------- /crypto/psa_csr/README.md: -------------------------------------------------------------------------------- 1 | # PSA CSR sample 2 | This sample (will soon) show how to do a Certificate Signing Request (CSR) with the PSA Crypto APIs. 3 | 4 | # TF-M 5 | This sample was tested without Trusted Firmware-M. It gets some build errors with, but I beleive this should be mostly due to different default configuration with TF-M. 6 | 7 | ## Patching sdk-nrf 8 | To run the sample, you need to apply a patch first: 9 | ``` 10 | cd NCS_PATH/nrf/ 11 | git apply PATH_TO/csr_fixed_nrf.patch 12 | ``` 13 | 14 | ## Docs 15 | This sample is uses the [PSA Crypto ECDSA sample](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/samples/crypto/ecdsa/README.html) as a base. 16 | This sample CSR code is from the [Zephyr TF-M PSA Crypto CSR sample](https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/samples/tfm_integration/psa_crypto/README.html). 17 | The Zephyr sample from above uses Legact MbedTLS drivers for CSR. The converting of this sample to use PSA Crypto API directly for CSR was done using these docs on [MbedTLS: Using opaque ECDSA keys to generate certificate signing requests (CSRs)](https://os.mbed.com/docs/mbed-os/v6.16/porting/using-psa-enabled-mbed-tls.html#using-opaque-ecdsa-keys-to-generate-certificate-signing-requests-csrs). 18 | 19 | ## Disclaimer 20 | When writing this sample, I did not verify the output. As a user of this sample, you should test the output to make sure it does what you expect. 21 | 22 | ## Output 23 | Here is the output I get from the sample over logging: 24 | ``` 25 | *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 *** 26 | *** Using Zephyr OS v3.6.99-100befc70c74 *** 27 | [00:00:00.389,190] ecdsa: Starting ECDSA example... 28 | [00:00:00.395,263] ecdsa: Generating random ECDSA keypair... 29 | [00:00:00.426,574] ecdsa: Signing a message using ECDSA... 30 | [00:00:00.463,195] ecdsa: Message signed successfully! 31 | [00:00:00.469,512] ecdsa: ---- Plaintext (len: 100): ---- 32 | [00:00:00.476,135] ecdsa: Content: 33 | 45 78 61 6d 70 6c 65 20 73 74 72 69 6e 67 20 74 |Example string t 34 | 6f 20 64 65 6d 6f 6e 73 74 72 61 74 65 20 62 61 |o demons trate ba 35 | 73 69 63 20 75 73 61 67 65 20 6f 66 20 45 43 44 |sic usag e of ECD 36 | 53 41 2e 00 00 00 00 00 00 00 00 00 00 00 00 00 |SA...... ........ 37 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |........ ........ 38 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |........ ........ 39 | 00 00 00 00 |.... 40 | [00:00:00.561,828] ecdsa: ---- Plaintext end ---- 41 | [00:00:00.567,779] ecdsa: ---- SHA256 hash (len: 32): ---- 42 | [00:00:00.574,462] ecdsa: Content: 43 | 6d bf 34 71 f1 7f cd 8d 99 13 10 e7 95 48 84 60 |m.4q.... .....H.` 44 | d3 35 65 8a 82 b6 76 07 5c 3b 79 3b be d7 6e 4f |.5e...v. \;y;..nO 45 | [00:00:00.597,900] ecdsa: ---- SHA256 hash end ---- 46 | [00:00:00.604,034] ecdsa: ---- Signature (len: 64): ---- 47 | [00:00:00.610,534] ecdsa: Content: 48 | 4f 48 15 67 18 7c ea 55 59 84 fe c4 9b 4d 82 05 |OH.g.|.U Y....M.. 49 | 69 33 d0 8d 7d 11 38 f6 62 3d 8c 5d 1f 5c 80 89 |i3..}.8. b=.].\.. 50 | d2 e5 c1 4e a1 97 a6 2b ae c1 4d 24 b1 ae de 95 |...N...+ ..M$.... 51 | a2 fc 65 03 c8 8f 2b e6 2d aa 28 cb 50 55 2a d9 |..e...+. -.(.PU*. 52 | [00:00:00.652,862] ecdsa: ---- Signature end ---- 53 | [00:00:00.658,843] ecdsa: Verifying ECDSA signature... 54 | [00:00:00.720,153] ecdsa: Signature verification was successful! 55 | [00:00:00.727,355] ecdsa: Setting up CSR... 56 | [00:00:00.732,910] ecdsa: Adding EC key to PK container completed 57 | [00:00:00.740,295] ecdsa: Create device Certificate Signing Request 58 | [00:00:00.803,619] ecdsa: Create device Certificate Signing Request completed 59 | [00:00:00.812,011] ecdsa: Certificate Signing Request: 60 | 61 | -----BEGIN CERTIFICATE REQUEST----- 62 | MIHpMIGQAgEAMC4xDzANBgNVBAoMBkxpbmFybzEbMBkGA1UEAwwSRGV2aWNlIENl 63 | cnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEApJRuGVNaKCQRVl 64 | CzOBQsHw+jESD7tAD8qaxybq/qNKJtkX7SXvrmANY5fdnx4BcqGz1uV69/0Nabh9 65 | WV+4XaAAMAoGCCqGSM49BAMCA0gAMEUCIQDTnWbeD0aLvWnHToJUB5/sEuXp0mED 66 | rs89Yu6f97sITwIgGo8YZuKNmGrCnP30jxdGSl2OqFFOtt3GswcAM3HeoJY= 67 | -----END CERTIFICATE REQUEST----- 68 | 69 | [00:00:00.853,210] ecdsa: Encoding CSR as json 70 | [00:00:00.859,405] ecdsa: Encoding CSR as json completed 71 | [00:00:00.865,905] ecdsa: Certificate Signing Request in JSON: 72 | 73 | {"CSR":"-----BEGIN CERTIFICATE REQUEST-----\nMIHpMIGQAgEAMC4xDzANBgNVBAoMBkxpbmFybzEbMBkGA1UEAwwSRGV2aWNlIENl\ncnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEApJRuGVNaKCQRVl\nCzOBQsHw+jESD7tAD8qaxybq/qNKJtkX7SXvrmANY5fdnx4BcqGz1uV69/0Nabh9\nWV+4XaAAMAoGCCqGSM49BAMCA0gAMEUCIQDTnWbeD0aLvWnHToJUB5/sEuXp0mED\nrs89Yu6f97sITwIgGo8YZuKNmGrCnP30jxdGSl2OqFFOtt3GswcAM3HeoJY=\n-----END CERTIFICATE REQUEST-----\n"} 74 | [00:00:00.910,247] ecdsa: Example finished successfully! 75 | ``` 76 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf52840dk_nrf52840.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | # Using hardware crypto accelerator 7 | CONFIG_PSA_CRYPTO_DRIVER_OBERON=y 8 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=n 9 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf5340dk_nrf5340_cpuapp.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | # Using hardware crypto accelerator 7 | CONFIG_PSA_CRYPTO_DRIVER_OBERON=n 8 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y 9 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf5340dk_nrf5340_cpuapp_ns.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | CONFIG_TFM_PROFILE_TYPE_NOT_SET=y 7 | 8 | # Using hardware crypto accelerator 9 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y 10 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | CONFIG_PSA_CRYPTO_DRIVER_OBERON=n 7 | CONFIG_PSA_CRYPTO_DRIVER_CRACEN=y 8 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf9151dk_nrf9151.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | # Using hardware crypto accelerator 7 | CONFIG_PSA_CRYPTO_DRIVER_OBERON=n 8 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y 9 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf9151dk_nrf9151_ns.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | CONFIG_TFM_PROFILE_TYPE_NOT_SET=y 7 | 8 | # Using hardware crypto accelerator 9 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y 10 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf9160dk_nrf9160.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | # Using hardware crypto accelerator 7 | CONFIG_PSA_CRYPTO_DRIVER_OBERON=n 8 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y 9 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf9160dk_nrf9160_ns.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | CONFIG_TFM_PROFILE_TYPE_NOT_SET=y 7 | 8 | # Using hardware crypto accelerator 9 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y 10 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf9161dk_nrf9161.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | # Using hardware crypto accelerator 7 | CONFIG_PSA_CRYPTO_DRIVER_OBERON=n 8 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y 9 | -------------------------------------------------------------------------------- /crypto/psa_csr/boards/nrf9161dk_nrf9161_ns.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | CONFIG_TFM_PROFILE_TYPE_NOT_SET=y 7 | 8 | # Using hardware crypto accelerator 9 | CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y 10 | -------------------------------------------------------------------------------- /crypto/psa_csr/csr_fixes_nrf.patch: -------------------------------------------------------------------------------- 1 | diff --git a/subsys/nrf_security/cmake/psa_crypto_config.cmake b/subsys/nrf_security/cmake/psa_crypto_config.cmake 2 | index 42075a55cd..9b15b6a7a4 100644 3 | --- a/subsys/nrf_security/cmake/psa_crypto_config.cmake 4 | +++ b/subsys/nrf_security/cmake/psa_crypto_config.cmake 5 | @@ -555,14 +555,14 @@ if (NOT CONFIG_MBEDTLS_PSA_CRYPTO_SPM) 6 | kconfig_check_and_set_base_int(MBEDTLS_MPI_MAX_SIZE) 7 | 8 | # x509 configurations 9 | - # kconfig_check_and_set_base_to_one(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 10 | - # kconfig_check_and_set_base_to_one(MBEDTLS_X509_USE_C) 11 | - # kconfig_check_and_set_base_to_one(MBEDTLS_X509_CRT_PARSE_C) 12 | - # kconfig_check_and_set_base_to_one(MBEDTLS_X509_CRL_PARSE_C) 13 | - # kconfig_check_and_set_base_to_one(MBEDTLS_X509_CSR_PARSE_C) 14 | - # kconfig_check_and_set_base_to_one(MBEDTLS_X509_CREATE_C) 15 | - # kconfig_check_and_set_base_to_one(MBEDTLS_X509_CRT_WRITE_C) 16 | - # kconfig_check_and_set_base_to_one(MBEDTLS_X509_CSR_WRITE_C) 17 | + kconfig_check_and_set_base_to_one(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 18 | + kconfig_check_and_set_base_to_one(MBEDTLS_X509_USE_C) 19 | + kconfig_check_and_set_base_to_one(MBEDTLS_X509_CRT_PARSE_C) 20 | + kconfig_check_and_set_base_to_one(MBEDTLS_X509_CRL_PARSE_C) 21 | + kconfig_check_and_set_base_to_one(MBEDTLS_X509_CSR_PARSE_C) 22 | + kconfig_check_and_set_base_to_one(MBEDTLS_X509_CREATE_C) 23 | + kconfig_check_and_set_base_to_one(MBEDTLS_X509_CRT_WRITE_C) 24 | + kconfig_check_and_set_base_to_one(MBEDTLS_X509_CSR_WRITE_C) 25 | 26 | # TLS key exchange 27 | kconfig_check_and_set_base_to_one(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) 28 | diff --git a/subsys/nrf_security/configs/psa_crypto_config.h.template b/subsys/nrf_security/configs/psa_crypto_config.h.template 29 | index 644591a3f6..61233713e4 100644 30 | --- a/subsys/nrf_security/configs/psa_crypto_config.h.template 31 | +++ b/subsys/nrf_security/configs/psa_crypto_config.h.template 32 | @@ -570,6 +570,25 @@ 33 | #define MBEDTLS_CIPHER_MODE_CBC 34 | #endif 35 | 36 | +/** 37 | + * \def MBEDTLS_PEM_WRITE_C 38 | + * 39 | + * Enable PEM encoding / writing. 40 | + * 41 | + * Module: library/pem.c 42 | + * Caller: library/pkwrite.c 43 | + * library/x509write_crt.c 44 | + * library/x509write_csr.c 45 | + * 46 | + * Requires: MBEDTLS_BASE64_C 47 | + * 48 | + * This modules adds support for encoding / writing PEM files. 49 | + */ 50 | +#define MBEDTLS_PEM_WRITE_C 51 | + 52 | +/* Define as a "hack" since it is required by the above. */ 53 | +#define MBEDTLS_BASE64_C 54 | + 55 | #include 56 | 57 | #include 58 | -------------------------------------------------------------------------------- /crypto/psa_csr/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | # The Zephyr CMSIS emulation assumes that ticks are ms, currently 7 | CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 8 | 9 | CONFIG_MAIN_STACK_SIZE=16000 10 | CONFIG_HEAP_MEM_POOL_SIZE=16000 11 | 12 | # Enable logging 13 | CONFIG_CONSOLE=y 14 | CONFIG_LOG=y 15 | 16 | # Enable nordic security backend and PSA APIs 17 | CONFIG_NRF_SECURITY=y 18 | CONFIG_MBEDTLS_PSA_CRYPTO_C=y 19 | 20 | CONFIG_MBEDTLS_ENABLE_HEAP=y 21 | CONFIG_MBEDTLS_HEAP_SIZE=8192 22 | 23 | CONFIG_PSA_WANT_ALG_ECDSA=y 24 | CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE=y 25 | CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT=y 26 | CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT=y 27 | CONFIG_PSA_WANT_ECC_SECP_R1_256=y 28 | CONFIG_PSA_WANT_ALG_SHA_256=y 29 | 30 | # For key generation 31 | CONFIG_PSA_WANT_GENERATE_RANDOM=y 32 | 33 | #----------------------------- Below is what I added beyond ECDSA sample defaults 34 | 35 | # mbed TLS and security 36 | CONFIG_MBEDTLS_PK_C=y 37 | 38 | CONFIG_MBEDTLS_ENABLE_HEAP=y 39 | CONFIG_MBEDTLS_HEAP_SIZE=32768 40 | CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=2304 41 | CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2304 42 | CONFIG_MBEDTLS_TLS_LIBRARY=y 43 | CONFIG_MBEDTLS_X509_LIBRARY=y 44 | CONFIG_NRF_SECURITY_ADVANCED=y 45 | 46 | # NB: This list of PSA dependencies may be too long 47 | CONFIG_PSA_WANT_GENERATE_RANDOM=y 48 | CONFIG_PSA_WANT_KEY_TYPE_AES=y 49 | CONFIG_PSA_WANT_ALG_CCM=y 50 | CONFIG_PSA_WANT_ALG_GCM=y 51 | CONFIG_PSA_WANT_ALG_CHACHA20_POLY1305=y 52 | CONFIG_PSA_WANT_ALG_CMAC=y 53 | CONFIG_PSA_WANT_ALG_HMAC=y 54 | CONFIG_PSA_WANT_ALG_SHA_1=y 55 | CONFIG_PSA_WANT_ALG_SHA_224=y 56 | CONFIG_PSA_WANT_ALG_SHA_256=y 57 | CONFIG_PSA_WANT_ALG_SHA_384=y 58 | CONFIG_PSA_WANT_ALG_SHA_512=y 59 | CONFIG_PSA_WANT_ALG_ECB_NO_PADDING=y 60 | CONFIG_PSA_WANT_ALG_CBC_NO_PADDING=y 61 | CONFIG_PSA_WANT_ALG_CBC_PKCS7=y 62 | CONFIG_PSA_WANT_ALG_CTR=y 63 | CONFIG_PSA_WANT_ALG_HKDF=y 64 | CONFIG_PSA_WANT_ALG_TLS12_PRF=y 65 | CONFIG_PSA_WANT_ALG_ECDH=y 66 | CONFIG_PSA_WANT_ALG_ECDSA=y 67 | CONFIG_PSA_WANT_ALG_DETERMINISTIC_ECDSA=y 68 | CONFIG_PSA_WANT_ECC_SECP_R1_256=y 69 | CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT=y 70 | CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT=y 71 | CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE=y 72 | CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE=y 73 | CONFIG_PSA_WANT_ALG_STREAM_CIPHER=y 74 | CONFIG_PSA_WANT_KEY_TYPE_CHACHA20=y 75 | CONFIG_PSA_WANT_ALG_TLS12_PSK_TO_MS=y 76 | 77 | # ------------------ My custom adds 78 | CONFIG_LOG_MODE_IMMEDIATE=y 79 | 80 | # Enable X509 configs 81 | CONFIG_MBEDTLS_X509_CREATE_C=y 82 | CONFIG_MBEDTLS_X509_CSR_WRITE_C=y 83 | 84 | # Enable JSON for output 85 | CONFIG_JSON_LIBRARY=y 86 | 87 | CONFIG_MBEDTLS_DEBUG_C=y 88 | -------------------------------------------------------------------------------- /crypto/psa_csr/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: | 3 | This app provides an example of signing/verifying using ECDSA signatures 4 | name: ECDSA example 5 | tests: 6 | sample.ecdsa.cc3xx: 7 | sysbuild: true 8 | tags: introduction psa cc3xx sysbuild 9 | platform_allow: > 10 | nrf5340dk/nrf5340/cpuapp/ns nrf5340dk/nrf5340/cpuapp nrf9160dk/nrf9160/ns 11 | nrf9160dk/nrf9160 nrf52840dk/nrf52840 nrf9161dk/nrf9161 nrf9161dk/nrf9161/ns 12 | nrf9151dk/nrf9151 nrf9151dk/nrf9151/ns 13 | harness: console 14 | harness_config: 15 | type: multi_line 16 | regex: 17 | - ".*Example finished successfully!.*" 18 | integration_platforms: 19 | - nrf5340dk/nrf5340/cpuapp/ns 20 | - nrf5340dk/nrf5340/cpuapp 21 | - nrf9160dk/nrf9160/ns 22 | - nrf9160dk/nrf9160 23 | - nrf52840dk/nrf52840 24 | - nrf9161dk/nrf9161 25 | - nrf9161dk/nrf9161/ns 26 | - nrf9151dk/nrf9151 27 | - nrf9151dk/nrf9151/ns 28 | sample.ecdsa.cracen: 29 | sysbuild: true 30 | tags: introduction psa cracen sysbuild 31 | platform_allow: > 32 | nrf54l15pdk/nrf54l15/cpuapp 33 | nrf54l15pdk/nrf54l15/cpuapp/ns 34 | harness: console 35 | harness_config: 36 | type: multi_line 37 | regex: 38 | - ".*Example finished successfully!.*" 39 | integration_platforms: 40 | - nrf54l15pdk/nrf54l15/cpuapp 41 | - nrf54l15pdk/nrf54l15/cpuapp/ns 42 | -------------------------------------------------------------------------------- /crypto/psa_csr/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #ifdef CONFIG_BUILD_WITH_TFM 22 | #include 23 | #endif 24 | 25 | #define APP_SUCCESS (0) 26 | #define APP_ERROR (-1) 27 | #define APP_SUCCESS_MESSAGE "Example finished successfully!" 28 | #define APP_ERROR_MESSAGE "Example exited with error!" 29 | 30 | #define PRINT_HEX(p_label, p_text, len)\ 31 | ({\ 32 | LOG_INF("---- %s (len: %u): ----", p_label, len);\ 33 | LOG_HEXDUMP_INF(p_text, len, "Content:");\ 34 | LOG_INF("---- %s end ----", p_label);\ 35 | }) 36 | 37 | LOG_MODULE_REGISTER(ecdsa, LOG_LEVEL_DBG); 38 | 39 | /* ====================================================================== */ 40 | /* Global variables/defines for the ECDSA example */ 41 | 42 | #define NRF_CRYPTO_EXAMPLE_ECDSA_TEXT_SIZE (100) 43 | 44 | #define NRF_CRYPTO_EXAMPLE_ECDSA_PUBLIC_KEY_SIZE (65) 45 | #define NRF_CRYPTO_EXAMPLE_ECDSA_SIGNATURE_SIZE (64) 46 | #define NRF_CRYPTO_EXAMPLE_ECDSA_HASH_SIZE (32) 47 | 48 | /* Below text is used as plaintext for signing/verification */ 49 | static uint8_t m_plain_text[NRF_CRYPTO_EXAMPLE_ECDSA_TEXT_SIZE] = { 50 | "Example string to demonstrate basic usage of ECDSA." 51 | }; 52 | 53 | static uint8_t m_pub_key[NRF_CRYPTO_EXAMPLE_ECDSA_PUBLIC_KEY_SIZE]; 54 | 55 | static uint8_t m_signature[NRF_CRYPTO_EXAMPLE_ECDSA_SIGNATURE_SIZE]; 56 | static uint8_t m_hash[NRF_CRYPTO_EXAMPLE_ECDSA_HASH_SIZE]; 57 | 58 | static psa_key_id_t keypair_id; 59 | static psa_key_id_t pub_key_id; 60 | 61 | static mbedtls_pk_context csr_pk_ctx; 62 | static mbedtls_x509write_csr x509_ctx; 63 | 64 | struct csr_json_struct { 65 | const char *CSR; 66 | }; 67 | 68 | static const struct json_obj_descr csr_json_descr[] = { 69 | JSON_OBJ_DESCR_PRIM(struct csr_json_struct, CSR, JSON_TOK_STRING) 70 | }; 71 | /* ====================================================================== */ 72 | 73 | int crypto_init(void) 74 | { 75 | psa_status_t status; 76 | 77 | /* Initialize PSA Crypto */ 78 | status = psa_crypto_init(); 79 | if (status != PSA_SUCCESS) { 80 | LOG_INF("psa_crypto_init failed! (Error: %d)", status); 81 | return APP_ERROR; 82 | } 83 | 84 | mbedtls_pk_init(&csr_pk_ctx); 85 | 86 | return APP_SUCCESS; 87 | } 88 | 89 | int crypto_finish(void) 90 | { 91 | psa_status_t status; 92 | 93 | /* Destroy the key handle */ 94 | status = psa_destroy_key(keypair_id); 95 | if (status != PSA_SUCCESS) { 96 | LOG_INF("psa_destroy_key failed! (Error: %d)", status); 97 | return APP_ERROR; 98 | } 99 | 100 | status = psa_destroy_key(pub_key_id); 101 | if (status != PSA_SUCCESS) { 102 | LOG_INF("psa_destroy_key failed! (Error: %d)", status); 103 | return APP_ERROR; 104 | } 105 | 106 | return APP_SUCCESS; 107 | } 108 | 109 | int generate_ecdsa_keypair(void) 110 | { 111 | psa_status_t status; 112 | size_t olen; 113 | 114 | LOG_INF("Generating random ECDSA keypair..."); 115 | 116 | /* Configure the key attributes */ 117 | psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; 118 | 119 | /* Configure the key attributes */ 120 | psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH); 121 | psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE); 122 | psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); 123 | psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); 124 | psa_set_key_bits(&key_attributes, 256); 125 | 126 | /* Generate a random keypair. The keypair is not exposed to the application, 127 | * we can use it to sign hashes. 128 | */ 129 | status = psa_generate_key(&key_attributes, &keypair_id); 130 | if (status != PSA_SUCCESS) { 131 | LOG_INF("psa_generate_key failed! (Error: %d)", status); 132 | return APP_ERROR; 133 | } 134 | 135 | /* Export the public key */ 136 | status = psa_export_public_key(keypair_id, m_pub_key, sizeof(m_pub_key), &olen); 137 | if (status != PSA_SUCCESS) { 138 | LOG_INF("psa_export_public_key failed! (Error: %d)", status); 139 | return APP_ERROR; 140 | } 141 | 142 | /* Reset key attributes and free any allocated resources. */ 143 | psa_reset_key_attributes(&key_attributes); 144 | 145 | return APP_SUCCESS; 146 | } 147 | 148 | int import_ecdsa_pub_key(void) 149 | { 150 | /* Configure the key attributes */ 151 | psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; 152 | psa_status_t status; 153 | 154 | /* Configure the key attributes */ 155 | psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH); 156 | psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE); 157 | psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); 158 | psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); 159 | psa_set_key_bits(&key_attributes, 256); 160 | 161 | status = psa_import_key(&key_attributes, m_pub_key, sizeof(m_pub_key), &pub_key_id); 162 | if (status != PSA_SUCCESS) { 163 | LOG_INF("psa_import_key failed! (Error: %d)", status); 164 | return APP_ERROR; 165 | } 166 | 167 | /* Reset key attributes and free any allocated resources. */ 168 | psa_reset_key_attributes(&key_attributes); 169 | 170 | return APP_SUCCESS; 171 | } 172 | 173 | int sign_message(void) 174 | { 175 | uint32_t output_len; 176 | psa_status_t status; 177 | 178 | LOG_INF("Signing a message using ECDSA..."); 179 | 180 | /* Compute the SHA256 hash*/ 181 | status = psa_hash_compute(PSA_ALG_SHA_256, 182 | m_plain_text, 183 | sizeof(m_plain_text), 184 | m_hash, 185 | sizeof(m_hash), 186 | &output_len); 187 | if (status != PSA_SUCCESS) { 188 | LOG_INF("psa_hash_compute failed! (Error: %d)", status); 189 | return APP_ERROR; 190 | } 191 | 192 | /* Sign the hash */ 193 | status = psa_sign_hash(keypair_id, 194 | PSA_ALG_ECDSA(PSA_ALG_SHA_256), 195 | m_hash, 196 | sizeof(m_hash), 197 | m_signature, 198 | sizeof(m_signature), 199 | &output_len); 200 | if (status != PSA_SUCCESS) { 201 | LOG_INF("psa_sign_hash failed! (Error: %d)", status); 202 | return APP_ERROR; 203 | } 204 | 205 | LOG_INF("Message signed successfully!"); 206 | PRINT_HEX("Plaintext", m_plain_text, sizeof(m_plain_text)); 207 | PRINT_HEX("SHA256 hash", m_hash, sizeof(m_hash)); 208 | PRINT_HEX("Signature", m_signature, sizeof(m_signature)); 209 | 210 | return APP_SUCCESS; 211 | } 212 | 213 | int verify_message(void) 214 | { 215 | psa_status_t status; 216 | 217 | LOG_INF("Verifying ECDSA signature..."); 218 | 219 | /* Verify the signature of the hash */ 220 | status = psa_verify_hash(pub_key_id, 221 | PSA_ALG_ECDSA(PSA_ALG_SHA_256), 222 | m_hash, 223 | sizeof(m_hash), 224 | m_signature, 225 | sizeof(m_signature)); 226 | if (status != PSA_SUCCESS) { 227 | LOG_INF("psa_verify_hash failed! (Error: %d)", status); 228 | return APP_ERROR; 229 | } 230 | 231 | LOG_INF("Signature verification was successful!"); 232 | 233 | return APP_SUCCESS; 234 | } 235 | 236 | /** 237 | * @brief PSA Random number generator wrapper for Mbed TLS 238 | */ 239 | static int psa_rng_for_mbedtls(void *p_rng, 240 | unsigned char *output, size_t output_len) 241 | { 242 | (void)p_rng; 243 | 244 | return psa_generate_random(output, output_len); 245 | } 246 | 247 | int certificate_signing_request(void){ 248 | int status = 0; 249 | 250 | unsigned char output_buf[2048]; 251 | unsigned char json_encoded_buf[2048]; 252 | 253 | struct csr_json_struct csr_json = { 254 | .CSR = output_buf 255 | }; 256 | 257 | mbedtls_x509write_csr req; 258 | 259 | LOG_INF("Setting up CSR..."); 260 | 261 | mbedtls_x509write_csr_init(&req); 262 | 263 | memset(output_buf, 0, sizeof(output_buf)); 264 | 265 | status = mbedtls_pk_setup_opaque(&csr_pk_ctx,keypair_id); 266 | if (status) { 267 | LOG_INF("mbedtls_pk_setup_opaque failed! (Error: %x)", status); 268 | return APP_ERROR; 269 | } 270 | mbedtls_x509write_csr_set_key(&x509_ctx, &csr_pk_ctx); 271 | 272 | LOG_INF("Adding EC key to PK container completed"); 273 | 274 | mbedtls_x509write_csr_set_key(&req, &csr_pk_ctx); 275 | 276 | mbedtls_x509write_csr_set_md_alg(&req, MBEDTLS_MD_SHA256); 277 | 278 | status = mbedtls_x509write_csr_set_subject_name(&req, "O=Linaro,CN=Device Certificate"); 279 | if (status != 0) { 280 | LOG_ERR("failed! mbedtls_x509write_csr_set_subject_name returned %d", status); 281 | return APP_ERROR; 282 | } 283 | 284 | LOG_INF("Create device Certificate Signing Request"); 285 | 286 | status = mbedtls_x509write_csr_pem(&req, output_buf, sizeof(output_buf), 287 | psa_rng_for_mbedtls, NULL); 288 | if (status < 0) { 289 | LOG_ERR("failed! mbedtls_x509write_csr_pem returned -0x%04x", 290 | (unsigned int) -status); 291 | return APP_ERROR; 292 | } 293 | 294 | LOG_INF("Create device Certificate Signing Request completed"); 295 | 296 | LOG_INF("Certificate Signing Request:\n"); 297 | 298 | printf("%s\n", output_buf); 299 | 300 | /* 301 | * 1.3. Encoding CSR as JSON 302 | */ 303 | LOG_INF("Encoding CSR as json"); 304 | 305 | status = json_obj_encode_buf(csr_json_descr, ARRAY_SIZE(csr_json_descr), 306 | &csr_json, json_encoded_buf, sizeof(json_encoded_buf)); 307 | 308 | if (status != 0) { 309 | LOG_ERR("failed! json_obj_encode_buf returned 0x%04x", status); 310 | return APP_ERROR; 311 | } 312 | 313 | LOG_INF("Encoding CSR as json completed"); 314 | 315 | LOG_INF("Certificate Signing Request in JSON:\n"); 316 | 317 | printk("%s\n", json_encoded_buf); 318 | 319 | return APP_SUCCESS; 320 | } 321 | 322 | int main(void) 323 | { 324 | int status; 325 | 326 | LOG_INF("Starting ECDSA example..."); 327 | 328 | status = crypto_init(); 329 | if (status != APP_SUCCESS) { 330 | LOG_INF(APP_ERROR_MESSAGE); 331 | return APP_ERROR; 332 | } 333 | 334 | status = generate_ecdsa_keypair(); 335 | if (status != APP_SUCCESS) { 336 | LOG_INF(APP_ERROR_MESSAGE); 337 | return APP_ERROR; 338 | } 339 | 340 | status = import_ecdsa_pub_key(); 341 | if (status != APP_SUCCESS) { 342 | LOG_INF(APP_ERROR_MESSAGE); 343 | return APP_ERROR; 344 | } 345 | 346 | status = sign_message(); 347 | if (status != APP_SUCCESS) { 348 | LOG_INF(APP_ERROR_MESSAGE); 349 | return APP_ERROR; 350 | } 351 | 352 | status = verify_message(); 353 | if (status != APP_SUCCESS) { 354 | LOG_INF(APP_ERROR_MESSAGE); 355 | return APP_ERROR; 356 | } 357 | 358 | status = certificate_signing_request(); 359 | if (status != APP_SUCCESS) { 360 | LOG_INF(APP_ERROR_MESSAGE); 361 | return APP_ERROR; 362 | } 363 | 364 | status = crypto_finish(); 365 | if (status != APP_SUCCESS) { 366 | LOG_INF(APP_ERROR_MESSAGE); 367 | return APP_ERROR; 368 | } 369 | 370 | LOG_INF(APP_SUCCESS_MESSAGE); 371 | 372 | return APP_SUCCESS; 373 | } 374 | -------------------------------------------------------------------------------- /lowlevel/eraseprotect/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /lowlevel/eraseprotect/README.md: -------------------------------------------------------------------------------- 1 | # ERASEPROTECT SAMPLE 2 | **DISCLAIMER: If you enable both APPROTECT and ERASEPROTECT at the same time without setting the internal ERASEPROTECT.DISABLE register in firmware, you will no longer be able to program the nRF5340! It will be Bricked!** 3 | 4 | ## As is 5 | This code/configuration is not thoroughly tested or qualified and should be considered provided “as-is”. Please test it with your application and let me know if you find any issues. 6 | 7 | # Error 8 | This sample do only work for the application core. 9 | The eraseprotect in this sample can be undone by recovering the network core. 10 | I have not added a fix for this yet. 11 | If you want me to speed up on the fix, create an issue# Error 12 | This sample do only work for the application core. 13 | The eraseprotect in this sample can be undone by recovering the network core. 14 | I have not added a fix for this yet. 15 | If you want me to speed up on the fix, create an issue. 16 | 17 | ## Versions 18 | - nRF Connect SDK: v2.0.1 19 | - nRF5340DK 20 | - Python 3 21 | - pynrfjprog 10.16.0 22 | 23 | ## Documentation 24 | [CTRL-AP - Control access port](https://infocenter.nordicsemi.com/topic/ps_nrf5340/ctrl-ap.html?cp=3_0_0_7_9) 25 | 26 | ## Preparation 27 | Change the snr numbers in the scripts to match the ID printed on the sticker on your DK, or found via: 28 | ``` 29 | nrfjprog --ids 30 | ``` 31 | 32 | ## Building and Running 33 | First, build and flash the code to a nRF5340DK. 34 | Add --recover option to undo a previous ERASEPROTECT. 35 | ``` 36 | west build -p -b nrf5340dk_nrf5340_cpuapp 37 | west flash --recover 38 | ``` 39 | 40 | The firmware will enable ERASEPROTECT on startup. 41 | Check the status from the [ERASEPROTECT.STATUS](https://infocenter.nordicsemi.com/topic/ps_nrf5340/ctrl-ap.html?cp=3_0_0_7_9_5_0_5#register.ERASEPROTECT.STATUS) register with a script: 42 | ``` 43 | python3 scripts/read_eraseprotect_status.py 44 | ``` 45 | 46 | To disable eraseprotect, the firmware has written a key to an internal [ERASEPROTECT.DISABLE](https://infocenter.nordicsemi.com/topic/ps_nrf5340/ctrl-ap.html?cp=3_0_0_7_9_6_5#unique_1767310017). Write the same key to another, different [ERASEPROTECT.DISABLE](https://infocenter.nordicsemi.com/topic/ps_nrf5340/ctrl-ap.html?cp=3_0_0_7_9_6_7#unique_1545884140) with the script: 47 | ``` 48 | python3 scripts/disable_eraseprotecy.py 49 | ``` 50 | 51 | ## Alternatives 52 | As long as APPROTECT is not enabled, you can disable the ERASEPROTECT by flashing with the --recover option, which will use the debugger to reset the chip. 53 | ERASEPROTECT can also be enabled by the debugger by running the script: 54 | ``` 55 | python3 scripts/enable_eraseprotect.py 56 | ``` 57 | 58 | ## Trusted Firmware-M 59 | This sample does not work with TF-M included (nrf5340dk_nrf5340_ns), since the registers used are secure, and the application is non-secure. 60 | To make it work with TF-M, you will have to make a secure service for setup of ERASEPROTECT. 61 | For hints on how this can be done, see [TF-M secure peripheral partion](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.1/nrf/samples/tfm/tfm_secure_peripheral/README.html) 62 | -------------------------------------------------------------------------------- /lowlevel/eraseprotect/prj.conf: -------------------------------------------------------------------------------- 1 | # nothing here 2 | -------------------------------------------------------------------------------- /lowlevel/eraseprotect/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Simple sample to show how to use the ERASEPROTECT feature for the nRF5340DK 3 | name: F5340 ERASEPROTECT sample 4 | -------------------------------------------------------------------------------- /lowlevel/eraseprotect/scripts/disable_eraseprotect.py: -------------------------------------------------------------------------------- 1 | from pynrfjprog import LowLevel 2 | from time import sleep 3 | # FILL IN YOUR INFO 4 | my_snr = 1050084572 5 | eraseprotect_key = 0x00000001 6 | target_cp = LowLevel.CoProcessor.CP_APPLICATION 7 | # FROM DATASHEET 8 | # CTRL-AP ID according to datasheet debug and trace (2 = app, 3 = net) 9 | ap_id = 2 if target_cp == LowLevel.CoProcessor.CP_APPLICATION else 3 10 | # CTRL-AP addr offsets. 11 | eraseprotect_disable_addr = 0x01C 12 | eraseall_status_addr = 0x008 13 | 14 | print("Start") 15 | with LowLevel.API("NRF53", log=True) as nrf: 16 | print("Connecting to debugger") 17 | nrf.connect_to_emu_with_snr(my_snr) 18 | 19 | # Write values 20 | nrf.write_access_port_register(ap_id, eraseprotect_disable_addr, eraseprotect_key) 21 | 22 | print("Wait for eraseall to be finished") 23 | finished_writing = False 24 | counter = 0 25 | while( nrf.read_access_port_register(ap_id, eraseall_status_addr) == True): 26 | counter+=1 27 | print(".",end="") 28 | sleep(0.01) 29 | if(counter == 0): 30 | print("Failed to disable eraseprotect. Try to reset nRF5340DK and run this script again.") 31 | else: 32 | print("\nDone. Run read_eraseprotect_status.py to test.") 33 | -------------------------------------------------------------------------------- /lowlevel/eraseprotect/scripts/enable_eraseprotect.py: -------------------------------------------------------------------------------- 1 | from pynrfjprog import LowLevel 2 | # FILL IN YOUR INFO 3 | my_snr = 1050084572 4 | target_cp = LowLevel.CoProcessor.CP_APPLICATION 5 | print("Start") 6 | with LowLevel.API("NRF53", log=True) as nrf: 7 | print("Connecting to debugger") 8 | nrf.connect_to_emu_with_snr(my_snr) 9 | # Connect debugger to nrf device and select target processor 10 | nrf.connect_to_device() 11 | nrf.enable_coprocessor(target_cp) 12 | nrf.select_coprocessor(target_cp) 13 | # Enable eraseprotect 14 | nrf.enable_eraseprotect() 15 | print("Done") 16 | -------------------------------------------------------------------------------- /lowlevel/eraseprotect/scripts/read_eraseprotect_status.py: -------------------------------------------------------------------------------- 1 | from pynrfjprog import LowLevel 2 | # FILL IN YOUR INFO 3 | my_snr = 1050084572 4 | target_cp = LowLevel.CoProcessor.CP_APPLICATION 5 | # FROM DATASHEET 6 | # CTRL-AP ID according to datasheet debug and trace (2 = app, 3 = net) 7 | ap_id = 2 if target_cp == LowLevel.CoProcessor.CP_APPLICATION else 3 8 | # CTRL-AP addr offsets. 9 | eraseprotect_status_addr = 0x018 10 | 11 | print("Start") 12 | with LowLevel.API("NRF53", log=True) as nrf: 13 | print("Connecting to debugger") 14 | nrf.connect_to_emu_with_snr(my_snr) 15 | # Write values 16 | status = nrf.read_access_port_register(ap_id, eraseprotect_status_addr) 17 | print("ERASEPROTECT.STATUS: ", status) 18 | -------------------------------------------------------------------------------- /lowlevel/eraseprotect/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | static void config_nvmc(uint32_t val) 11 | { 12 | while (!NRF_NVMC_S->READY); 13 | NRF_NVMC_S->CONFIG = val; 14 | while (!NRF_NVMC_S->READY); 15 | } 16 | 17 | void main(void) 18 | { 19 | uint32_t read_val; 20 | 21 | printk("Start eraseprotect sample.\n"); 22 | NRF_CTRLAP_S->ERASEPROTECT.DISABLE = 0x00000001; 23 | // Somehow, reading the value back does not work. 24 | // printk("NRF_CTRLAP_S->ERASEPROTECT.DISABLE: %08x\n",NRF_CTRLAP_S->ERASEPROTECT.DISABLE); 25 | 26 | if(NRF_UICR_S->ERASEPROTECT){ 27 | config_nvmc(NVMC_CONFIG_WEN_Wen); 28 | NRF_UICR_S->ERASEPROTECT=0x00000000; 29 | config_nvmc(NVMC_CONFIG_WEN_Ren); 30 | NVIC_SystemReset(); 31 | } 32 | 33 | printk("Entering forever loop.\n"); 34 | printk("Disclaimer: This example does not lock netcore, and can be unlocked by recovering netcore!\n See README for more information.\n"); 35 | while(1){ 36 | k_sleep(K_SECONDS(1)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lowlevel/uicr_write_customer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /lowlevel/uicr_write_customer/README.md: -------------------------------------------------------------------------------- 1 | ## CUSTOMER 2 | Here is an example on how to write to the CUSTOMER register in UICR 3 | Tested for the nRF52840. 4 | 5 | Docs: https://docs.nordicsemi.com/bundle/ncs-latest/page/nrfx/drivers/nvmc/driver.html 6 | 7 | Newer chips have The OTP register instead of this. 8 | -------------------------------------------------------------------------------- /lowlevel/uicr_write_customer/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_NRFX_NVMC=y 2 | -------------------------------------------------------------------------------- /lowlevel/uicr_write_customer/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define CUSTOMER0_TEST_DATA ((uint32_t)0x12345678) 5 | 6 | int main(void) 7 | { 8 | printk("CUSTOMER0 before: %x\n",(uint32_t)NRF_UICR->CUSTOMER[0]); 9 | bool is_writable = nrfx_nvmc_word_writable_check((uint32_t)&NRF_UICR->CUSTOMER[0],CUSTOMER0_TEST_DATA); 10 | 11 | if(is_writable){ 12 | nrfx_nvmc_word_write((uint32_t)&NRF_UICR->CUSTOMER[0],CUSTOMER0_TEST_DATA); 13 | printk("Written\n"); 14 | } else { 15 | printk("Not written\n"); 16 | } 17 | 18 | printk("CUSTOMER0 after: %x\n",(uint32_t)NRF_UICR->CUSTOMER[0]); 19 | 20 | 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/commissioner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/commissioner/README.md: -------------------------------------------------------------------------------- 1 | # Commissioner for Autojoin sample 2 | The commissioner needs to be set up manually. 3 | This can either be done in code or by using the cli. 4 | For now, this sample use the cli. 5 | Use the following commands to start the commisioner: 6 | ``` 7 | ot commissioner start 8 | ot commissioner joiner add * J01NU5 9 | ``` 10 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/commissioner/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2020 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # Network shell 8 | CONFIG_SHELL=y 9 | CONFIG_OPENTHREAD_SHELL=y 10 | CONFIG_SHELL_ARGC_MAX=26 11 | CONFIG_SHELL_CMD_BUFF_SIZE=416 12 | 13 | # Enable OpenThread features set 14 | CONFIG_OPENTHREAD_NORDIC_LIBRARY_FTD=y 15 | CONFIG_NET_L2_OPENTHREAD=y 16 | 17 | # Generic networking options 18 | CONFIG_NETWORKING=y 19 | 20 | CONFIG_OPENTHREAD_MANUAL_START=n 21 | CONFIG_OPENTHREAD_COMMISSIONER=y 22 | 23 | #CONFIG_LOG=y 24 | #CONFIG_OPENTHREAD_LOG_LEVEL_DEBG=y 25 | #CONFIG_OPENTHREAD_DEBUG=y 26 | #CONFIG_LOG_STRDUP_BUF_COUNT=24 27 | #CONFIG_LOG_STRDUP_MAX_STRING=128 28 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/commissioner/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/commissioner/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | void main(void) 11 | { 12 | printk("Hello World! %s\n", CONFIG_BOARD); 13 | } 14 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/joiner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/joiner/README.rst: -------------------------------------------------------------------------------- 1 | Automatic Joiner 2 | ########### 3 | nRF Connect SDK v1.9.1 4 | This sample should automatically join a comissioner which has the joiner PSKD "J01NU5". 5 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/joiner/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2020 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # Network shell 8 | CONFIG_SHELL=y 9 | CONFIG_OPENTHREAD_SHELL=y 10 | CONFIG_SHELL_ARGC_MAX=26 11 | CONFIG_SHELL_CMD_BUFF_SIZE=416 12 | 13 | # Enable OpenThread features set 14 | CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y 15 | CONFIG_NET_L2_OPENTHREAD=y 16 | 17 | # Generic networking options 18 | CONFIG_NETWORKING=y 19 | 20 | CONFIG_OPENTHREAD_JOINER=y 21 | CONFIG_OPENTHREAD_JOINER_AUTOSTART=y 22 | CONFIG_OPENTHREAD_JOINER_PSKD="J01NU5" 23 | CONFIG_OPENTHREAD_MANUAL_START=n 24 | 25 | #CONFIG_LOG=y 26 | #CONFIG_OPENTHREAD_LOG_LEVEL_WARN=y 27 | #CONFIG_OPENTHREAD_DEBUG=y 28 | #CONFIG_LOG_STRDUP_BUF_COUNT=8 29 | #CONFIG_LOG_STRDUP_MAX_STRING=128 30 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/joiner/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /openthread_samples/autojoin/joiner/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | void main(void) 11 | { 12 | printk("Hello World! %s\n", CONFIG_BOARD); 13 | } 14 | -------------------------------------------------------------------------------- /peripherals/lpcomp_system_off/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /peripherals/lpcomp_system_off/app.overlay: -------------------------------------------------------------------------------- 1 | / { 2 | aliases { 3 | test-comp = ∁ 4 | }; 5 | }; 6 | 7 | &comp { 8 | compatible = "nordic,nrf-lpcomp"; 9 | psel = "AIN4"; /* P0.28 for 52840DK */ 10 | refsel = "VDD_4_8"; /* This is the start value. 11 | We will reconfiger in main.c */ 12 | status = "okay"; 13 | enable-hyst; 14 | }; 15 | -------------------------------------------------------------------------------- /peripherals/lpcomp_system_off/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_COMPARATOR=y 2 | CONFIG_NRFX_LPCOMP=y 3 | CONFIG_GPIO=y 4 | CONFIG_PRINTK=y 5 | CONFIG_LOG=y 6 | CONFIG_LOG_MODE_IMMEDIATE=y 7 | 8 | CONFIG_POWEROFF=y 9 | CONFIG_PM_DEVICE=y 10 | -------------------------------------------------------------------------------- /peripherals/lpcomp_system_off/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | LOG_MODULE_REGISTER(comp_app, LOG_LEVEL_INF); 9 | 10 | 11 | static int poweroff = false; 12 | 13 | static const struct device *comp_dev = DEVICE_DT_GET(DT_ALIAS(test_comp)); 14 | 15 | enum comp_state { 16 | WAITING_FOR_VOLT_HIGH, 17 | WAITING_FOR_VOLT_LOW, 18 | }; 19 | 20 | #define LPCOMP_INPUT_CHANNEL NRF_LPCOMP_INPUT_4 21 | 22 | static nrfx_lpcomp_config_t config_volt_high = { 23 | .reference = NRF_LPCOMP_REF_SUPPLY_7_8, 24 | .detection = NRF_LPCOMP_DETECT_UP, 25 | #if NRF_LPCOMP_HAS_HYST 26 | .hyst = NRF_LPCOMP_HYST_ENABLED, 27 | #endif 28 | .input = LPCOMP_INPUT_CHANNEL, 29 | .interrupt_priority = 6, 30 | }; 31 | 32 | static nrfx_lpcomp_config_t config_volt_low = { 33 | .reference = NRF_LPCOMP_REF_SUPPLY_4_8, 34 | .detection = NRF_LPCOMP_DETECT_DOWN, 35 | #if NRF_LPCOMP_HAS_HYST 36 | .hyst = NRF_LPCOMP_HYST_ENABLED, 37 | #endif 38 | .input = LPCOMP_INPUT_CHANNEL, 39 | .interrupt_priority = 6, 40 | }; 41 | 42 | static enum comp_state current_state = WAITING_FOR_VOLT_LOW; 43 | 44 | static void comp_callback(const struct device *dev, void *user_data) 45 | { 46 | nrfx_err_t err = NRFX_SUCCESS; 47 | ARG_UNUSED(dev); 48 | ARG_UNUSED(user_data); 49 | 50 | int output = comparator_get_output(comp_dev); 51 | 52 | if (current_state == WAITING_FOR_VOLT_HIGH && output == 0) { 53 | 54 | poweroff = false; 55 | LOG_INF("Voltage above VDD * 7/8"); 56 | 57 | current_state = WAITING_FOR_VOLT_LOW; 58 | nrfx_lpcomp_stop(); 59 | err = nrfx_lpcomp_reconfigure(&config_volt_low); 60 | nrfx_lpcomp_start(NRF_LPCOMP_INT_UP_MASK,0); 61 | } else if (current_state == WAITING_FOR_VOLT_LOW && output == 1) { 62 | 63 | LOG_INF("Voltage below VDD * 4/8"); 64 | poweroff = true; 65 | 66 | current_state = WAITING_FOR_VOLT_HIGH; 67 | nrfx_lpcomp_stop(); 68 | err = nrfx_lpcomp_reconfigure(&config_volt_high); 69 | nrfx_lpcomp_start(NRF_LPCOMP_INT_DOWN_MASK,0); 70 | } 71 | 72 | if(err != NRFX_SUCCESS ) { 73 | LOG_ERR("lpcomp reconfigure error: %d",err); 74 | } 75 | } 76 | 77 | int main(void) 78 | { 79 | 80 | if (!device_is_ready(comp_dev)) { 81 | LOG_ERR("Comparator device not ready"); 82 | } 83 | 84 | if (comparator_set_trigger_callback(comp_dev, comp_callback, NULL) != 0) { 85 | LOG_ERR("Failed to set comparator callback"); 86 | } 87 | 88 | if (comparator_set_trigger(comp_dev, COMPARATOR_TRIGGER_RISING_EDGE) != 0) { 89 | LOG_ERR("Failed to set rising edge trigger"); 90 | } 91 | 92 | LOG_INF("Comparator started; waiting for voltage events..."); 93 | 94 | while (1) { 95 | k_sleep(K_MSEC(5000)); 96 | LOG_INF("Main loop"); 97 | 98 | if(poweroff) { 99 | sys_poweroff(); 100 | } 101 | } 102 | return 1; 103 | } 104 | --------------------------------------------------------------------------------