RL78 L13 Bootloader/Jump To App problem

I am having a problem getting my RL78 bootloader to correctly jump to and execute the new application. My bootloader is written to parse SREC data and write it to the proper place in memory using the Renesas FSL library. The application that I programming onto the board simply flashes two LEDs and is small enough that I declared the SREC data as a constant in the bootloader so as to eliminate the need for a communication protocol until I got the bootloader itself working. My bootloader can successfully write the new application to the proper place in flash, however the jump to the new application does not work (i.e. the LEDs do not flash as expected and there is in fact no change to the LEDs to indicate anything is happening).

Here is the chip and software tools that I am using:
   Chip = Renesas RL78 L13 R5F10WMG
   IAR Embedded Workbench 4.21.1
   FSL T01 for IAR(V2.xx) :V2.21 (*)

Figure 1 below shows the declaration for the new application SREC file declared as a constant in the bootloader. Figure 2 shows a memory dump of the flash in my MCU after the self-programming is finished, and the data is at the intended location in flash. With those things in place, I should be able to jump to the new application. I have looked at several of the forum entries on this topic and tried a few different ways to accomplish the jump (none of which worked for me). Note that although I tried the FSL bootswap, I cannot use that method because the final bootloader will be larger than 4K.

The methods that I tried for performing the jump to the application are as follows:

//--------------------------
// Method 1
//--------------------------
if ((ucResult == FSL_OK) || (ucResult == SREC_LAST_REC))
{
   DI();
   R_TAU0_Channel0_Stop();
   R_UART0_Stop();

   AppMain();
}
where AppMAin is declared as:
   void (*AppMain)(void)= (void (*)(void))0x00001000;

//--------------------------
// Method 2
//--------------------------
if ((ucResult == FSL_OK) || (ucResult == SREC_LAST_REC))
{
   DI();
   R_TAU0_Channel0_Stop();
   R_UART0_Stop();

   JumpToApp(0x1000, 0x1004);
}
where JumpToApp is declared as:
   void JumpToApp(uint16_t usStackPointer, uint16_t usProgCounter)
   {
      asm("MOVW SP, AX"); // set stack pointer = 0x1000

      asm("MOVW AX, BC");
      asm("BR AX"); // branch to program counter = 0x1004
   }

//---------------------------------------------------------------------------
// Method 3 (this is the method that I ultimately would not be able to use)
//---------------------------------------------------------------------------
if ((ucResult == FSL_OK) || (ucResult == SREC_LAST_REC))
{
   DI();
   R_TAU0_Channel0_Stop();
   R_UART0_Stop();

   FSL_InvertBootFlag();
   FSL_ForceReset();
}


Any help would be very appreciated. I feel like I am very close but I can't find that final piece to get it working. Thanks in advance for your help.

Parents
  • Can you step thru the boot-loader code with a debugger to observe transfer of control to the application, and then step thru the application code to toggle the LEDs?

    There are several similar threads on this forum, I would suggest reviewing many of them to look for hints.

  • I stepped through with the debugger using Method 1 above (i.e.  by calling AppMain() at address 0x00001000).  The code vectors to 0x00001000 and then begins to step through the vector table for AppMain and gets hung up because the micro thinks it should be executing sequential instructions rather than performing the reset procedure that I actually want.  

    How should I be performing this jump to main in a way that uses the vector table for the new application?  Should I be vectoring to the address of the main function in the new application? 

  • Hi Bill,

    What went wrong with method 2 ? Did the program jump to 0x1000 ?

    Regards

  • By default the address of application image starts at 0x2000.

    Have you changed the default address ?

  • Based on various feedback, I reorganized my memory map as follows:

    1. The .reset, .intvec, OPTBYTE and SECUR_ID for the bootloader are in the default addresses in BOOT0 (starting at address 0x0000). Part of the bootloader application resides in the program area of BOOT0
    2. The only code that resides in BOOT1 (address 0x1000) is .reset, .intvec, OPTBYTE and SECUR_ID for the application. None of the application itself resides on BOOT1.
    3. The entire application resides at address 0x2000 and above.
      I also know now that I will need to use the boot swap functionality provided in the self programming library and move the part of the bootloader that won't fit in BOOT0 to higher memory.

    So given the new memory layout outlined above, I believe that when I swap boot sectors using FSL_InvertBootFlag() followed by FSL_ForceReset(), the start-up code for the application that resides in BOOT1 should be called and properly reset into my new application that resides at address 0x2000. However I found that the bot flag is not being swapped as commanded. When I run:

       fsl_u08 fsl_status;

       FSL_GetBootFlag(&fsl_status);

       /* Invert boot flag to prepare for boot swap */
       fsl_status = FSL_InvertBootFlag();

       while (fsl_status == FSL_BUSY)
          fsl_status = FSL_StatusCheck();

       FSL_GetBootFlag(&fsl_status);

    fsl_status == 0 after the second call to FSL_GetBootFlag(). I am using the self programming library as shown in the RL78 One Image Bootloader Example code including initialization and the memory writes that use the library are working well. Any thoughts on why how to fix this problem with the boot flag?

  • After some twists and turns I was able to get the bootloader to work. The solution to the boot flag problem that I reported above was that the stack size needed to be increased. Stack overflow was causing the software to go off into invalid memory space.

    At the start of my development, I was hoping to implement a bootloader that would update the application in memory and then simply jump to the new application and begin executing. In the end I realized that I would not be able to use that architecture because I needed one set of interrupt vectors for my bootloader, and a different vector table for my application. This requires the boot swap functionality provided in the RL78 because the bootloader vector table needed to be replaced by the application’s vector table. If I hadn’t needed interrupts in the bootloader, I might have been able to use a single interrupt vector table (i.e. the application’s vector table) and simply jump to the new application after it was updated as I originally wanted to do.

    I also knew that my bootloader was going to be larger than the boot cluster. To solve this problem I implemented a linker script that allows the bootloader code to be split between the boot cluster and program flash memory. This combined with the boot swap functionality made the bootloader work.

    Thanks to everyone for your help!

  • Hi, finally you get the way, I have the same solution as yours, but right now,I have a question

    bootloader vector table needed to be replaced by the application’s vector table

    What does that mean ? I have a problem when trying to update bootloader from application, 

    Code flash:

    Bootloader is (boot cluster 0) 0x0000-0x1ffff, 0x4000-0xAFFF

    Application:(boot cluster 1) 0x2000-0x3Ffff, other code flash.

    I can update application from bootloader, but the application was stacked to write the data to boot cluster 0.

    Is anyone know what happened?

  • bootloader vector table needed to be replaced by the application’s vector table

    What does that mean ? I have a problem when trying to update bootloader from application, 

    The vector table replacement happens automatically when the boot clusters are swapped.  If you modify the application linker script to map the .reset, .intvec, etc. into boot cluster 1 (addresses 0x1000 - 0x1FFF), then the bootloader's vector table is replaced with the application vector table when when boot cluster 0 and boot cluster 1 are swapped.

Reply
  • bootloader vector table needed to be replaced by the application’s vector table

    What does that mean ? I have a problem when trying to update bootloader from application, 

    The vector table replacement happens automatically when the boot clusters are swapped.  If you modify the application linker script to map the .reset, .intvec, etc. into boot cluster 1 (addresses 0x1000 - 0x1FFF), then the bootloader's vector table is replaced with the application vector table when when boot cluster 0 and boot cluster 1 are swapped.

Children