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.

  • I have added the log statement and made changes to spi_nor_write(). Unfortunately, I have not seen any change in the bootloader output:

    [00:00:00.253,570] <inf> mcuboot: Starting bootloader
    [00:00:00.254,241] <inf> mcuboot: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    [00:00:00.254,241] <inf> mcuboot: Boot source: none
    [00:00:00.254,791] <inf> mcuboot: Swap type: test
    [00:00:00.254,791] <inf> mcuboot: Header is valid!
    [00:00:00.254,791] <inf> mcuboot: Inside bootutil_img_validate()
    [00:00:00.880,889] <inf> mcuboot: offset 300292 | image size: 299780 | header size 512
    [00:00:00.954,650] <inf> mcuboot: bootutil_img_validate() successful!
    [00:00:00.954,650] <inf> mcuboot: Inisde boot_perform_update()
    [00:00:21.496,856] <inf> mcuboot: Inisde boot_perform_update() completed with status 0
    [00:00:21.497,009] <inf> mcuboot: Header is valid!
    [00:00:21.497,009] <inf> mcuboot: Inside bootutil_img_validate()
    [00:00:21.736,511] <inf> mcuboot: offset 300292 | image size: 299780 | header size 512
    [00:00:21.736,541] <err> mcuboot: tlv magic is wrong! expected 6907 but got 0
    [00:00:21.736,541] <err> mcuboot: bootutil_tlv_iter_begin failed with error -1
    [00:00:21.736,541] <err> mcuboot: Failed to validate the image!
    [00:00:21.736,541] <err> mcuboot: Image in the primary slot is not valid!
    [00:00:21.736,541] <err> mcuboot: Unable to find bootable image

    Note that the image size is so large because I am testing with the custom application I am building. The offset seems to be the image size + the header size. Here are the code changes I made to the spi_nor driver. I added this function:

    static inline int spi_nor_write_sub_word(const struct device *dev, off_t addr,
                                             const void *src, size_t slen)
    {
        uint8_t __aligned(4) buf[4];
        int ret;
        ret = spi_nor_cmd_addr_read(dev, SPI_NOR_CMD_READ, addr, buf,
                                    sizeof(buf));
        spi_nor_wait_until_ready(dev);
        if (ret >= 0) {
            memcpy(buf, src, slen);
            spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN);
            ret = spi_nor_cmd_addr_write(dev, SPI_NOR_CMD_PP, addr, buf,
                                         sizeof(buf));
        }
        return ret;
    }

    And then in spi_nor_write() I edited lines 498 - 499 to be:

    if (to_write < 4U) {
        ret = spi_nor_write_sub_word(dev, addr, src, to_write);
    } else {
        spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN);
        ret = spi_nor_cmd_addr_write(dev, SPI_NOR_CMD_PP, addr,
                                     src, to_write);
    }

    I will continue digging to see whats going on with the tlv magic.

  • Could you send over your application in a zipped file? Then I could modify it to work with the nRF52840 and the mx25r64 and try to reproduce the issue.

  • Is there a way I can send the application privately?

  • I've sent you a privat message here on DevZone, check that out on how to share the project privately.

  • I got the project, and will try to reproduce.

Related