2 Replies Latest reply on Aug 31, 2018 2:43 PM by keng_3159731

    Bootloadable_Load() Function reboots to bootloader, but then launches bootloadable application

    keng_3159731

      Hello, I'm trying to implement an OTA Bootloader via BLE.

      I have created a simple test project where I can successfully trigger a reboot from the Bootloadable application into the Bootloader using the Bootloadable_Load() function, using the same method as given in one of the Cypress examples.

       

      void BootloaderSwitch()
      {
          if (Bootloader_Service_Activation_Read() == 0)
          {
              CyDelay(100);
              if (Bootloader_Service_Activation_Read() == 0)
              {
                  DBG_PRINTF("Bootloader activation button pressed \r\n");
                  DBG_PRINTF("Switching to bootloader application... \r\n");
                  CyDelay(500);
                  
                  
                  CyBle_Shutdown(); /* stop all ongoing activities */
                  CyBle_ProcessEvents(); /* process all pending events */
                  CyBle_SetState(CYBLE_STATE_STOPPED);
                  CySysWdtUnlock();
                  CySysWdtDisable(WDT_COUNTER_MASK);
                  CyGlobalIntDisable;
                  Bootloadable_Load();
              }
          }
      }
      

       

      In my simple test project, when I call the Bootloadable_Load() function, the target will reboot into the Bootloader application and stay in the Bootloader, as expected.

       

      Now, as I'm trying to integrate the bootloader functionality into an existing BLE project, the Bootloadable_Load() function will cause a reboot into the Bootloader application, but it does not stay in the Bootloader and launches right back into the Bootloadable application!

       

      I have compared the existing project and the simple test project, and have not been able to figure out any differences in implementation.

       

      Any insights would be appreciated.

        • 1. Re: Bootloadable_Load() Function reboots to bootloader, but then launches bootloadable application
          keng_3159731

          To help shed some light on this issue which remains open, I instrumented the Bootloader_Start() function in the auto-generated Bootloader.c (version 1.5) file with some serial output.  As well as I can follow the code, it appears that the function will check the validity of the Bootloadable application (or applications), then will either hang waiting for host communication or launch the Bootloadable application, depending on the value of the Bootloader_GET_RUN_TYPE macro.

           

          The following code (with additional serial commands) will cause the Bootloader to wait forever for host communication if  Bootloader_GET_RUN_TYPE == Bootloader_SCHEDULE_BTLDR.

              UART_PutString("Bootloader Run Type ");
              UART_PutHexInt(Bootloader_GET_RUN_TYPE);
              UART_PutString("\r\n");
              
              if ((Bootloader_GET_RUN_TYPE == Bootloader_SCHEDULE_BTLDR) 
                  #if (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)        
                          || (CYRET_SUCCESS != validApp)
                  #endif        
                  )
              {
                  UART_PutString("Bootloader Host");
                  
                  Bootloader_SET_RUN_TYPE(Bootloader_SCHEDULE_BTLDR_INIT_STATE);
          
          
                  Bootloader_HostLink(Bootloader_WAIT_FOR_COMMAND_FOREVER);
              }
          

           

           

          If the Bootloader does not hang waiting for the host communication, the following code will launch the Bootloadable application.

          #if (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)             
              /* Schedule Bootloadable application and perform software reset */
              UART_PutString("Bootloader Launch");
              Bootloader_LaunchApplication();
          #endif /*(CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)*/ 
          

           

          static void Bootloader_LaunchApplication(void) CYSMALL \
                              
          {
              /* Schedule Bootloadable to start after a reset */
              Bootloader_SET_RUN_TYPE(Bootloader_SCHEDULE_BTLDB);
          
          
              CySoftwareReset();
          }
          #endif /*(CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)*/
          

           

           

          Here are the values of the different Bootloader Schedule defines, as found in the Bootloader.h file.

          /* Mask used to indicate starting application */
          #define Bootloader_SCHEDULE_BTLDB             (0x80u)
          #define Bootloader_SCHEDULE_BTLDR             (0x40u)
          #define Bootloader_SCHEDULE_MASK              (0xC0u)
          #define Bootloader_SCHEDULE_BTLDR_INIT_STATE  (0x00u)
          

           

           

          In the example project that works correctly and stays in the Bootloader when triggered, I can see the following through the serial output.

          On Initial Restart:                    Bootloader Run Type 0000

          On Bootloader Trigger:           Bootloader Run Type 0040

           

          In my project I'm trying to integrate the Bootloader into, I can see the following serial output when triggering the Bootloader.

          On Initial Restart:                    Bootloader Run Type 0000

          On Bootloader Trigger:           Bootloader Run Type 0000

           

          So there is something in the integration project that seems to be resetting the Bootloader_GET_RUN_TYPE return value to 0x00, instead of the correct value of 0x40 which would trigger the Bootloader to hang waiting for host communication.  I have found this post and this other post, but they seem to be experiencing power issues, which this project is not.  I can load the test project and see the correct operation, and load the integration project, and see constant booting into the Bootloadable application.

          The Bootloadable component of the integration project is using the checksum exclusion area to store some data, but when I add the same code to the working project, it still works.

           

          Any information, or perspective on where to look next would be appreciated.

           

           

          • 2. Re: Bootloadable_Load() Function reboots to bootloader, but then launches bootloadable application
            keng_3159731

            I discovered the issue while adding more serial output to the Bootloadable_Load() function.

             

            The CyDelay() function was causing the target to reboot prior to calling the Bootloadable_Load() function to set the reboot flag.

            Since a reboot was expected anyway, the error was masked.

            The following code will allow the Bootloader to come back and hang waiting for host communication.

                        if (TRUE == startBootloaderFlag)
                        {
                            send_serial("Starting the Bootloader\r\n");
                           
                           
                            //CyDelay(500);
                            CyBle_Shutdown(); /* stop all ongoing activities */
                            CyBle_ProcessEvents(); /* process all pending events */
                            CyBle_SetState(CYBLE_STATE_STOPPED);
                            CyGlobalIntDisable;
                            Bootloadable_Load();
                        }
            

            The only reason the CyDelay was added, was because it worked well in the example project, and there was no reason to expect that it would cause a reboot.

            Any ideas on why the CyDelay function would cause a reboot would be welcome.