bootloader/bootloadadle from external memory

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

cross mob
Anonymous
Not applicable

Hi!

I'm implementing a bootloader/bootloadable project using a external memory to hold the new image. I was inspired by the project at Hackster.io​, but I implemented a little different, giving support to the functions

Well, I finished the project and at the final tests I'm dealing with some issues. The first one is about the "communication" between the bootloadable and bootloader using the Metadata area present at the flash memory of the microcontroller.

I don't know if I'm doing something wrong, but, for example, the bootloader  doesn't have information about the size of bootloadable image and etc.  This is a problem, but I solved this using the user space of Metadata to save the boltloadable image size.

Another question is about the operation of the Bootloader.

After the bootloadable firmware receives a new image, it calls the Bootloadable_Load() function, that calls the bootloader application.

The bootloader reads the external memory and writes the data read into the internal memory. Here are where I dealing with another problem: when the bootloader attempts to write a buffer into the internal flash memory, the function CySysFlashWriteRow are returning the CY_SYS_FLASH_PROTECTED value. Differently of the solution provided in Hackster.io, I'm using the default bootloader source code generated by the PSoC-Creator. So, I would like to know what I have to get a success result from  CySysFlashWriteRow.

Bellow I'm providing the source code of the functions CyBtldrCommStart, CyBtldrCommStop, CyBtldrCommReset, CyBtldrCommWrite and CyBtldrCommRead:

/**

*  @file   myCyBtldr.c

*  @brief  Cypress bootloader interface implementation

*  @author Rafael Dias <rd185189@ncr.com>

*  @date   feb-2018

*/

#include "cytypes.h"

#include "EMS_SPI.h"

#include "Flash_AT25DN011.h"

#include "Bootloader_PVT.h"

#include "util.h"

#include "Bootloader.h"

#include "Bootloader_Status.h"

/*****************************************************************************/

typedef enum _TBootLoaderState

{

    BTLD_ST_CHECKSUM,

    BTLD_ST_REPORT_SIZE,

    BTLD_ST_APP_STATUS,

    BTLD_ST_ERASE,

    BTLD_ST_SYNC,

    BTLD_ST_APP_ACTIVE,

    BTLD_ST_DATA,

    BTLD_ST_ENTER,

    BTLD_ST_PROGRAM,

    BTLD_ST_GET_ROW_CHKSUM,

    BTLD_ST_EXIT,

    BTLD_ST_GET_METADATA,

    BTLD_ST_VERIFY_FLS_ROW,

}TBootLoaderState;

#define TBOOT_PREAMBLE_SIZE (3L)

/*****************************************************************************/

/* local data types */

typedef struct _TBootLoaderData

{

    uint32_t            dwCurAddr;

    TBootLoaderState    dwState;

    uint32_t            dwTotalReadBytes;   

}TBootLoaderData;

/*****************************************************************************/

/* module static members                                                     */

static TSwSpi*  xSpi = NULL; 

static TBootLoaderData xBootLoaderData; 

/*****************************************************************************/

static uint16 MyBootLoaderCalcPacketChecksum(const uint8 buffer[], uint16 size)

{

    #if(0u != Bootloader_PACKET_CHECKSUM_CRC)

        uint16 CYDATA crc = Bootloader_CRC_CCITT_INITIAL_VALUE;

        uint16 CYDATA tmp;

        uint8  CYDATA i;

        uint16 CYDATA tmpIndex = size;

        if(0u == size)

        {

            crc = ~crc;

        }

        else

        {

            do

            {

                tmp = buffer[tmpIndex - size];

                for (i = 0u; i < 8u; i++)

                {

                    if (0u != ((crc & 0x0001u) ^ (tmp & 0x0001u)))

                    {

                        crc = (crc >> 1u) ^ Bootloader_CRC_CCITT_POLYNOMIAL;

                    }

                    else

                    {

                        crc >>= 1u;

                    }

                    tmp >>= 1u;

                }

                size--;

            }

            while(0u != size);

            crc = ~crc;

            tmp = crc;

            crc = ( uint16 )(crc << 8u) | (tmp >> 8u);

        }

        return(crc);

    #else

        uint16 CYDATA sum = 0u;

        while (size > 0u)

        {

            sum += buffer[size - 1u];

            size--;

        }

        return(( uint16 )1u + ( uint16 )(~sum));

    #endif /* (0u != Bootloader_PACKET_CHECKSUM_CRC) */

}

/*****************************************************************************/

void CyBtldrCommStart(void)

{

    if ( NULL == xSpi )

    {

        xSpi = GetFlashInterface( FlashAT25DN011 );

    }

   

    if ( xSpi )

    {

        xBootLoaderData = (TBootLoaderData)

                            {

                                .dwCurAddr          = BOOT_SECTION_INIT_ADDRESS,

                                .dwState            = BTLD_ST_ENTER,

                                .dwTotalReadBytes   = 0,                               

                            };

    }

    return;

}

/*****************************************************************************/

void CyBtldrCommStop (void)

{

    if ( NULL != xSpi )

    {

        xSpi->deinit( xSpi );

        xSpi = NULL;

    }

   

    return;

}

/*****************************************************************************/

void CyBtldrCommReset( void )

{

    // TBD

    return;

}

/*****************************************************************************/

cystatus CyBtldrCommWrite( uint8* buffer, uint16 size, uint16* count, uint8 timeOut )

{

    (void)buffer;

    (void)size;

    (void)count;

    (void)timeOut;

    uint32_t dwRet = CYRET_SUCCESS;

   

    if ( Bootloader_SOP == buffer[Bootloader_SOP_ADDR] )

    {

        if ( Bootloader_EOP == buffer[Bootloader_EOP_ADDR(*count)] )

        {

            if ( CYRET_SUCCESS != buffer[Bootloader_CMD_ADDR] )

            {

                dwRet = buffer[Bootloader_CMD_ADDR];

               

                xBootLoaderData = (TBootLoaderData)

                                    {

                                        .dwCurAddr          = BOOT_SECTION_INIT_ADDRESS,

                                        .dwState            = BTLD_ST_ENTER,

                                        .dwTotalReadBytes   = 0,                               

                                    };               

            }

        }

    }

   

    return dwRet;

}

/*****************************************************************************/

#ifdef __GNUC__

#pragma GCC push_options

#pragma GCC optimize ("O0")

#endif

cystatus CyBtldrCommRead ( uint8* buffer, uint16 size, uint16* count, uint8 timeOut )

{

    (void)timeOut;

    uint32_t dwRet = CYRET_UNKNOWN;

    extern const uint32 CYCODE Bootloader_SizeBytes;

   

    Bootloader_Status_Write(!Bootloader_Status_Read());

   

    if ( NULL == xSpi )

    {

        dwRet = CYRET_MEMORY;

    }

    else

    {

        if ( NULL != buffer )

        {

            if ( size > 0 )

            {

                if ( NULL != count )

                {

                    switch( xBootLoaderData.dwState )

                    {

                        case BTLD_ST_ENTER:

                        {

                            buffer[Bootloader_SOP_ADDR] = Bootloader_SOP;                           // required parameter

                            buffer[Bootloader_CMD_ADDR] = Bootloader_COMMAND_ENTER;

                            buffer[Bootloader_SIZE_ADDR]    = 0;

                            buffer[Bootloader_SIZE_ADDR+1]  = 0;

                            uint16_t uiCRC = MyBootLoaderCalcPacketChecksum( &buffer[Bootloader_SOP_ADDR],

                                                    Bootloader_DATA_ADDR );

                           

                            buffer[Bootloader_CHK_ADDR(0)]    =  LOBYTE( uiCRC );

                            buffer[Bootloader_CHK_ADDR(0)+1]  =  HIBYTE( uiCRC );

                            buffer[Bootloader_EOP_ADDR(0)] = Bootloader_EOP;

                            *count = Bootloader_MIN_PKT_SIZE;

                            dwRet = CYRET_SUCCESS;

                           

                            xBootLoaderData.dwState = BTLD_ST_PROGRAM;

                           

                            break;

                        }

                       

                        case BTLD_ST_PROGRAM:

                        {

                            uint32_t dwBootloadableSizeBytes = 59776L/*Bootloader_GetMetadata( Bootloader_GET_BTLDB_USER_DATA, 0 )*/;

                            if ( dwBootloadableSizeBytes <= xBootLoaderData.dwTotalReadBytes )

                            {

                                buffer[Bootloader_SOP_ADDR]         = Bootloader_SOP;                           // required parameter

                                buffer[Bootloader_CMD_ADDR]         = Bootloader_COMMAND_EXIT;

                                buffer[Bootloader_SIZE_ADDR]        = 0;

                                buffer[Bootloader_SIZE_ADDR+1]      = 0;

                                uint16_t uiCRC = MyBootLoaderCalcPacketChecksum( &buffer[Bootloader_SOP_ADDR],

                                                        Bootloader_DATA_ADDR );

                               

                                buffer[Bootloader_CHK_ADDR(0)]      =  LOBYTE( uiCRC );

                                buffer[Bootloader_CHK_ADDR(0)+1]    =  HIBYTE( uiCRC );

                                buffer[Bootloader_EOP_ADDR(0)]      = Bootloader_EOP;

                                *count = Bootloader_MIN_PKT_SIZE;

                                dwRet = CYRET_SUCCESS;

                               

                                xBootLoaderData.dwState = BTLD_ST_EXIT;

                            }

                            else

                            {

                                uint16_t uiReadBytes;

                                uint16_t uiBufferTotalBytes = 0;

                               

                                buffer[Bootloader_SOP_ADDR] = Bootloader_SOP;                           // required parameter

                                buffer[Bootloader_CMD_ADDR] = Bootloader_COMMAND_PROGRAM;

                               

                                uiReadBytes = xSpi->read(   xSpi,

                                                            xBootLoaderData.dwCurAddr,

                                                            &buffer[Bootloader_DATA_ADDR + TBOOT_PREAMBLE_SIZE],

                                                            Bootloader_FROW_SIZE );

                                if ( uiReadBytes )

                                {

                                    uint32_t dwApplicationRow;

                                    dwApplicationRow = /*Bootloader_SizeBytesAccess*/ Bootloader_SizeBytes / CYDEV_FLS_ROW_SIZE;

                                    if (/*Bootloader_SizeBytesAccess*/ Bootloader_SizeBytes % CYDEV_FLS_ROW_SIZE)

                                        dwApplicationRow++;

                                   

                                    dwApplicationRow += (xBootLoaderData.dwTotalReadBytes / CYDEV_FLS_ROW_SIZE);

                                    if (xBootLoaderData.dwTotalReadBytes % CYDEV_FLS_ROW_SIZE)

                                        dwApplicationRow++;

                                   

                                    buffer[Bootloader_DATA_ADDR]    = 0 /*Bootloader_SizeBytes / CYDEV_FLS_ROW_SIZE*/;

                                    buffer[Bootloader_DATA_ADDR+1]  = LOBYTE( dwApplicationRow );

                                    buffer[Bootloader_DATA_ADDR+2]  = HIBYTE( dwApplicationRow );

                                    xBootLoaderData.dwTotalReadBytes += uiReadBytes;

                                    uiBufferTotalBytes = uiReadBytes + TBOOT_PREAMBLE_SIZE;

                                    buffer[Bootloader_SIZE_ADDR]    = LOBYTE( uiBufferTotalBytes );

                                    buffer[Bootloader_SIZE_ADDR+1]  = HIBYTE( uiBufferTotalBytes );

                                    uint16_t uiCRC = MyBootLoaderCalcPacketChecksum(    buffer,

                                                                                        uiBufferTotalBytes + Bootloader_DATA_ADDR );

                                   

                                    buffer[Bootloader_CHK_ADDR(uiBufferTotalBytes)]    =  LOBYTE( uiCRC );

                                    buffer[Bootloader_CHK_ADDR(uiBufferTotalBytes)+1]  =  HIBYTE( uiCRC );

                                   

                                    *count = uiBufferTotalBytes + Bootloader_MIN_PKT_SIZE;

                                   

                                   

                                    dwRet = CYRET_SUCCESS;

                                }

                                else

                                {

                                    dwRet = CYRET_MEMORY;

                                }

                               

                                buffer[Bootloader_EOP_ADDR(uiBufferTotalBytes)] = Bootloader_EOP;

                            }

                           

                            break;

                        }

                       

                        case BTLD_ST_EXIT:

                        {

                            buffer[Bootloader_SOP_ADDR] = Bootloader_SOP;                           // required parameter

                            buffer[Bootloader_CMD_ADDR] = Bootloader_COMMAND_EXIT;

                            buffer[Bootloader_SIZE_ADDR]    = 0;

                            buffer[Bootloader_SIZE_ADDR+1]  = 0;

                            buffer[Bootloader_CHK_ADDR(0)]    =  0;

                            buffer[Bootloader_CHK_ADDR(0)+1]  =  0;

                            buffer[Bootloader_EOP_ADDR(0)] = Bootloader_EOP;

                            *count = Bootloader_MIN_PKT_SIZE;

                            dwRet = CYRET_SUCCESS;

                           

                            xBootLoaderData.dwState = BTLD_ST_ENTER;

                           

                            break;

                        }

                       

                        default:

                        break;

                    }

                }

            }

        }

    }

    return dwRet;   

}

#ifdef __GNUC__

#pragma GCC pop_options

#endif

/*****************************************************************************/

0 Likes
1 Solution
GeonaP_26
Moderator
Moderator
Moderator
250 solutions authored 100 solutions authored 50 solutions authored

CySysFlashWriteRow returns CY_SYS_FLASH_PROTECTED when the specified flash row is protected. Please remove flash protection settings from the Flash Security tab of cydwr window. For more details, please refer to section: Flash Security Editor.

PSoC Creator provides a code example: BLE_OTA_External_Memory_Bootloader where the Bootloader component is configured to work with the custom interface based on the SCB component. This project replaces a bootloadable image stored in the internal memory with a bootloadable image that is stored in the external memory. Hope it helps.

View solution in original post

2 Replies
GeonaP_26
Moderator
Moderator
Moderator
250 solutions authored 100 solutions authored 50 solutions authored

CySysFlashWriteRow returns CY_SYS_FLASH_PROTECTED when the specified flash row is protected. Please remove flash protection settings from the Flash Security tab of cydwr window. For more details, please refer to section: Flash Security Editor.

PSoC Creator provides a code example: BLE_OTA_External_Memory_Bootloader where the Bootloader component is configured to work with the custom interface based on the SCB component. This project replaces a bootloadable image stored in the internal memory with a bootloadable image that is stored in the external memory. Hope it helps.

Anonymous
Not applicable

Thanks!

I forgot the Flash memory protection. I left the Flash memory unprotected and I was able to write to it.

Now I am facing another problem, but I think it is better to open another thread just to deal with it.

0 Likes