6 Replies Latest reply on Jun 12, 2019 6:38 AM by GeonaM_26

    re-program from within application - continued

    PeSi_1583586

      Following my request for support with problems re-programming a PSoC 5 device (CY8C5888) from within the application (see Re-program from within application) I have discovered that what I had marked as the correct answer (the introduction of more delay before starting the bootloader program) does not fix the problem.

      As mentioned in my previous discussion my bootloader is based closely on the Bootloader Host utility in PSoc Creator.

      If I run my program in Debug mode then programming is successful. However running it in Release mode programming fails.

      I have compared the USB transactions for the PSoC Creator bootloader, my bootloader in Debug mode and my bootloader in Release mode. I have filtered out the Endpoint0 transactions to show only the Endpoint 1 and 2 data transfers.

      All three start with:

      OUT transaction    6    1    ACK    FS    64 bytes (01 38 00 00 C7 FF 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00)   

      IN transaction    6    2    ACK    FS    64 bytes (01 00 08 00 69 10 16 2E 00 3C 01 01 FC FE 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00)   

      which I understand to be the command to enter the bootloader.

      This is followed by:

      OUT transaction    6    1    ACK    FS    64 bytes (01 33 01 00 00 CB FF 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00)   

      OUT transaction    6    1    ACK    FS    64 bytes (01 33 01 00 00 CB FF 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00)   

      which is not present in the PSoC creator version. I understand this to be the command to get info about the app status which according to comments in the header file is only supported in a multi-app bootloader - this despite my program calling Bootloader_Utils.CyBtldr_Program() with appID = 1

       

      Both PSoc Creator and my debug program continue with:

      OUT transaction    6    1    ACK    FS    64 bytes (01 32 01 00 00 CC FF 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00)    

      IN transaction    6    2    ACK    FS    64 bytes (01 00 04 00 2C 00 FF 00 D0 FE 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00)     (Get number of Flash Rows in target device)

      The both then continue to write data to the device.

       

      However, in Release mode of my program the Get Info command is immediately followed with:

      OUT transaction    6    1    ACK    FS    64 bytes (01 3B 00 00 C4 FF 17 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00)    - Exit Bootloader, with no response. No further USB transactions take place.

       

      Suspecting the problem may be due to program optimisation I have set the compilation mode of the Bootloader_Utils.dll to no optimisation, but this makes no difference.

      Can anyone shed ny light on what the problem is, and provide a solution

        • 1. Re: re-program from within application - continued
          GeonaM_26

          Please let us know the bootloader response for Get Application Status (0x33) command in both Debug and Release modes.

          • 2. Re: re-program from within application - continued
            PeSi_1583586

            The response is the same in both Debug and release modes :

            IN transaction    1    2    ACK    FS    64 bytes (01 05 00 00 FA FF 17 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00)  

            • 3. Re: re-program from within application - continued
              GeonaM_26

              Response of 0x05 (BOOTLOADER_ERR_CMD) says that the command is not recognized. I assume that the project is a single application bootloader. I understand that you have disabled the optimization. Please use volatile qualifier for variables. Can you share the host application project so that we can take a look.

              • 4. Re: re-program from within application - continued
                PeSi_1583586

                Yes, the project is a single application bootloader, hence I was puzzled as to why the GetApplicationStatus was being called in the first place, and wondered whether that would be a pointer to the actual problem.

                The project is divided into two parts - the bootloader utilities (from PSoC Creator) and the main application project.

                The main application includes a lot of code which is irrelevant to programing the device and contains propretary information.

                I have attached a zip file of the Boottloader_Utils project from Visual Studio 2017 and the source files used from the PSoC Creator folder in 'Program Files' (used to build the bootloader_Utils.dll) which, as far as I am aware are unmodified from the PSoC Creator 4.2 installation. - you will need to change the paths to the source files to match the location of the source files

                As these files were as supplied by Cypress I have not added any 'volatile' qualifiers to any of the variables.

                It will take me some time to prune down the main application to a working project with only the 'ReProgram' function present, but I thought it might be useful if you could look at the bootloaderUtils project first.

                Thank you for your help

                • 5. Re: re-program from within application - continued
                  PeSi_1583586

                  I have analysed the source code for the USB Bootloader Utils located in C:\Program Files (x86)\Cypress\PSoC Creator\4.2\PSoC Creator\cybootloaderutils, and have found the problem to be due to a bug in the definition of RunActionV0() in the file :program files (x86)/cypress/psoc creator/4.2/psoc creator/CyBootloaderUtils/cybtldr_api2.c

                  My data file (generated by PSoC Creator 4.2) has the extension .Cyacd which defines it as being version 0 and hence will execute RunActionV0 rather than .cyacd2 which would have defined it as version 1 which would have caused it to execute RunActionV1.

                  Below is a copy of the runActionV0 function with comments showing my analysis of the program.

                  (Comments added by me are delimited by // and highlighted in bold Green as opposed to the original comments which are delimited by /*...........*/)

                   

                  int RunAction_v0(CyBtldr_Action action, uint32_t lineLen, uint8_t* line, uint8_t appId,

                      const uint8_t* securityKey, CyBtldr_CommunicationsData* comm, CyBtldr_ProgressUpdate* update)

                  {

                      const uint8_t INVALID_APP = 0xFF;

                      uint32_t blVer = 0;

                      uint32_t siliconId = 0;

                      uint8_t siliconRev = 0;

                      uint8_t chksumtype = SUM_CHECKSUM;

                      uint8_t isValid;

                      uint8_t isActive;

                      int err;

                      uint8_t bootloaderEntered = 0;

                   

                   

                      err = CyBtldr_ParseHeader(lineLen, line, &siliconId, &siliconRev, &chksumtype); // header is 2E1610690000 giving chksum=0, siliconId=2E161069 siliconRev=0 returns CYRET_SUCCESS 

                      if (CYRET_SUCCESS == err) // true

                      {

                          CyBtldr_SetCheckSumType(chksumtype);

                   

                          err = CyBtldr_StartBootloadOperation(comm, siliconId, siliconRev, &blVer, securityKey); // sends start bootloader command

                          bootloaderEntered = 1;

                   

                          appId -= 1; /* 1 and 2 are legal inputs to function. 0 and 1 are valid for bootloader component */ // we enter with 1 (as it is a single application) so decrement to 0

                          if (appId > 1)// false - skip the next 3 lines

                          {

                              appId = INVALID_APP;

                          }

                   

                          if ((CYRET_SUCCESS == err) && (appId != INVALID_APP)) // true

                          {

                              /* This will return error if bootloader is for single app */

                              err = CyBtldr_GetApplicationStatus(appId, &isValid, &isActive); //sends GetAppStatus command which returns response CYBTLDR_STAT_ERR_CMD and err = 0x4005  because it is for single app

                   

                              /* Active app can be verified, but not programmed or erased */

                              if (CYRET_SUCCESS == err && VERIFY != action && isActive) // false - skip next 4 lines

                              {

                                  /* This is multi app */

                                  err = CYRET_ERR_ACTIVE;

                              }

                  // See note 2 below

                          }

                      }

                  //Note 2a

                      while (CYRET_SUCCESS == err) // false - err is 0x4005 so skip programming data

                      {

                          if (g_abort)

                          {

                              err = CYRET_ABORT;

                              break;

                          }

                   

                          err = CyBtldr_ReadLine(&lineLen, line);

                          if (CYRET_SUCCESS == err)

                          {

                              err = ProcessDataRow_v0(action, lineLen, line, update);

                          }

                          else if (CYRET_ERR_EOF == err)

                          {

                              err = CYRET_SUCCESS;

                              break;

                          }

                      }

                   

                      if (err == CYRET_SUCCESS) // false - err is still 0x4005

                      {

                          if (PROGRAM == action && INVALID_APP != appId)

                          {

                              err = CyBtldr_GetApplicationStatus(appId, &isValid, &isActive);

                   

                              if (CYRET_SUCCESS == err)

                              {

                                  /* If valid set the active application to what was just programmed */

                                  /* This is multi app */

                                  err = (0 == isValid)

                                      ? CyBtldr_SetApplicationStatus(appId)

                                      : CYRET_ERR_CHECKSUM;

                              }

                              else if (CYBTLDR_STAT_ERR_CMD == (err ^ (int)CYRET_ERR_BTLDR_MASK))

                              {

                                  /* Single app - restore previous CYRET_SUCCESS */

                                  err = CYRET_SUCCESS;

                              }

                          }

                          else if (PROGRAM == action || VERIFY == action)

                          {

                              err = CyBtldr_VerifyApplication();

                          }

                          CyBtldr_EndBootloadOperation();

                      }

                      else if (CYRET_ERR_COMM_MASK != (CYRET_ERR_COMM_MASK & err) && bootloaderEntered) // true

                      {

                          CyBtldr_EndBootloadOperation(); // sends end bootloader command

                      }

                      return err;

                  }

                  As you will see, when the program gets to the loop for programming data into the device ( note 2a), err still has a value of 0x4005 returned by the GetStatus command, and so skips programming data into the device.

                   

                  Note 2:

                  At this point in the program, the equivalent function (RunAction) in cybtldr_api2.c included with version 3.3 of psoc creator includes the following lines

                   

                   

                              else if (CYBTLDR_STAT_ERR_CMD == (err ^ (int)CYRET_ERR_BTLDR_MASK)) //true

                              {

                                  /* Single app - restore previous CYRET_SUCCESS */

                                  err = CYRET_SUCCESS; // programming loop will now be executed

                              }

                   

                  Note 3:

                  I suspect that the version of the dll I was using in debug mode was compiled using the files from psoc creator version 3.3

                   

                  Note 4:

                  I am now using a dll created using the files included with psoc creator version 3.3 in the Release mode of my program and this now appears to be working fine!

                   

                  Would you please confirm that my analysis is correct and there is indeed a bug.

                   

                  As I stated earlier I am now using a DLL from version 3.3 of PSoC Creator on a project created in version 4.2 for a PSoc 5 device. Is this ok, or will it present other problems?

                  Is there a fix for this bug?

                  Given that I am creating a single app bootloader, is it possible to prevent command 33 from being called and thus avoid the inevitable generation of an error?

                  • 6. Re: re-program from within application - continued
                    GeonaM_26

                    Get Application Status (0x33) is a dual-application bootloader only command. If single application bootloader is used, user should not use this command.