I am using the nRF52840-dk with the nRF Connect SDK v2.0.0 and for the development itself I use Visual Studio Code.
My Goal: Both the bootloader and the actual application should be upgradeable, with firmware updates stored on an external flash. Supposedly this should be possible.
The firmware is stored in the external flash via specially developed methods. Afterwards the bootloader should detect these firmware updates in the external flash and copy/swap them to the internal flash.
According to the documentation I need the nRF Secure Immutable Bootloader and MCUboot as a second stage bootloader.
This actual bootloader chain works fine so far even with my own private keys.
Currently I am getting the following output with my configuration:
*** Booting Zephyr OS build v3.0.99-ncs1 *** Attempting to boot slot 0. Attempting to boot from address 0x9200. Verifying signature against key 0. Hash: 0xea...6a Firmware signature verified. Firmware version 1 Setting monotonic counter (version: 1, slot: 0) *** Booting Zephyr OS build v3.0.99-ncs1 *** I: Starting bootloader I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 I: Boot source: none I: Swap type: none I: Primary image: magic=bad, swap_type=0x2, copy_done=0x2, image_ok=0x2 I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 I: Boot source: none I: Swap type: none I: Bootloader chainload address offset: 0x23000 ▒*** Booting Zephyr OS build v3.0.99-ncs1 *** [00:0Bluetooth initialized
I do not understand the output of MCUboot at all. Why do two passes take place? Why is magic from the primary image suddenly bad on the second pass, but loads the firmware anyway?
I can change the version number of MCUboot. This is also shown correctly by the first bootloader.
But that's it. I can't get it to recognize the firmware updates.
MCUboot doesn't seem to make any attempt at all to read anything from the external flash. Well I don't know. The bootloader doesn't give any further relevant information, even if I adjust the log level.
For now, I'd be happy to at least have MCUboot upgradeable.
The following already works:
The firmware update is in the right position in the external flash. For testing purposes at offset 0x0.
As the firmware update for MCUboot I use the file "signed_by_b0_s0_image.bin" from the "build/zephyr" directory. If I open this binary
I see the first 0x200 bytes with some meta information. See here:
$ head --bytes=$((16#200)) signed_by_b0_s0_image.bin | xxd 00000000: c05d 0020 5dbc 0000 1907 0100 31bc 0000 .]. ].......1... 00000010: 31bc 0000 31bc 0000 31bc 0000 0000 0000 1...1...1....... 00000020: 0000 0000 0000 0000 0000 0000 69b7 0000 ............i... 00000030: 31bc 0000 0000 0000 15b7 0000 31bc 0000 1...........1... 00000040: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 00000050: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 00000060: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 00000070: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 00000080: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 00000090: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 000000a0: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 000000b0: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 000000c0: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 000000d0: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 000000e0: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 000000f0: 19b8 0000 19b8 0000 19b8 0000 19b8 0000 ................ 00000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000110: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000120: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000130: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000140: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000150: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000160: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000170: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000180: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000190: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000001a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000001b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000001c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000001d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000001f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
My expectation would be: Since it is signed_by_b0_s0_image.bin, which is (presumably) a valid MCUboot firmware, the bootloader would have to output some message and validate the update or do something else. But I don't see anything of that.
Below I list the most important configurations I use. These are mainly for the current development.
And yes, due to days of desperate attempts, the configuration files are now very messy.
pm_static.yml (originally taken from a sample project - but couldn't even be built in the first place)
external_flash: address: 0x000000 region: external_flash size: 0x0 device: MX25R64 mcuboot_secondary: address: 0x00000 device: MX25R64 region: external_flash size: 0xdb000 rest_storage: address: 0xdb000 size: 0x725000 device: MX25R64 region: external_flash
nrf52840dk_nrf52840.overlay:
/ { chosen { nordic,pm-ext-flash = &mx25r64; }; };
The generated partitions.yml:
EMPTY_0: address: 0x15200 end_address: 0x16000 placement: before: - s1_pad region: flash_primary size: 0xe00 EMPTY_1: address: 0x22200 end_address: 0x23000 placement: before: - mcuboot_pad region: flash_primary size: 0xe00 app: address: 0x23200 end_address: 0xfe000 region: flash_primary size: 0xdae00 app_image: address: 0x23200 end_address: 0xfe000 orig_span: &id001 - app region: flash_primary size: 0xdae00 span: *id001 b0: address: 0x0 end_address: 0x8000 placement: after: - start region: flash_primary size: 0x8000 b0_container: address: 0x0 end_address: 0x9000 orig_span: &id002 - b0 - provision region: flash_primary size: 0x9000 span: *id002 external_flash: address: 0x0 device: MX25R64 end_address: 0x0 region: external_flash size: 0x0 mcuboot: address: 0x9200 end_address: 0x15200 placement: before: - mcuboot_primary region: flash_primary sharers: 0x1 size: 0xc000 mcuboot_pad: address: 0x23000 end_address: 0x23200 placement: align: start: 0x1000 before: - mcuboot_primary_app region: flash_primary sharers: 0x2 size: 0x200 mcuboot_primary: address: 0x23000 end_address: 0xfe000 orig_span: &id003 - mcuboot_pad - app region: flash_primary size: 0xdb000 span: *id003 mcuboot_primary_app: address: 0x23200 end_address: 0xfe000 orig_span: &id004 - app region: flash_primary size: 0xdae00 span: *id004 mcuboot_secondary: address: 0x0 device: MX25R64 end_address: 0xdb000 region: external_flash size: 0xdb000 provision: address: 0x8000 end_address: 0x9000 placement: after: - b0 align: start: 0x1000 region: flash_primary size: 0x1000 rest_storage: address: 0xdb000 device: MX25R64 end_address: 0x800000 region: external_flash size: 0x725000 s0: address: 0x9000 end_address: 0x15200 orig_span: &id005 - mcuboot - s0_pad region: flash_primary size: 0xc200 span: *id005 s0_image: address: 0x9200 end_address: 0x15200 orig_span: &id006 - mcuboot region: flash_primary size: 0xc000 span: *id006 s0_pad: address: 0x9000 end_address: 0x9200 placement: after: - b0_container align: start: 0x1000 region: flash_primary share_size: - mcuboot_pad size: 0x200 s1: address: 0x16000 end_address: 0x22200 orig_span: &id007 - s1_pad - s1_image region: flash_primary size: 0xc200 span: *id007 s1_image: address: 0x16200 end_address: 0x22200 placement: after: - s1_pad - s0 region: flash_primary share_size: - mcuboot size: 0xc000 s1_pad: address: 0x16000 end_address: 0x16200 placement: after: - s0 align: start: 0x1000 region: flash_primary share_size: - mcuboot_pad size: 0x200 settings_storage: address: 0xfe000 end_address: 0x100000 placement: before: - end region: flash_primary size: 0x2000 sram_primary: address: 0x20000000 end_address: 0x20040000 region: sram_primary size: 0x40000
prj.conf
CONFIG_NEWLIB_LIBC=y CONFIG_CPLUSPLUS=y CONFIG_STD_CPP2A=y CONFIG_LIB_CPLUSPLUS=y CONFIG_NEWLIB_LIBC_NANO=y CONFIG_EXCEPTIONS=y CONFIG_SENSOR=y CONFIG_TEMP_NRF5=y CONFIG_NRFX_TEMP=y CONFIG_STDOUT_CONSOLE=y CONFIG_FLASH=y CONFIG_I2C=n CONFIG_SPI=y CONFIG_NORDIC_QSPI_NOR=y CONFIG_SPI_SLAVE=n CONFIG_SPI_NRFX=y CONFIG_SPI_ASYNC=y CONFIG_NRFX_SPIS0=y CONFIG_GPIO=y CONFIG_SPI_0_NRF_ORC=0x80 CONFIG_THREAD_STACK_INFO=y CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 CONFIG_MAIN_STACK_SIZE=4096 CONFIG_BT_RX_STACK_SIZE=4096 CONFIG_BT_GATT_AUTO_SEC_REQ=n CONFIG_BT=y CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_EXT_ADV=y CONFIG_BT_PER_ADV=y CONFIG_BT_DEBUG_LOG=y CONFIG_BT_DEBUG_SMP=y CONFIG_BT_DIS=y CONFIG_BT_ATT_PREPARE_COUNT=5 CONFIG_BT_PRIVACY=n CONFIG_BT_DEVICE_NAME="MyName" CONFIG_BT_DEVICE_APPEARANCE=833 CONFIG_BT_DEVICE_NAME_DYNAMIC=y CONFIG_BT_DEVICE_NAME_MAX=65 CONFIG_BT_SMP_ENFORCE_MITM=y CONFIG_BT_GATT_DYNAMIC_DB=y CONFIG_BT_BUF_ACL_RX_SIZE=517 CONFIG_BT_L2CAP_TX_MTU=517 CONFIG_BT_BUF_ACL_TX_SIZE=517 CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 CONFIG_BT_KEYS_OVERWRITE_OLDEST=y CONFIG_BT_SETTINGS=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y CONFIG_LZ4=y CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_SMF=y CONFIG_DEBUG_THREAD_INFO=y CONFIG_DEBUG_OPTIMIZATIONS=y CONFIG_DEBUG_INFO=y CONFIG_BT_EXT_ADV_MAX_ADV_SET=2 CONFIG_BT_MAX_CONN=10 CONFIG_ASSERT=n CONFIG_NORDIC_QSPI_NOR=y CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 CONFIG_STDOUT_CONSOLE=y CONFIG_FPU=y CONFIG_FPU_SHARING=y CONFIG_DEBUG_THREAD_INFO=y CONFIG_DEBUG_OPTIMIZATIONS=y CONFIG_DEBUG_INFO=y CONFIG_NRFX_NVMC=y CONFIG_FW_INFO=y CONFIG_FW_INFO_OFFSET=0x200 CONFIG_SECURE_BOOT=y CONFIG_DISABLE_FLASH_PATCH=y CONFIG_BOOTLOADER_MCUBOOT=y CONFIG_MCUBOOT_IMAGE_VERSION="1.1.1+1" CONFIG_SB_SIGNING_KEY_FILE="private.pem" CONFIG_SB_SIGNING_PUBLIC_KEY="public.pem" CONFIG_TIMING_FUNCTIONS=y CONFIG_DISABLE_FLASH_PATCH=y CONFIG_BOOT_BANNER=y CONFIG_IMG_MANAGER=y CONFIG_MCUBOOT_IMG_MANAGER=y CONFIG_UPDATEABLE_IMAGE_NUMBER=1 CONFIG_PM_EXTERNAL_FLASH_BASE=0x0 CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y CONFIG_DFU_TARGET_MCUBOOT=y
child_image/b0.conf:
CONFIG_IS_SECURE_BOOTLOADER=y CONFIG_MULTITHREADING=n CONFIG_GPIO=n CONFIG_ARM_MPU=n CONFIG_PM=n CONFIG_TICKLESS_KERNEL=n CONFIG_ERRNO=n CONFIG_FPROTECT=y CONFIG_SECURE_BOOT_CRYPTO=y CONFIG_SECURE_BOOT_DEBUG=y CONFIG_SECURE_BOOT_VALIDATION=y CONFIG_SECURE_BOOT_STORAGE=y CONFIG_BL_ROT_VERIFY_EXT_API_ENABLED=y CONFIG_BL_SHA256_EXT_API_ENABLED=y CONFIG_BL_SECP256R1_EXT_API_ENABLED=y CONFIG_BL_VALIDATE_FW_EXT_API_ENABLED=y CONFIG_EXT_API_PROVIDE_EXT_API_ENABLED=y CONFIG_NRFX_NVMC=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_TIMEOUT_64BIT=n CONFIG_ASSERT=n CONFIG_NRF_RTC_TIMER=n CONFIG_FW_INFO=y CONFIG_PM_EXTERNAL_FLASH_BASE=0x0
child_image/mcuboot.conf:
CONFIG_PM=n CONFIG_MAIN_STACK_SIZE=10240 CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" CONFIG_BOOT_SWAP_SAVE_ENCTLV=n CONFIG_BOOT_ENCRYPT_RSA=n CONFIG_BOOT_ENCRYPT_EC256=n CONFIG_BOOT_ENCRYPT_X25519=n CONFIG_BOOT_UPGRADE_ONLY=n CONFIG_MCUBOOT_DOWNGRADE_PREVENTION=n CONFIG_BOOT_BOOTSTRAP=n CONFIG_FLASH=y CONFIG_FPROTECT=y CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y # former CONFIG_MODE_MINIMAL CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_CBPRINTF_NANO=y CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y CONFIG_BOOT_NRF_EXTERNAL_CRYPTO=y CONFIG_SECURE_BOOT_CRYPTO=y CONFIG_SB_CRYPTO_CLIENT_ECDSA_SECP256R1=y CONFIG_SB_CRYPTO_CLIENT_SHA256=y CONFIG_BL_SHA256_EXT_API_REQUIRED=y CONFIG_BL_SECP256R1_EXT_API_REQUIRED=y CONFIG_EXT_API_PROVIDE_EXT_API_ATLEAST_OPTIONAL=y CONFIG_BOOT_SIGNATURE_KEY_FILE="private.pem" CONFIG_FW_INFO_FIRMWARE_VERSION=1 CONFIG_NORDIC_QSPI_NOR=y CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 CONFIG_MULTITHREADING=y CONFIG_BOOT_MAX_IMG_SECTORS=256 CONFIG_IMG_MANAGER=y CONFIG_UPDATEABLE_IMAGE_NUMBER=1 CONFIG_SIZE_OPTIMIZATIONS=y CONFIG_PM_EXTERNAL_FLASH_BASE=0x0 CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y CONFIG_DEBUG_INFO=y CONFIG_BOOT_SWAP_USING_MOVE=y CONFIG_DFU_TARGET=y CONFIG_DEBUG=y CONFIG_LOG_OVERRIDE_LEVEL=4