ota2_bootloader failsafe

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

cross mob
GeEs_4724546
Level 1
Level 1
First solution authored 5 replies posted 5 sign-ins

On an STM32F4 based board...

When hitting ota2_bootloader.c::ota2_failsafe_app_load() the entry point is a flash address  0x800c3e5 but it hasn't been loaded into internal flash from SFlash.   I see ota2_failsafe_app_load() erasing (internal?) flash:

/* Erase the application area */
result = ota2_failsafe_app_area_erase( flash_location, &header );

Then reading into RAM from flash:

result = ota2_failsafe_app_read( flash_location, (uint8_t*)prog_header.physical_address, prog_header.data_offset, prog_header.data_size_in_file );

But danged if it's obvious how internal flash get's written!  It is quite clear in wiced_waf_common.c::wiced_waf_app_load():

result = platform_load_app_chunk( app_header_location, offset, (void*) prog_header.physical_address, prog_header.data_size_in_file );

Thanks!

Geoff

 

 

0 Likes
1 Solution
Aditi_B
Moderator
Moderator
Moderator
500 replies posted 5 questions asked 250 replies posted

Hi,

Just to ensure, have you followed section-8 "Adding OTA2 to a new platform" of WICED OTA2 Update Support provided in Wiced Studio? Location- 

43xxx_Wi-Fi\doc\WICED-OTA2.pdf

Thanks

Aditi

View solution in original post

0 Likes
5 Replies
Charles_Lai
Moderator
Moderator
Moderator
500 replies posted 250 solutions authored 250 sign-ins

Hi,

Could you try to post your code or the complete log output? We need more information to identify the cause.

Best regards

0 Likes

I'm using WICED-SDK 6.4 and the stock ota2_bootloader.c and ota2_failsafe.c (which is stuffed into sflash).   The only change made was for test purposes, I added:

dct_ota2_config.boot_type = OTA2_BOOT_FAILSAFE_FACTORY_RESET;

Simply so I can verify it would load and run failsafe.  Previously, I had used ModusToolbox to run ota2_failsafe without any problem.   There's no output because the ota2_bootloader does select the failsafe path, but then jumps into a hardfault.   That led me to wonder how the sflash image was being copied into iflash.   Unless the ota2_failsafe image is supposed to run entirely out of SRAM, I couldn't follow the ota2_bootloader logic.

0 Likes

This is the fix... sorry not pretty:

uint8_t buff[ 64 ];
while ( size > 0 )
{
uint32_t write_size = MIN( sizeof(buff), size);

result = ota2_failsafe_app_read( flash_location, buff, offset, write_size );
platform_write_flash_chunk( (uint32_t) physical_address, buff, write_size );

The original code did not read into an SRAM buffer and then into iflash (with platform_write_flash_chunk).  The only way it might have worked is if the failsafe was linked to execute out of SRAM.

0 Likes
Aditi_B
Moderator
Moderator
Moderator
500 replies posted 5 questions asked 250 replies posted

Hi,

Just to ensure, have you followed section-8 "Adding OTA2 to a new platform" of WICED OTA2 Update Support provided in Wiced Studio? Location- 

43xxx_Wi-Fi\doc\WICED-OTA2.pdf

Thanks

Aditi

0 Likes
GeEs_4724546
Level 1
Level 1
First solution authored 5 replies posted 5 sign-ins

To get to as far as I got, clearly I had to perform the steps in Section 8.

To re-state, the code in ota2_bootloader.c:ota2_failsafe_app_load() does not copy the failsafe app from sflash into iflash.

 

static wiced_result_t ota2_failsafe_app_load( uint32_t flash_location, uint32_t* entry_point )
{
    wiced_result_t       result = WICED_SUCCESS;
    uint32_t             i;
    elf_header_t         header;
    elf_program_header_t prog_header;

    /* assume pointer is good (only called from within this file) and assume error */
    *entry_point = 0;

    /* Read the image header */
    result = ota2_failsafe_app_read( flash_location, (uint8_t*) &header, 0, sizeof( header ) );
    if (result != WICED_SUCCESS)
    {
        return result;
    }

    /* Quick ELF header validity check */
    if (header.ident.magic != ELF_MAGIC_NUMBER)
    {
        return result;
    }

    /* Erase the application area */
    result = ota2_failsafe_app_area_erase( flash_location, &header );
    if (result != WICED_SUCCESS)
    {
        return result;
    }

#if 1
/*
 * The code provided by WICED tries to write from sflash directly to the physical_address which is not possibly with flash.
 * This code follows the implementation in wiced_waf_app_load() looping through each elf section and is simliar platform_copy_app_to_iflash() but
 * our code ignores the header that wiced_apps_read() is looking for (since it is missing).
 *
 */

    for ( i = 0; i < header.program_header_entry_count; i++ )
    {
    	wiced_bool_t is_elf;
    	//read the elf header
        unsigned long offset = header.program_header_offset + header.program_header_entry_size * (unsigned long) i;
        result = ota2_failsafe_app_read( flash_location, (uint8_t*) &prog_header, offset, sizeof( prog_header ) );

        if ( result != WICED_SUCCESS )
        {
        	return WICED_ERROR;
        }

        //only load code segments
        is_elf = ota2_failsafe_is_elf_segment_load( &prog_header );
        if ( is_elf == WICED_FALSE )
        {
            continue;
        }

        offset = prog_header.data_offset;
        int32_t size = prog_header.data_size_in_file;
        uint8_t* physical_address = (uint8_t*)prog_header.physical_address;
        uint8_t buff[ 64 ];

        while ( size > 0 )
        {
            uint32_t write_size = MIN( sizeof(buff), size);
            
            result = ota2_failsafe_app_read( flash_location, buff, offset, write_size );
            platform_write_flash_chunk( (uint32_t) physical_address, buff, write_size );

            //check our data written to flash is good.
            if (memcmp((char *)physical_address, buff, write_size))
            {
                offset = 0;
                return WICED_ERROR;
            }
            offset      	+= write_size;
            physical_address += write_size;
            size             -= write_size;
        }
        result = WICED_SUCCESS;
    }
#else // incorrect WICED implementation
    for ( i = 0; i < header.program_header_entry_count; i++ )
    {
        wiced_bool_t is_elf;
        unsigned long offset = header.program_header_offset + header.program_header_entry_size * (unsigned long) i;

        result = ota2_failsafe_app_read( flash_location, (uint8_t*) &prog_header, offset, sizeof( prog_header ) );
        is_elf = ota2_failsafe_is_elf_segment_load( &prog_header );
        if ( is_elf == WICED_FALSE )
        {
            continue;
        }

        result = ota2_failsafe_app_read( flash_location, (uint8_t*)prog_header.physical_address, prog_header.data_offset, prog_header.data_size_in_file );
        if (result != WICED_SUCCESS)
        {
            break;
        }
    }
#endif

    if (result == WICED_SUCCESS)
    {
        /* return the program entry point */
        *entry_point = header.entry;
    }

    return result;
}
0 Likes