2 Replies Latest reply on Sep 28, 2018 6:53 AM by rd185189_2046471

    bootloader/bootloadadle from external memory

    rd185189_2046471

      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
      
      /*****************************************************************************/
      
        • 1. Re: bootloader/bootloadadle from external memory
          geon

          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.

          1 of 1 people found this helpful
          • 2. Re: bootloader/bootloadadle from external memory
            rd185189_2046471

            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.