NRF52840: mcuboot (ota) and external flash / Compilation Problem

Hye everyone, thanks for the project
i have a problem on NRF52840 on a project using mcuboot (ota) and an external flash used independently by the app (not for ota)

prj.conf:

...
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y

myboard.dts:

...
&zd25wq32 {
    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;
        
        storagenor_part: partition@0 {
            label = "storagenor";
            reg = <0x000000 0x400000>; /* 0x00100000 -> 4MB */
        };
    };
};

storage.c

...
#define STORAGE_PARTITION storagenor_part
#define STORAGE_PARTITION_ID FIXED_PARTITION_ID(STORAGE_PARTITION)

my code build when CONFIGBOOTLOADER_MCUBOOT=n
but i get a compilation error when CONFIG_BOOTLOADER_MCUBOOT=y

[15/363] Building C object CMakeFiles/app.dir/src/drivers/storage.c.obj
FAILED: CMakeFiles/app.dir/src/drivers/storage.c.obj
...
In file included from /opt/nordic/ncs/v2.5.2/zephyr/include/zephyr/storage/flash_map.h:275,
from ../src/drivers/storage.c:19:
../src/drivers/storage.c: In function 'setup_flash':
/opt/nordic/ncs/v2.5.2/nrf/include/flash_map_pm.h:43:22: error: 'PM_storagenor_part_ID' undeclared (first use in this function)
43 | #define PM_ID(label) PM##label##_ID
| ^
/opt/nordic/ncs/v2.5.2/nrf/include/flash_map_pm.h:48:35: note: in expansion of macro 'PM_ID'
48 | #define FIXED_PARTITION_ID(label) PM_ID(label)
| ^
../src/drivers/storage.c:12:41: note: in expansion of macro 'FIXED_PARTITION_ID'
12 | #define STORAGE_PARTITION_ID FIXED_PARTITION_ID(STORAGE_PARTITION)
| ^~~~
../src/drivers/storage.c:36:36: note: in expansion of macro 'STORAGE_PARTITION_ID'
36 | mnt->storage_dev = (void *)STORAGE_PARTITION_ID;
| ^~~~~~~~

tried a lot but i can't pass through this
same pb with toolchain 2.4.2 and 2.5.2.
any advice ?!

  • Hi,

    I created a sample to illustrate how to do this which you can see here https://github.com/aHaugl/samples_for_NCS/tree/main/DFU/mcuboot_internal_settings_external

    As the Readme states it is a modified version of the zephyr setting sample with the addition of a static partitioning that forces MCUboot primary and secondary application slot to be located on the internal flash and the settings partition to be on the external flash through CONFIG_PM_PARTITION_REGION_SETTINGS_STORAGE_EXTERNAL=y

    Could I ask why you don't want to add MCUboot secondary for OTA purpose on the external flash? It seems to me to be the best way so that you can allocate more of the internal flash to increase the possible application size

    Kind regards,
    Andreas

  • hi, thanks a lot for the sample, i will check this in a moment.

    just to be clear my storage.c file is not used for settings but for filesystem (wave files) on the external flash, even if i also used nvs settings in the app but without fs.

    ideally you are right, could be better to add MCUboot secondary for OTA purpose on the external flash. but if so i'll like two partition on external flash... one for MCUboot secondary and the other for my fs... how modify dts or pm or conf to do it ? maybe in your sample ? thanks 

    also do you know if it's possible to add files to binary in the fota zip and put those files in specific partition during the update ?

    maybe alternatively do you know a client and mobile sample to use the blob transfert ble api (or something else ?) to transfert files from mobile to firmware ?

    keep you updated for my compilation pb.

  • i had to add in flash dts:

    &zd25wq32 {
    	size = <0x400000>;
    	...
    }

    if not i got:

    CMake Error at /opt/nordic/ncs/v2.4.2/nrf/cmake/partition_manager.cmake:220 (math):
      math cannot parse the expression: " / 8": syntax error, unexpected
      exp_DIVIDE (2).

    same error with or without the pm_static.yml

    but then i got

    /opt/nordic/ncs/v2.4.2/zephyr/drivers/flash/nrf_qspi_nor.c:72:1: error: static assertion failed: "Node /soc/qspi@40029000/zd25wq32ctigt@0 has both size and size-in-bytes properties; use exactly one"
    72 | BUILD_ASSERT(!(DT_INST_NODE_HAS_PROP(0, size_in_bytes) && DT_INST_NODE_HAS_PROP(0, size)),
    | ^~~~~~~~~~~~

    and always the same error also about storage.c 

    /opt/nordic/ncs/v2.5.2/nrf/include/flash_map_pm.h:43:22: error: 'PM_storagenor_part_ID' undeclared (first use in this function)
    43 | #define PM_ID(label) PM##label##_ID

    i also found an try with

    CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y
    CONFIG_PM_EXTERNAL_FLASH_BASE=0

    but without success... same errors

    maybe i should share thin repo ?

  • Hi

    iznow said:
    ideally you are right, could be better to add MCUboot secondary for OTA purpose on the external flash. but if so i'll like two partition on external flash... one for MCUboot secondary and the other for my fs... how modify dts or pm or conf to do it ? maybe in your sample ? thanks 

    Yes, this is showcased in the sample with the pm_static.yml. If you don't add anything there, and simply have your external flash defined and existing, the dynamic partitioning used by the build system will often place the mcuboot secondary application slot on the external flash and allocate maximum of room for the application on the internal flash. 

    If you build the settings sample with CONFIG_BOOTLOADER_MCUBOOT=y and have an external flash enabled as shown in https://github.com/aHaugl/samples_for_NCS/blob/main/DFU/mcuboot_internal_settings_external/nrf52840dk_nrf52840.overlay, then your partition will something like this automatically:

    Internal flash:
    MCUBoot
    Primary application slot
    settings_storage

    External flash:
    Secondary application slot

    If you investigate the links I mention in the sample I sent you then I refer to https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.99-dev1/nrf/scripts/partition_manager/partition_manager.html. If you inspect this documentation and focus on static partitioning then you will see how you can configure a specific static partition which I'm using. 

    This can also be done with CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y, which you mention you try, but then you will have to remove the definition of the secondary partition from the static partitioning map.

    For instance I've defined MCUboot secondary to be located on the internal flash with start address and size defined as 

    mcuboot_secondary:
      address: 0x86000
      end_address: 0x100000
      placement:
        after:
        - mcuboot_primary
        align:
          start: 0x1000
        align_next: 0x1000
      region: flash_primary
      share_size:
      - mcuboot_primary
      size: 0x7a000

    I.e I've used static partitioning to state that I want this partition to be defined as I want it to be (based on your description of the application)

    Everything you need to know to learn how static partitioning should be mentioned above, but we will also shortly launch a DFU topic in the upcomming NCS intermediate course that we will release on https://academy.nordicsemi.com/ this week. I highly recommend that you go through that, and other relevant courses, with focus on the DFU lesson in the upcoming Intermediate course.

    iznow said:
    also do you know if it's possible to add files to binary in the fota zip and put those files in specific partition during the update ?

    MCUboot handles this when you enter DFU mode. See https://docs.nordicsemi.com/bundle/ncs-latest/page/mcuboot/wrapper.html for more info regarding MCUboot as well as the academy course I mentioned that will come shortly. The new firmware that you want to update through FOTA will be placed in MCUBoot secondary application slot and swapped to the primary application slot through the DFU algorithm selected (default is swap).

    iznow said:
    maybe alternatively do you know a client and mobile sample to use the blob transfert ble api (or something else ?) to transfert files from mobile to firmware ?

    See smp server sample with Bluetooth overlay for how to transport new firmware over BLE through for instance nRF Connect for Mobile or Device Manager mobile application: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/samples/subsys/mgmt/mcumgr/smp_svr/README.html

    iznow said:
    but then i got

    /opt/nordic/ncs/v2.4.2/zephyr/drivers/flash/nrf_qspi_nor.c:72:1: error: static assertion failed: "Node /soc/qspi@40029000/zd25wq32ctigt@0 has both size and size-in-bytes properties; use exactly one"
    72 | BUILD_ASSERT(!(DT_INST_NODE_HAS_PROP(0, size_in_bytes) && DT_INST_NODE_HAS_PROP(0, size)),
    | ^~~~~~~~~~~~

    The error you get states that you need to only use either size or size-in-bytes property. https://docs.zephyrproject.org/latest/build/dts/api/bindings/mtd/jedec,spi-nor.html says more about Jedec properties. You can also see how you should set up an external flash device in https://docs.zephyrproject.org/latest/samples/drivers/spi_flash/README.html

    Kind regards,
    Andreas

  • ok i manage to pass my compilation pb thanks to your advices by using the following pm_static.yml:

    app:
      address: 0xc200
      end_address: 0xfe000
      region: flash_primary
      size: 0xf1e00
    # external_flash:
    #   address: 0xf2000
    #   end_address: 0x80000
    #   region: external_flash
    #   size: -0x72000
    mcuboot:
      address: 0x0
      end_address: 0xc000
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0xc000
    mcuboot_pad:
      address: 0xc000
      end_address: 0xc200
      placement:
        align:
          start: 0x1000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0xc000
      end_address: 0xfe000
      orig_span: &id001
      - mcuboot_pad
      - app
      region: flash_primary
      size: 0xf2000
      span: *id001
    mcuboot_primary_app:
      address: 0xc200
      end_address: 0xfe000
      orig_span: &id002
      - app
      region: flash_primary
      size: 0xf1e00
      span: *id002
    storagenor_part:
      address: 0xf2000
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0x400000
      placement:
        align:
          start: 0x4
      region: external_flash
      share_size:
      - mcuboot_primary
      size: 0x30E000
    mcuboot_secondary:
      address: 0x0
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0xf2000
      placement:
        align:
          start: 0x4
      region: external_flash
      share_size:
      - mcuboot_primary
      size: 0xf2000
    settings_storage:
      address: 0xfe000
      end_address: 0x100000
      placement:
        align:
          start: 0x1000
        before:
        - end
      region: flash_primary
      size: 0x2000
    sram_primary:
      address: 0x20000000
      end_address: 0x20040000
      region: sram_primary
      size: 0x40000
    

     

    but now i have a flashing issue :

    Flashing build to 683735107
    west flash -d /Users/pi/Documents/Code/baltee/b01-firmware/build --skip-rebuild --dev-id 683735107
    
    -- west flash: using runner nrfjprog
    -- runners.nrfjprog: Flashing file: /Users/pi/Documents/Code/baltee/b01-firmware/build/zephyr/merged.hex
    [ ######               ]   0.000s | Erase file - Check image           [ ####                 ]   0.000s | Check image validity - Initialize d[ ########             ]   0.000s | Check image validity - Check region[ ############         ]   0.000s | Check image validity - block 1 of 3[ ################     ]   0.006s | Check image validity - block 2 of 3[ #################### ]   0.046s | Check image validity - Finished    [ #############        ]   0.000s | Erase file - Erasing               [ ######               ]   0.000s | Erasing non-volatile memory - block[ #############        ]   0.362s | Erasing non-volatile memory - block[ #################### ]   0.000s | Erasing non-volatile memory - Erase[ #################### ]  10.143s | Erase file - Done erasing                                                          
    [ ######               ]   0.000s | Program file - Checking image      [ ####                 ]   0.000s | Check image validity - Initialize d[ ########             ]   0.000s | Check image validity - Check region[ ############         ]   6.862s | Check image validity - block 1 of 3[error] [ Client] - Encountered error -102: Command program_file executed for 155 milliseconds with result -102
    [ ################     ]   2.579s | Check image validity - block 2 of 3[ #################### ]   0.045s | Check image validity - Finished    [ #############        ]   0.000s | Program file - Programming         [ ######               ]   0.000s | Programming image - block 1 of 2   [error] [  nRF52] - The write access failed, but no cause could be determined.
    [error] [  nRF52] - It may be due to an unaligned access, accessing a nonexistent memory, or a communication issue.
    [error] [  nRF52] - Failed while performing 'Write' operation on target address 0x00000000. 
    -102: An unknown error.
    [error] [  nRF52] - Failed while reading device information.
    [error] [ Worker] - An unknown error.
    ERROR: JLinkARM DLL reported an error. Try again. If error condition
    ERROR: persists, run the same command again with argument --log, contact Nordic
    ERROR: Semiconductor and provide the generated log.log file to them.
    NOTE: For additional output, try running again with logging enabled (--log).
    NOTE: Any generated log error messages will be displayed.
    FATAL ERROR: command exited with status 33: nrfjprog --program /Users/pi/Documents/Code/baltee/b01-firmware/build/zephyr/merged.hex --sectoranduicrerase --verify -f NRF52 --snr 683735107

    any idea ? 

    thanks a lot

Related