MCUboot warnings + app errors when using external flash

Disclaimer: I'm new to both Nordic SDK and Zephyr in general so apologize in advance for glaring mistakes

Using SDK v2.1.2
Trying to implement OTA DFU functionality, hence need bootloader.
Using MCUboot (version enclosed with SDK) for that purpose.
My Zephyr-based app image is too large (>250KB) to fit twice in the internal flash of nRF52833 (512KB), so I have to place secondary partition in external SPI-connected NOR flash (Winbond W25Q80DV).

I managed to build both mcuboot and app, but when I load merged file, I get a warning from MCUBoot.

** Booting Zephyr OS build v3.1.99-ncs1-1 ***
I: Starting bootloader
W: Failed reading sectors; BOOT_MAX_IMG_SECTORS=128 - too small?
W: Cannot upgrade: not a compatible amount of sectors
I: Bootloader chainload address offset: 0x10000
*** Booting Zephyr OS build v3.1.99-ncs1-1 ***
Starting app...

Upon further inspection, the chain of errors is as following:
boot_initialize_area --> flash_area_get_sectors--> flash_area_layout --> flash_area_open --> get_flash_area_from_id 

static inline struct flash_area const *get_flash_area_from_id(int idx)
{
    for (int i = 0; i < flash_map_entries; i++) {
        if (flash_map[i].fa_id == idx) {
            return &flash_map[i];
        }
    }

    return NULL; <----------------------
}

After the warnings, MCUboot proceeds to load the app, but app misbehaves, which it doesn't do when loaded standalone or when bootloader is built without external flash configuration.
Misbehavior is strangely confined to BLE stack (my app implements a BLE peripheral)

E: Too big advertising data
Failed to set advertising data (-22)
W: opcode 0x2039 status 0x42
E: Failed to start advertiser
Failed to start advertising set (-5)


Another piece of information, I tried
CONFIG_SINGLE_APPLICATION_SLOT=y
in bootloader's config overlay file, which eliminates the need for configuring external flash in device tree and config
That makes both MCUBoot and app happy, but of course this is not an acceptable workaround, need two images for OTA DFU.

Any advice on what am I doing wrong with the external flash configuration (or in general) would be greatly appreciated

My prj.conf
4628.prj.conf

Main device tree
myboard.dts

Device tree overlay (used by both app and bootloader)
myboard_uart.overlay

Bootloader config overlay
bootloader_uart.conf

Build command line

west build --build-dir $BUILD_DIR $TOP_DIR --pristine --board 32-00008618 -- -DUSE_PARTITION_MANAGER=1 -DNCS_TOOLCHAIN_VERSION:STRING="NONE" -DCONFIG_SIZE_OPTIMIZATIONS=y -DCONFIG_DEBUG_THREAD_INFO=y -DCONF_FILE:STRING="${TOP_DIR}/prj.conf" -DBOARD_ROOT:STRING="$TOP_DIR" -DDTC_OVERLAY_FILE:STRING="${TOP_DIR}/myboard_uart.overlay" -DOVERLAY_CONFIG:STRING="${TOP_DIR}/factory_mode.conf" -Dmcuboot_OVERLAY_CONFIG="${TOP_DIR}/bootloader_uart.conf" -Dmcuboot_DTC_OVERLAY_FILE="${TOP_DIR}/myboard_uart.overlay"

Parents
  • Hi,

    I've picked up your case and will be looking into guiding you to solve the issues at hand :) Lets start with a couple of questions

    1. I see that you've supplied a lot of configurations, but could you also post a partition report?
      1. You can find it by either building and navigating to your build folder in a command line window and entering ninja partition_manager_report and it should look something like this
      2. or by using the memory report action key in VS Code extension
    2. Does your firmware without DFU support run as expected?
    3. Does your firmware without external flash run as expected on a device with sufficient ROM such as the nRF52840DK?

    Kind regards,
    Andreas

  • When I try to dump flash_map while in bootloader, this is what I get
    (cross-referencing it against generated partitions.yml)

    get_flash_area_from_id(1)
    Entry fa_id fa_device_id fa_off             fa_size
    -----------------------------------------------------------
    0        0      0                    0x00000000 0x00010000 <-------- this is MCUBoot itself
    1        2      0                    0x00010000 0x00000200 <--------- this is mcuboot_pad
    2        3      0                    0x00010000 0x0006A000 <--------- this is mcuboot_primary
    3        4      0                    0x00010200 0x00069E00 <--------- this is app
    4        5      0                    0x00010200 0x00069E00 <---------  this is mcuboot_primary_app
    5        7      0                    0x0007A000 0x00006000 <--------- this is nvs_storage

    Since flash_map has no area with ID == 1, this is what is causing 
    W: Failed reading sectors; BOOT_MAX_IMG_SECTORS=128 - too small?

    I believe ID 1 is 
    #define PM_MCUBOOT_SECONDARY_ID 1
    as seen in generated pm_config.h

    What I'm not sure about is how I'm not sure how to make this call chain
    boot_initialize_area --> flash_area_get_sectors--> flash_area_layout --> flash_area_open --> get_flash_area_from_id 
    aware of  secondary being placed in external flash and therefore will not be included in internal flash map

    Also, I'm confused by the following snippet in generated regions.yml

    external_flash:
    base_address: 0x0
    default_driver_kconfig: CONFIG_NORDIC_QSPI_NOR <----------------------
    device: /soc/spi@40023000/w25q80dv@0
    dynamic_partition: null
    name: external_flash
    placement_strategy: start_to_end
    size: 0x100000

    My SPI connection is regular 4 wire SPI, not QSPI, as indicated in device tree

    w25q80dv: w25q80dv@0 {
         compatible = "jedec,spi-nor";

    and in config file

    CONFIG_SPI=y
    CONFIG_SPI_NOR=y
    CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

    So, I'm confused as to where does this QSPI come from


    Attaching my generated pm_config.h

    pm_config.h


    BTW for some reason DevZone doesn't allow upload of *.yml files ?


Reply
  • When I try to dump flash_map while in bootloader, this is what I get
    (cross-referencing it against generated partitions.yml)

    get_flash_area_from_id(1)
    Entry fa_id fa_device_id fa_off             fa_size
    -----------------------------------------------------------
    0        0      0                    0x00000000 0x00010000 <-------- this is MCUBoot itself
    1        2      0                    0x00010000 0x00000200 <--------- this is mcuboot_pad
    2        3      0                    0x00010000 0x0006A000 <--------- this is mcuboot_primary
    3        4      0                    0x00010200 0x00069E00 <--------- this is app
    4        5      0                    0x00010200 0x00069E00 <---------  this is mcuboot_primary_app
    5        7      0                    0x0007A000 0x00006000 <--------- this is nvs_storage

    Since flash_map has no area with ID == 1, this is what is causing 
    W: Failed reading sectors; BOOT_MAX_IMG_SECTORS=128 - too small?

    I believe ID 1 is 
    #define PM_MCUBOOT_SECONDARY_ID 1
    as seen in generated pm_config.h

    What I'm not sure about is how I'm not sure how to make this call chain
    boot_initialize_area --> flash_area_get_sectors--> flash_area_layout --> flash_area_open --> get_flash_area_from_id 
    aware of  secondary being placed in external flash and therefore will not be included in internal flash map

    Also, I'm confused by the following snippet in generated regions.yml

    external_flash:
    base_address: 0x0
    default_driver_kconfig: CONFIG_NORDIC_QSPI_NOR <----------------------
    device: /soc/spi@40023000/w25q80dv@0
    dynamic_partition: null
    name: external_flash
    placement_strategy: start_to_end
    size: 0x100000

    My SPI connection is regular 4 wire SPI, not QSPI, as indicated in device tree

    w25q80dv: w25q80dv@0 {
         compatible = "jedec,spi-nor";

    and in config file

    CONFIG_SPI=y
    CONFIG_SPI_NOR=y
    CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

    So, I'm confused as to where does this QSPI come from


    Attaching my generated pm_config.h

    pm_config.h


    BTW for some reason DevZone doesn't allow upload of *.yml files ?


Children
No Data
Related