3 Replies Latest reply on Mar 16, 2020 11:07 AM by RuLe_1240116

    PSOC5LP Bootloader - Launcher Only with external EEPROM memory

    RuLe_1240116

      Hi Cypress folks,

       

      Recently had a thread here, which got me 95% there, but I'm still struggling to get things to work:

      PSOC5LP / Custom bootloader with external I2C EEPROM slave device

       

      The idea was to develop a very simple bootloader for a PSOC5LP from an external EEPROM without using any of the "official" bootloader protocols or messaging. Just read from external I2C EEPROM, write to flash, reboot the chip into new code.  Was pointed in the right direction to create a "custom launcher", which I think is the right solution, but I'm having some difficulty.  Thanks in advance for any advice you can provide.

       

      Here's the current process:

      1. Software is compiled. Generates Intel HEX, .cyacd, etc.
      2. External app converts .cyacd to BIN file. This cuts the size in half (cyacd is ASCII-encoded HEX).  
      3. External app writes contents of BIN file to EEPROM
      4. Micro powers up into bootloader.
      5. Bootloader checks state of a flag indicating if new software update is pending.  If not, it exits to bootloadable.  If it's pending, it reads the contents of EEPROM containing new firmware and writes to flash a page at a time until all rows are written, then exits to bootloadable.
      6. No metadata is updated during this process. All application validation is disabled.
      7. In theory, we're done, and new code begins executing. 

       

      Problem: 

      1. All flash is written successfully, and the application exits to bootloadable.
      2. The chip resets back to bootloader immediately, indicating a problem with the update process.

       

      Questions:

      1. Is the endianness of the cyacd file generated is big endian (Format of .cyacd File for PSoC® 3 or PSoC 5LP Bootloader - KBA216138).  Do I need to convert this to little endian format for PSOC5LP? If so, is the conversion over 32 bits at a time?
      2. Does the metadata need to be updated with the Bootloadable Application Start Routine Address, or does this happen naturally, as the bootloadable code begins right after the bootloader, as shown below (Bootloader and Bootloadable 002-21055, p. 45)?
      3. For any remaining flash not part of the new firmware image, can we simply write 0x00?
      4. Is it possible that with a "Launcher only" bootloader that the bootloader is not started until called explicitly via Bootloader_Load() from the bootloadable application, or does the chip reset directly to the bootloader?

       

       

      Here is the code:

      /* Start of bootloader (this executes after reset) */
      
      int main (void)
      {
          CyGlobalIntEnable;
          
          /* Check if we had a software update request */
          uint16 bootload_request = EEPROM_Read_U16(ROM_ADDR_SWUPDATE_PENDING);
          if (bootload_request == SWUPDATE_PENDING_KEY) {
              EEPROM_Write_U16(ROM_ADDR_SWUPDATE_PENDING, 0x0000);
              
              /* Get number of pages for firmware image */
              uint16 SWUpdateNumPages = EEPROM_Read_U16(ROM_ADDR_SWUPDATE_NUM_PAGES);
              
          #if __DEBUG__    
              SWUpdateNumPages = 204; /* Number of pages in 'bin' file generated from cyacd */
          #endif
      
      
              /* Start bootloader process */
              /* This function exits inside the loop */
              for(;;)
              {           
                  /* Specifies the ID of the array that contains the sector to be erased.
                     This parameter determines whether to program flash or EEPROM array. 
                     The number of arrays that are flash and the number of arrays that 
                     are EEPROM are device specific. */
                  uint8 flashArrayId = 0;
                  uint16 flashRowAddress = BOOTLOADABLE_START_ROW;
                  
                  /* Write all page data from EEPROM */
                  for (uint16 eepromPage = 0; eepromPage < SWUpdateNumPages; eepromPage++) {
                      /* Increment the arrayId and reset rowAddress*/ 
                      /* Refer to System Reference Guide, Flash Memory Organization */
                      if (flashRowAddress == CY_FLASH_NUMBER_ROWS) {
                          flashArrayId++;
                          if (flashArrayId > (CY_FLASH_NUMBER_ARRAYS - 1)) {
                              /* Max ArrayId error */
                          }
                          flashRowAddress = 0x0000;
                      }
                      
                      /* Read EEPROM page bin data, or all zero */
                      ST_STATUS eeprom_status;
                      uint32 eeprom_rd_addr = ROM_OFST_SWUPDATE_BIN + (eepromPage * EEPROM_PAGE_SIZE);
                      if (eeprom_rd_addr < (SWUpdateNumPages * EEPROM_PAGE_SIZE)) {
                          eeprom_status = EEPROM_ReadBytes(eeprom_rd_addr, EEPROM_PAGE_SIZE, g_FlashRowData);
                      }
                      else {
                          /* Write zero data to flash */
                          for (uint16 b = 0; b < CY_FLASH_SIZEOF_ROW; b++) {
                              g_FlashRowData[b] = 0x00;
                          }
                      }
                      
                      if (eeprom_status == ST_OK) {
                          /* Perform flash write operation */
                          CySetTemp();
                          cystatus WriteRowStatus = CyWriteRowData(flashArrayId, flashRowAddress, g_FlashRowData);
                          if (WriteRowStatus == CYRET_SUCCESS) {
                              /* Flash write success */
                              #if __DEBUG__
                                  DEBUG_TP(10);         
                              #endif 
                          }
                          else if (WriteRowStatus == CYRET_LOCKED) {
                              #if __DEBUG__
                                  DEBUG_TP(1);                
                              #endif 
                          }
                          else if (WriteRowStatus == CYRET_CANCELED) {
                              #if __DEBUG__
                                  DEBUG_TP(2);
                              #endif                     
                          }
                          else if (WriteRowStatus == CYRET_UNKNOWN) {
                              #if __DEBUG__
                                  DEBUG_TP(3);               
                              #endif                     
                          }
                          else {
                              #if __DEBUG__
                                  DEBUG_TP(4);                  
                              #endif 
                          }
                      }
                      else {
                          /* EEPROM read error */
                      }
                      flashRowAddress++;
                  }
                  CyDelay(100);
      
      
                  /* Increment software update counter */
                  uint16 NumUpdates = EEPROM_Read_U16(ROM_ADDR_SYS_NUM_UPDT);
                  EEPROM_Write_U16(ROM_ADDR_SYS_NUM_UPDT, (NumUpdates + 1));
                  
                  #if __DEBUG__
                      DEBUG_TP(20);                                   
                  #endif         
                  
                  /* We are done, exit to bootloadable */
                  BOOTLOADER_Exit(BOOTLOADER_EXIT_TO_BTLDB);
              }        
          }        
          else {
              /* Run the app */
              BOOTLOADER_Exit(BOOTLOADER_EXIT_TO_BTLDB);
          }
      }
      
        • 1. Re: PSOC5LP Bootloader - Launcher Only with external EEPROM memory
          RuLe_1240116

          Some answers to my own question (for anyone reading this thread):

           

          1. Is the endianness of the cyacd file generated is big endian (Format of .cyacd File for PSoC® 3 or PSoC 5LP Bootloader - KBA216138).  Do I need to convert this to little endian format for PSOC5LP? If so, is the conversion over 32 bits at a time?
            1. Endianness is little-endian on PSOC5LP, but if you attach to running target and look at the memory window, you can verify that the memory written after the bootload process is the same as the memory in the device. I am writing the contents of the .cyacd in the same order (big endian).  
          2. Does the metadata need to be updated with the Bootloadable Application Start Routine Address, or does this happen naturally, as the bootloadable code begins right after the bootloader, as shown below (Bootloader and Bootloadable 002-21055, p. 45)?
            1. I have not updated any of the metadata, and have not had issues with this.  Would of course be useful to know whether this is required or not.
          3. For any remaining flash not part of the new firmware image, can we simply write 0x00?
            1. This looks to be the case.
          4. Is it possible that with a "Launcher only" bootloader that the bootloader is not started until called explicitly via Bootloader_Load() from the bootloadable application, or does the chip reset directly to the bootloader?
            1. I still don't know the answer to this.  It appears that in "launcher only" reset jumps to 0x0000 and executes the bootloader. This might also be true with any other bootloader configurations as well.

           

          One additional thing to note is that the bootloadable component has an option for "manual application image placement" where you can add a little more space if your bootloader will grow. This will avoid overwriting bootloader memory accidentally, or running into write protect errors if the bootloader size changes after programming with a Miniprog.

          • 2. Re: PSOC5LP Bootloader - Launcher Only with external EEPROM memory
            BiBi_1928986

            Hello RuLe.

             

            In Step 2, app converts .cyacd to bin, is this a custom app, or Cypress supplied?  I've used WINHEX editor to do this in the past.

             

            If you haven't already, take a look into \PSoC Creator\cybootloaderutils\cybtldr_parse.c  to see if there's something missing.

             

            A 'normal' bootloader writes something into 5LP EEPROM, Sector 0.  I don't know if the bootable looks at this or not.  Some missing metadata?

             

            [edit]

            Have you tried building both bootloader(launcher) and bootloadable, as 'release' instead of 'debug'?  Not sure if this will have any effect, but worth a try.

             

            Bill

            • 3. Re: PSOC5LP Bootloader - Launcher Only with external EEPROM memory
              RuLe_1240116

              Hi BiBi,

               

              This is a custom app.  It simply converts to data to binary, and enables writing the binary image to EEPROM. 

               

              I've read through cybtldr_parse.  Doesn't look like I'm missing anything obvious from that.  I completely ignore the checksum for each row, and just compute a single checksum for the whole image.

               

              A 'normal' bootloader writes something into 5LP EEPROM, Sector 0.  I don't know if the bootable looks at this or not.  Some missing metadata?

               

              Yeah, I'm not sure what that is, or what metadata needs to be updated.  I'm able to successfully bootload the same application, but if I change the version number, for example, it will fail and keep resetting into the bootloader. I feel like I'm missing some important piece of metadata or something during the process.

               

              I will try building as "release".  That's a good idea.