This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

FOTA with External Memory using Zephyr/NCS

Hello,

I am using the nrf52840dk_nrf52840 with NCS v1.7.0. I am trying to use the external memory (MX25R64) to host the mcuboot_secondary slot. Then, the primary slot could be twice as large and FOTA would still happen correctly using that external memory.

I went through a bunch of documentation and similar thread but I still cannot figure out what I am doing wrong.

So, I started from the external_flash test in "nrf\tests\modules\mcuboot\external_flash". I then added what make sense until I ended up with:

  • boards/nrf52840dk_nrf52840.overlay:

/ {
	chosen {
		nordic,pm-ext-flash = &mx25r64;
	};
};

  • child_image/mcuboot.conf

# MCUboot requires a large stack size, otherwise an MPU fault will occur
CONFIG_MAIN_STACK_SIZE=10240

# Set the size here so that the size of MCUBOOT_SECONDARY won't change
# if the default value changes.
CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x20000

CONFIG_DEBUG_OPTIMIZATIONS=y

# Enable flash operations
CONFIG_FLASH=y

# This value must match the size of the MCUboot primary partition.
CONFIG_PM_PARTITION_SIZE_MCUBOOT_SECONDARY=0xe0000

# This must be increased to accommodate the bigger images.
CONFIG_BOOT_MAX_IMG_SECTORS=256

# Enable serial recovery
CONFIG_UART_CONSOLE=n
CONFIG_CONSOLE_HANDLER=n
CONFIG_MCUBOOT_SERIAL=y
CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y

CONFIG_NORDIC_QSPI_NOR=y
CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16

  • src/main.c: It just registers the os_mgmt and img_mgmt group, then initialize ble and register smp.
  • CMakeLists.txt

# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.13.1)
set(BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})

set(mcuboot_DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD}.overlay")

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(peripheral_hr)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE
  ${app_sources}
  )

zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth)

  • prj.conf

# Deactivate DEBUG/LOG for production builds
CONFIG_SERIAL=y
# Logging
CONFIG_LOG=y
CONFIG_UART_CONSOLE=y

#### BLE ####
# Activate the BLE layer, set as peripheral
CONFIG_BT=y
CONFIG_BT_SMP=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CTLR=y
CONFIG_BT_CTLR_PHY_2M=y
CONFIG_BT_GATT_CLIENT=y
# Set up the Services
CONFIG_BT_DIS=y
CONFIG_BT_DIS_PNP=n

# Allow another device that unpaired to pair again
CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE=y

#### FLASH ####
# Configure stack size for process
CONFIG_MAIN_STACK_SIZE=8192
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192

##### MCUBOOT #####
# Enable mcumgr. #Turn to y if BOOTLOADER
CONFIG_MCUMGR=y
# Ensure an MCUboot-compatible binary is generated. MCUboot is the upgradable bootloader. #Turn to y if BOOTLOADER
CONFIG_BOOTLOADER_MCUBOOT=y
# Enable most core commands. #Turn to y if BOOTLOADER
CONFIG_MCUMGR_CMD_IMG_MGMT=y
CONFIG_MCUMGR_CMD_OS_MGMT=y
# Enable the Bluetooth (unauthenticated) mcumgr transports. #Turn to y if BOOTLOADER
CONFIG_MCUMGR_SMP_BT=y
CONFIG_MCUMGR_SMP_BT_AUTHEN=n
# Generate a confirmed image directly
CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE=y

# This value must match the size of the MCUboot primary partition
CONFIG_PM_PARTITION_SIZE_MCUBOOT_SECONDARY=0xf0000

# Enable flash operations
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_NORDIC_QSPI_NOR=y
CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=4

What happens is that when I try to test and confirm a new .bin, nothing happens. The serial line just shows this line: "<inf> mcuboot_util: Swap type: none". Digging deeper, it seems that this function poses problem (in bootloader/mcuboot/boot/bootutil/src/bootutil_public.c):

int
boot_magic_compatible_check(uint8_t tbl_val, uint8_t val)
{
    BOOT_LOG_INF("Magic combatibility check: tbl_val = %d, val = %d", tbl_val, val);

    switch (tbl_val) {
    case BOOT_MAGIC_ANY:
        return 1;

    case BOOT_MAGIC_NOTGOOD:
        return val != BOOT_MAGIC_GOOD;

    default:
        return tbl_val == val;
    }
}

I added the log and it showed this: 

<inf> mcuboot_util: Magic combatibility check: tbl_val = 4, val = 3
<inf> mcuboot_util: Magic combatibility check: tbl_val = 1, val = 3
<inf> mcuboot_util: Magic combatibility check: tbl_val = 4, val = 3
<inf> mcuboot_util: Magic combatibility check: tbl_val = 1, val = 3
<inf> mcuboot_util: Magic combatibility check: tbl_val = 1, val = 3

Looking at the build/partition.yml, I have this:

app:
  address: 0x20200
  end_address: 0x100000
  region: flash_primary
  size: 0xdfe00
external_flash:
  address: 0xe0000
  end_address: 0x800000
  region: external_flash
  size: 0x720000
mcuboot:
  address: 0x0
  end_address: 0x20000
  placement:
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0x20000
mcuboot_pad:
  address: 0x20000
  end_address: 0x20200
  placement:
    align:
      start: 0x1000
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0x20000
  end_address: 0x100000
  orig_span: &id001
  - mcuboot_pad
  - app
  region: flash_primary
  size: 0xe0000
  span: *id001
mcuboot_primary_app:
  address: 0x20200
  end_address: 0x100000
  orig_span: &id002
  - app
  region: flash_primary
  size: 0xdfe00
  span: *id002
mcuboot_secondary:
  address: 0x0
  device: MX25R64
  end_address: 0xe0000
  placement:
    align:
      start: 0x4
  region: external_flash
  size: 0xe0000
sram_primary:
  address: 0x20000000
  end_address: 0x20040000
  region: sram_primary
  size: 0x40000

This seems to make sense to me but then again I am not sure. 

So, my question is what am I doing wrong?

I will be grateful for any help. You will find that sample attached. Whenever it ends up working, I'll link an updated sample.fota_external_flash_spi.zip

Related