wiced_apps_set_size (OTA) fix

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

This fix resolve 2 issues, which reported her Possible OTA bug? :

1. app_header array overflow (..crash)

2. OTA update crash after 9 incremental firmware updates

Not resolve issues:

1. Crash after 112 incremental updates

2. Crash OTA update after factory restore *(if was before an update and new firmware sizes different by 1 sector). To resolve this, need clear apps headers sector in spi flash and restore default header.

wiced_result_t wiced_apps_set_size( image_location_t* app_header_location, uint32_t size )

{

    sflash_handle_t sflash_handle;

    app_header_t    app_header;

    uint8_t         index;

    uint32_t        current_size = 0;

    uint16_t        empty_sector;

    unsigned long   flash_memory_size;

    uint32_t        available_sectors;

    uint32_t        sectors_needed;

    init_sflash( &sflash_handle, PLATFORM_SFLASH_PERIPHERAL_ID, SFLASH_WRITE_NOT_ALLOWED );

    sflash_read( &sflash_handle, app_header_location->detail.external_fixed.location, &app_header, sizeof(app_header_t) );

    for ( index = 0; index < app_header.count; index++ )

    {

        current_size += app_header.sectors[ index ].count;

    }

    current_size *= SFLASH_SECTOR_SIZE;

    if ( current_size >= size )

    {

        deinit_sflash( &sflash_handle);

        return WICED_SUCCESS;

    }

    current_size   = ( size - current_size );

    sectors_needed = current_size / SFLASH_SECTOR_SIZE;

    sectors_needed = ( current_size % SFLASH_SECTOR_SIZE ) ? ( sectors_needed + 1 ) : ( sectors_needed );

    deinit_sflash( &sflash_handle);

    //darius internaly check new header that do not overload next sector this about 112 times if each firmare bigger. Internaly was change

    if ( wiced_apps_find_empty_location( app_header_location, &empty_sector ) != WICED_SUCCESS )

    {

        return WICED_ERROR;

    }

    sflash_get_size( &sflash_handle, &flash_memory_size );

    available_sectors = ( flash_memory_size / SFLASH_SECTOR_SIZE ) - empty_sector;

    /* Check whether number of sectors which are empty is more that the number of sectors required for an application */

    if ( sectors_needed > available_sectors )

    {

        wiced_assert("Flash memory doesn't have enough space for this application update", 0!=0);

        /* Application with requested size wont fit into flash memory chip */

        return WICED_ERROR;

    }

#if 1

    /*Darius. Trivial change. Check whether number of sections which are empty is more that the number of sectors required for an application */

    if ( app_header.count >= sizeof(app_header.sectors)/sizeof(app_header.sectors[0]) )

    {

        wiced_assert("App_header sections  doesn't have enough space for this application update. Total error.", 0!=0);

        /* We have sflash memory defragmentation */

        return WICED_ERROR;

    }

    if( app_header.count>0 && (app_header.sectors[ app_header.count-1].start+app_header.sectors[ app_header.count-1 ].count)==empty_sector ){

        app_header.sectors[ app_header.count-1].count += (uint16_t) sectors_needed;

    }

    else{

        app_header.sectors[ app_header.count ].start   = empty_sector;

        app_header.sectors[ app_header.count++ ].count = (uint16_t) sectors_needed;

    }

#else

    app_header.sectors[ app_header.count ].start   = empty_sector;

    app_header.sectors[ app_header.count++ ].count = (uint16_t) sectors_needed;

#endif

    init_sflash( &sflash_handle, PLATFORM_SFLASH_PERIPHERAL_ID, SFLASH_WRITE_ALLOWED );

    /* printf("sectory count %d %d %d\n", app_header.count, app_header.sectors[ app_header.count-1 ].start, app_header.sectors[ app_header.count-1 ].count); */

    sflash_write( &sflash_handle, app_header_location->detail.external_fixed.location, &app_header, sizeof(app_header_t) );

    memset(&app_header,0xFFFFFFFF, sizeof(app_header_t));//clear buffer

    sflash_read( &sflash_handle, app_header_location->detail.external_fixed.location, &app_header, sizeof(app_header_t) );

    /* printf("sectory count %d %d %d\n", app_header.count, app_header.sectors[ app_header.count-1 ].start, app_header.sectors[ app_header.count-1 ].count); */

    deinit_sflash( &sflash_handle);

    return WICED_SUCCESS;

}

0 Likes
15 Replies
AxLi_1746341
Level 7
Level 7
10 comments on KBA 5 comments on KBA First comment on KBA

Darius Babrauskas wrote:

wiced_result_t wiced_apps_set_size( image_location_t* app_header_location, uint32_t size )

{

    sflash_handle_t sflash_handle;

    app_header_t    app_header;

    uint8_t         index;

    uint32_t        current_size = 0;

    uint16_t        empty_sector;

    unsigned long   flash_memory_size;

    uint32_t        available_sectors;

    uint32_t        sectors_needed;

    init_sflash( &sflash_handle, PLATFORM_SFLASH_PERIPHERAL_ID, SFLASH_WRITE_NOT_ALLOWED );

    sflash_read( &sflash_handle, app_header_location->detail.external_fixed.location, &app_header, sizeof(app_header_t) );

    for ( index = 0; index < app_header.count; index++ )

    {

        current_size += app_header.sectors[ index ].count;

    }

    current_size *= SFLASH_SECTOR_SIZE;

    if ( current_size >= size )

    {

        deinit_sflash( &sflash_handle);

        return WICED_SUCCESS;

    }

Above code looks strange to me:

Setting a smaller size than current size has no effect.

e.g.

wiced_apps_get_size return 135168

wiced_apps_set_size set to 120000

wiced_apps_get_size still return 135168

I'm wondering if this is expected behavior?

0 Likes

Hi axel.lin_1746341

If I  recognize correctly, stock code doesn't shrink sizes on external flash.

If the new size is set by wiced_apps_set_size, it just ignores and LUT is left unchanged.

Modifications to LUT only happens when a app region on external flash increments.

And this is why darius1​ mentioned in the original post "incremental (firmware) updates".

0 Likes

xavier@candyhouse wrote:

Hi axel.lin_1746341

If I  recognize correctly, stock code doesn't shrink sizes on external flash.

If the new size is set by wiced_apps_set_size, it just ignores and LUT is left unchanged.

Modifications to LUT only happens when a app region on external flash increments.

And this is why darius1 mentioned in the original post "incremental (firmware) updates".

AFAICS, ignore updating LTU just hidden the bug as "incremental (firmware) updates".

BTW, I found yet another critical bug:

The wiced_apps_find_empty_location() checking does not make sense at all. It is *wrong*.

My device returned error due to "Flash memory doesn't have enough space for this application update".

The returned empty_sector is the latest sector of APP1 ( in my case APP1 is the latest section ).

It calculates the available space as available space = flash size - empty_sector position.

Whatever I want to do is to override the data in APP1. It's nothing to do with the available space in end-of-APP1 ~ end-of-flash.

In my case, it should check if the length of APP1 is big enough for new size rather than check the size of end-of-APP1 ~ end-of-flash.

mifokausikrash

0 Likes

AFAIK, Broadcom / Cypress made assumptions on external flash:

1. On first burn, all empty sectors locates at bottom

2. On region size shrink, no modification to LUT

3. On region size increase, assign first empty sectors to the region so remaining empty sectors, if any, still stay at bottom

Thus available size can be calculated by their implementation.

I think it's not wrong, but just not efficient considering "size shrink".

0 Likes

Assume your current image is 1MB in APP1, and you have 512KB empty sectors after APP1.

You want to OTA to a 1.1MB image,

the SDK returns "Flash memory doesn't have enough space for this application update" because 1.1MB > 512KB.

Are you sure you are fine with such case?

PS. I'm fine for not shrinking the size case if it still works. Compare to other issues, the shrink-size issue is minor.

0 Likes

I guess what we're discussing is about this :

    current_size   = ( size - current_size );

    sectors_needed = current_size / SFLASH_SECTOR_SIZE;

    sectors_needed = ( current_size % SFLASH_SECTOR_SIZE ) ? ( sectors_needed + 1 ) : ( sectors_needed );

    WICED_VERIFY( deinit_sflash( &sflash_handle) );

    if ( wiced_apps_find_empty_location( app_header_location, &empty_sector ) != WICED_SUCCESS )

    {

        return WICED_ERROR;

    }

    WICED_VERIFY( sflash_get_size( &sflash_handle, &flash_memory_size ) );

    available_sectors = ( flash_memory_size / SFLASH_SECTOR_SIZE ) - empty_sector;

    /* Check whether number of sectors which are empty is more that the number of sectors required for an application */

    if ( sectors_needed > available_sectors )

    {

        wiced_assert("Flash memory doesn't have enough space for this application update", 0!=0);

        /* Application with requested size wont fit into flash memory chip */

        return WICED_ERROR;

    }

Perhaps the 2nd argument name of "wiced_apps_find_empty_location" better describes the variable named "empty_sector".

static wiced_result_t wiced_apps_find_empty_location( image_location_t* new_header_location, uint16_t* new_sector_location )

As "current_size" is considered in the  1st line above, "sectors_needed" is already the "extra sector numbers need to add to this app region".

Seriously, I don't think the logic is very *wrong* here.

Please kindly correct me if I misunderstand anything...

0 Likes

xavier@candyhouse wrote:

Seriously, I don't think the logic is very *wrong* here.

Please kindly correct me if I misunderstand anything...

If you think the logic is *correct*, it means you accept the example I mentioned in previous post.

Maybe the issue is not just about the logic here, but the whole design of OTA.

i.e. If you have a 2MB flash, you cannot OTA a 1MB image to 1.1M image.

The solution is to get a larger flash then it works.

0 Likes

What is the external flash IC you're using?

axel.lin_1746341 wrote:

Assume your current image is 1MB in APP1, and you have 512KB empty sectors after APP1.

You want to OTA to a 1.1MB image,

the SDK returns "Flash memory doesn't have enough space for this application update" because 1.1MB > 512KB.

Assuming all above statements are correct, there is still one thing that may go wrong.

WICED api : flash_get_size() may give size = 0 and return 0 if the device_id is not found.

This will causes "Flash memory doesn't have enough space for this application update".

Note that the only place where flash_get_size() is being used elsewhere is at waf/sflash_write.

"chip_size = 0" here doesn't look like to stop board downloading, and this may be why you didn't notice.

Anonymous
Not applicable

Hello,

we facing same issue.

in our case:

ota_fr : 458KB

new app.stripped : 548KB

in this case it not work.

shown same error like in this your issue.

we Debug this case , in app_set_size() it fail.

need help how to resolve.

i have some of doubt:

1> while app download using  download_apps, it boot the code in external SFLASH region ?

2> if we increase size of SFLASH Size of it will resolve or not ?

Thanks & Regards

Chintan Patel

0 Likes

Adding the Apps team: madyrashgrsrkavsajai

0 Likes

---》i have some of doubt:

》1> while app download using  download_apps, it boot the code in external SFLASH region ?

It boot from RAM and communicate via jtag to pc.

》2> if we increase size of SFLASH Size of it will resolve or not ?

Possible resolve or not.  Better to find problem cause.

What is your sflash chip?

Note. Wi-fi firmware, DCT, FACTORY RESTORE reside in sflash.

BR.

Darius (Darius1 my old account)

0 Likes
Anonymous
Not applicable

Hello,

I clear all this my doubt,

In our case:

1> we have External Serial Flash of size: 1MB

we debug code and in function app_set_size(), we get flash size 1MB ok.

2> download code using snip.ota_fr-SN8205x JTAG=Olimex_ARM-USB-TINY-H download download_apps run

app size: 458KB,

degfault app: ota_fr:458KB

download app using OTA , its size:548KB, and it will save as DCT_APP0 region

Que:

1>Total size : (Default factory reset APP) 458KB +  548KB (new DCT_APP0) + DCT ,

so its size goes beyond my external serial falsh size. (1MB < Total Size)

it creat issue, and it always fail at app_set_size().

2> We does not require any default restore app in serial flash, just only update new app and it work

is it possible ?

if possible how we can do it ?

3> some time we get issue of after OTA Firmware upgrade,app not restart with new OTA Uploaded app and restart with old app.

4> some time code block at restart and do nothing.

We used:

Wiced SDK 3.7.0-3

App: snip.OTA_fr

need some guide to resolve such kind of issue..

Thanks & Regards

Chintan

0 Likes

Hi Chintan,

"snip.ota_fr-SN8205x JTAG=Olimex_ARM-USB-TINY-H download download_apps run "  cant work, because must be debug mode for  download_apps.

See her: sflash_write frequently fails on builds using download_apps

Maybe first:

"snip.ota_fr-SN8205x-debug JTAG=Olimex_ARM-USB-TINY-H download_apps"   at this case factory restore application can be big, so it can

busy more sflash space.   You can precompile factory restore elf file and  write in platform mk file path exmp:

FR_APP:= ./apps/factory/ota_fr.stripped.elf

I think possible disable FACTORY restore file, but don't know how. Maybe must be define in platform mk or  make string.

Maybe need  comment out   #FR_APP:= 

or set empty FR_APP:=

After download_apps try:

"snip.ota_fr-SN8205x JTAG=Olimex_ARM-USB-TINY-H download run"

BR.

Darius

0 Likes
Anonymous
Not applicable

Hello Darius,

Thanks a lot for your valuable help.

As per Follow your step WiFi OTA Working very well.

But we need to two time download code and it will not be possible when put product on market.

1> build app :  download_apps (write DCT, stripped.elf and apps.bin file)

2> build app:  download run

so any other way we can just download firmware one time only ??

Thanks & Regards

Chintan Patel

0 Likes

Hi Chitan,

I not use wiced tools to production.

Maybe posiible use open-ocd scripts to production.

Other way:

Maybe possible for put product on market use bootloader options.  DCT have option  (valid).  Then after first start bootloader test this bit, if it 1, then bootloader doing factory restoring, ant after set this value to 0.

Try define in your platform_config.h

/* The main app is stored in external serial flash */

#define BOOTLOADER_LOAD_MAIN_APP_FROM_EXTERNAL_LOCATION

#if defined( BOOTLOADER_LOAD_MAIN_APP_FROM_FILESYSTEM )

    .dct_header.boot_detail.entry_point = 0,

    .dct_header.boot_detail.load_details.valid = 1,

    .dct_header.boot_detail.load_details.load_once = 0,

    .dct_header.boot_detail.load_details.source.id = EXTERNAL_FILESYSTEM_FILE,

    .dct_header.boot_detail.load_details.source.detail.filesystem_filename = "app.elf",

    .dct_header.boot_detail.load_details.destination.id = INTERNAL,

#elif defined( BOOTLOADER_LOAD_MAIN_APP_FROM_EXTERNAL_LOCATION )

    .dct_header.boot_detail.entry_point = 0,

    .dct_header.boot_detail.load_details.valid =1,

    .dct_header.boot_detail.load_details.load_once = 0,

    .dct_header.boot_detail.load_details.source.id = EXTERNAL_FIXED_LOCATION,

    .dct_header.boot_detail.load_details.source.detail.external_fixed.location = SFLASH_APPS_HEADER_LOC + sizeof(app_header_t) * DCT_APP0_INDEX,

    .dct_header.boot_detail.load_details.destination.id = INTERNAL,

#else

    .dct_header.boot_detail.entry_point = 0,

    .dct_header.boot_detail.load_details.valid = 0,

    .dct_header.boot_detail.load_details.source.id = NONE,

    .dct_header.boot_detail.load_details.source.detail.external_fixed.location = 0,

    .dct_header.boot_detail.load_details.destination.id = INTERNAL,

#endif /* ifdef BOOTLOADER_LOAD_MAIN_APP_FROM_FILESYSTEM */

Then try do

1> build app :  download_apps run (write DCT, stripped.elf and apps.bin file)

At this case,  your MCU program it self from factory restore. So you automatically test your factory restore functionality.

P.S.

I not tested this (I think must work), but you can try do it and write you experiences.

0 Likes