This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

DFU from external flash using SPI NOR

Hi,

I am attempting to get the zephyr usb dfu sample located at ncs/zephyr/samples/usb/dfu to work using external flash. I am using the nrf52833 on a custom board in combination with mx25r32 flash chip on ncs version 2.4.0.

Firstly, I have been able to get the dfu working with no issues when I don't configure the project to use external flash. I build the project with the default usb device name, flash it and see that it shows up as a usb device. Then I change the name, rebuild the project and use dfu-util to send app_update.bin to the image 1 slot of the device. I reboot the device, it swaps in the new image and I see my newly named usb device show up. Unfortunately, I need the extra internal flash space as my application is larger than 250 kb.

I then make the following changes to the prj.conf file located at ncs/bootloader/mcuboot/boot/zephyr/prj.conf

CONFIG_MULTITHREADING=y
CONFIG_SPI=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
CONFIG_PM_EXTERNAL_FLASH=y
CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="MX25R32"
CONFIG_PM_EXTERNAL_FLASH_BASE=0
CONFIG_PM_EXTERNAL_FLASH_SIZE=0x73000

I then make the following change to the pm.yml located at the same place

mcuboot_secondary:
    region: external_flash
    size: CONFIG_PM_EXTERNAL_FLASH_SIZE

I also add the following to the prj.conf file in the usb dfu sample

CONFIG_SPI=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
CONFIG_PM_EXTERNAL_FLASH=y
CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="MX25R32"
CONFIG_PM_EXTERNAL_FLASH_BASE=0
CONFIG_PM_EXTERNAL_FLASH_SIZE=0x73000

Once I make these changes, everything builds fine and I see the new application size is basically doubled, which to me means that it is in fact configured correctly for storing the secondary image on external flash. I repeat the steps to get a new image on the device just as a I did before and everything seems to work fine. However, when I reboot the device the new usb device is never seen. I see the bootloader try to swap the new image in but it then says that there is no valid firmware image in the primary slot.

I also run into the same issue when I use SMP over BLE. The image is successfully added and the mcumgr image list command even shows that there are two firmware images on the device. But when I reboot, the bootloader tries to swap in the new image but then fails to validate it. 

Am I doing something wrong or is this only supposed to work with QSPI?

The external flash works fine on its own as I have the NVS system stored there and I am able to use it without any issues.

  • Hi, I had to work on something else for a bit so I apologize for the delayed response. I have picked this up again and made the changes in your above post to the file zephyr/subsys/dfu/boot/mcuboot.c. I did not see any change and something is still going wrong in the bootloader. For some reason, I am also not getting log output in the bootloader, so I don't have much to show here. Going to try to get that working so I can give more information. 

    I did verify that everything was still working when I do not use external flash. Note, I am following the sample and not using mcumgr to do the dfu but rather dfu-util using the command dfu-util --alt 0 --download build/zephyr/app_update.bin. The example says to use --alt 1 but for some reason that does not work for me. 

  • Hi,

    I only tested with BLE using the nRF connect android app, so I will try set up a test with dfu-util as well to see if I run into the same issue. But I can't promise that I will get time for that tomorrow, it might have to wait til next week. 

    dhump3 said:
    I did verify that everything was still working when I do not use external flash.

     This helps narrow it down, thanks.

  • Update: I have gone back to mcumgr to try and get more information on the images. I first flash an image of version 0.2.0 and then I get this output when I run mcumgr image list:

    Images:
     image=0 slot=0
        version: 0.2.0
        bootable: true
        flags: active confirmed
        hash: 1a55d38e4c3fff9c68e13274b534664a06e976726b7081812d2698b21fb4105e

    I then upload an image of version 0.3.0 to the secondary slot of the device and get this output:

    Images:
     image=0 slot=0
        version: 0.2.0
        bootable: true
        flags: active confirmed
        hash: 1a55d38e4c3fff9c68e13274b534664a06e976726b7081812d2698b21fb4105e
      image=0 slot=1
        version: 0.3.0
        bootable: true
        flags: 
        hash: adf638ddfb17699d45d2b4fe6c340db5ab4f7504655f3a728982d087cd345dd8

    I then test the new image and get the following output from the bootloader:

    *** Booting Zephyr OS build v2.4.0-ncs1  **
    [00:00:00.253,601] <inf> mcuboot: Starting bootloader
    [00:00:00.254,364] <inf> mcuboot: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    [00:00:00.254,364] <inf> mcuboot: Boot source: none
    [00:00:00.255,004] <inf> mcuboot: Swap type: test
    [00:00:22.608,764] <err> mcuboot: Image in the primary slot is not valid!
    [00:00:22.608,764] <err> mcuboot: Unable to find bootable image

    At this point the device is pretty much bricked, so I just end up flashing the version 0.3.0 image via nrfjprog to device. I decided to re run the image list command to see what was going on and get this:

    Images:
     image=0 slot=0
        version: 0.3.0
        bootable: true
        flags: active confirmed
        hash: adf638ddfb17699d45d2b4fe6c340db5ab4f7504655f3a728982d087cd345dd8
     image=0 slot=1
        version: 0.2.0
        bootable: true
        flags:
        hash: 2ef9a81cbe11a728a774bedb3ffeb7c66a01b8823693a82b166fa66cf1d26c74

    It seems it actually did try to swap the images as image 0.2.0 is now in slot 1. However the hash is completely different which must mean something went wrong in the swapping of the images. Just to see what happens, I then test the slot 1 image (0.2.0) and get this output from the bootloader:

    *** Booting Zephyr OS build v2.4.0-ncs1  **
    [00:00:00.253,631] <inf> mcuboot: Starting bootloader
    [00:00:00.254,394] <inf> mcuboot: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    [00:00:00.254,394] <inf> mcuboot: Boot source: none
    [00:00:00.255,035] <inf> mcuboot: Swap type: test
    [00:00:09.016,571] <err> mcuboot: Image in the secondary slot is not valid!
    Mcuboot recognizes the secondary image is invalid, deletes it and then it boots up the primary slot. Running image list now gives me:

    Images:
     image=0 slot=0
        version: 0.3.0
        bootable: true
        flags: active confirmed
        hash: adf638ddfb17699d45d2b4fe6c340db5ab4f7504655f3a728982d087cd345dd8
    Split status: N/A (0)

    I'm not entirely sure whats going on here but hopefully this extra detail can help narrow down the issue.

  • Hello dhump3, I'll take over this case. I'll put off some time tomorrow and see if I can get to the bottom of your issue.

    Best regards,

    Simon

    • It would be intereresting to see why the validation fails. Try to add some logging inside boot_is_header_valid() and boot_image_check() to figure out where and why it fails.
    • Could you also try to add BOOT_LOG_INF("Inside boot_perform_update()"); in boot_perform_update()? To see if it performs the image swap before or after you get the error "Image in the primary slot is not valid!". I guess the swap happens before the error, and the validation of the new image fails.
    • Are you able to read the content of the flash after you've transferred the image to the external flash, and before resetting the chip (before the swap happens)? This might be hard to achieve if you're transferring the image over a mobile app, as it will reset automatically after the transfer is complete. However if you use the mcumgr command line tool with macOS or Linux (not supported on Windows), it should be fine, since you're issuing the reset command manually. I'm not familiar with dfu-util but it might work with that tool as well. Try reading out the 4 first bytes, where the magic number should be stored. It should be equal to 0x 3d b8 f3 96. If you don't know how to read out the flash, please tell me and I can look into how to go about it. You could also try to read it out after the swap has happened.

    Best regards,

    Simon

Related