Learnings DFU and FLASH_MAX_UPGRADE_SIZE

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
fabriceo
XCore Addict
Posts: 184
Joined: Mon Jan 08, 2018 4:14 pm

Learnings DFU and FLASH_MAX_UPGRADE_SIZE

Post by fabriceo »

Hi,

I thought I could share some learnings when it comes to upgrading via DFU and some side effect or corner case we found.

first, our factory image (usb audio app) once compressed by the flash tool was just below 64kB and we have build our code with boot partition of 512k and the FLASH_MAX_UPGRADE_SIZE equal to 128*1024, considering this would give us some margin for the next upgrade.

Recently we have added some 64k of data and some extra code to support local flashing of an arm processor in charge of the display.

Unfortunately , our new image is now around 250kB, for the simple reason that the xflash tool is hanging in the process called lib compressor ... so we have to use the --no-compression attribute in the xflash command line.
Such failure was reported in the past e.g here:
viewtopic.php?t=4853
This problem exists also with the latest xflash tool version 14.4.1...

that is something weird as all of the sudden none of the product in the field could be upgraded...

so the way to sort this out has been to create a new light image called "upgrade1", based on the original factory light image, but with the famous FLASH_MAX_UPGRADE_SIZE set to 384k. Hopefully it is compressed successfully to less than 64k.
After a first DFU upgrade, this image is now running in the device and we are now able to upgrade a second time with our big image called "upgrade2".

but deep diving on the DFU code, I realized that the "upgrade 1" image is simply erased when programing the "upgrade 2" ! from the xmos documetation I was expecting that the upgrade2 would be added just after upgrade 1, but unfortunately NO, it is added just after the original factory image as can be seen in the code of the begin_write() function:

Code: Select all

do {
        result = fl_startImageAdd(&factory_image, FLASH_MAX_UPGRADE_SIZE, 0);
    } while (result > 0);
We wanted to keep "upgrade 1" in flash as a default boot image in case the upgrade 2 failed, for some reasons.
So the original DFU code was changed to support this, within the flash_cmd_init() with an extra parameter "version":

Code: Select all

    factory_image  = image;
    previous_image = image;
    do {
        if (fl_getNextBootImage(&image) == 0)
        {
            xprintf("fl-valid upgrade boot image identified\n");
            xprintf("   addr = %X, size = %d, ver = %d, factory = %d\n",image.startAddress,image.size,image.version, image.factory);
            if (image.version >= version) {
                xprintf("image selected as valid one\n");
                upgrade_image_valid = 1;
                upgrade_image = image;
                version = 0;
            } else
                previous_image = image;
        } else {
            xprintf("fl-No more upgrade boot image found\n");
            version = 0;
        }
    } while (version);
within DFU_dnload we get the Version of the image to be flashed by extracting 5th word of the block 0, sifted right by 4. Then this parameter is passed down to flash_cmd_line(int version).
the code of begin_write() was also modified to replace &factory_image by the new "previous_image" variable.

here we are, hope this helps.