- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
/*****************************************************************************/
Solved! Go to Solution.
- Labels:
-
PSoC 4 Architecture
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.