This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Custom Boot-loader jump to application

Other Parts Discussed in Thread: TMS320F28035, CONTROLSUITE, TMS320F28335

I am in the process of developing a custom boot-loader (which does not use the boot-loader functions or OTP) for the TMS320F28035 MCU.  I am using the "standard" implementation for boot-loaders that have been used for quite some time.  I've partitioned the boot-loader and application code into two separate projects.  The boot-loader makes use of flash sector A to store the boot-loader and the application uses the remaining flash.  I am able to use the boot-loader to transfer S-Records to flash and have been able to verify that the application is stored properly in the flash.  As part of the application loading process I write the reset vector for the application to flash at address 0x3F3FC0.  I want the main function of the application to be executed so I have stored my "reset" vector by using the following code:

typedef void (*fptr)(void);

void main(void);

#pragma DATA_SECTION(App_Reset, "App_Reset")

const fptr App_Reset[] =

{

  main

};

By doing this the location of the main function is stored in the "reset" location in the linker which is 0x3F3FCO.

In the boot-loader, I test that the flash has been programmed and if it has then I use a function pointer to call the function (application main) located at the reset address as follows:

const uint32* ptr = (uint32*)(0x3F3FC0);

fptr = Reset_Vector = (fptr)*ptr;

if(*ptr != 0xFFFFFFFF)

{

  // Jump to the application

   (*Reset_Vector)();

}

else

{

// Bootloader initialization is ran.

}

Now when (*Reset_Vector)() is called the code jumps to an Illegal_ISR function in the default ISR module.  I don't fully understand why this fault is occurring.  Can anyone recommend another method for jumping to the application code?  In other boot-loaders I would use assembly language to load the reset vector location and begin execution but I have not been able to find sufficient examples for this processor on how to do this.  I would also like to understand if there is something in the general strategy I am doing that is incorrect. 

 

Help is greatly appreciated.  Thanks.

  • We use different solution in F28335 platform, programming a customer bootloader into SECTION A, whose address is 0x33FFF6 and jumps to application code with entry point in 0x300000, which is in SECTION H, below assembly code does the jump:

     .text
    _jumpToAppEntry:
      SETC INTM;
      ZAPA;
      MOV @SP,#0;
      PUSH ACC; 
      PUSH AL;
      MOV AL, #0x0a08;
      PUSH AL;
      MOVL XAR7, #0x300000;
      PUSH XAR7;
      POP RPC;
      POP ST1;
      POP ST0;
      POP IER;
      POP DBGIER;
      LRETR;  

    Hope this helps

    Tim

  • Thank you for your response.  This worked very well.  Implementing your assembly code allowed me to discover that my function pointer branch code was functioning properly.  I had been writing my application to flash improperly.  S-Records were not properly being sent over CAN so incorrect application code was being written to flash. 

  • I have developed a custom CAN boot-loader for the TMS320F28035 but I have discovered that the user application which can be stored through it does not operate as expected. 

    What i am finding is that certain variables (more specifically variables and structures within the TI library) seem to not be modifiable by the application code.  For example, the CpuTimer0.InterruptCount variable will not increment within the application.  My RAM is broken up into two sections starting at 0x8000 and 0x9000 each of length 0x1000.  When I export these ram locations for the stand-alone application and the boot-loaded application and then compare them in WinMerge (against their respect memory range), I find that there are big differences between the two.

    For a custom boot-loader is it necessary to have the application manually copy the initialized sections from its application into RAM?  If so what is the best method of doing so? 

    One additional detail that I noticed was that if I loaded my user applications symbols in place of the boot-loader symbols and then went to Target->Restart, my user application would run properly.  However, if I added the user application symbols to the boot-loader symbols it doesn't function properly.

    If someone could illuminate how this works and how I can make my application run properly it would be greatly appreciated!

  • I assume your CAN boot-loader functions pretty much like my SCI boot-loader except it receives program data through CAN interface. If it's true, then much simpler. I suggest below steps:
    1. Verify CAN boot-loader receives all application data correctly
    2. Call FLASH API to program your application into Flash memory
    3. Jump to the entry point of your application, and see what will happen

    It is required to copy sections to internal RAM by your application, e.g., in F28335 platform, I have to put internal FLASH initialization routine into internal RAM.

    Tell me if I understand your question correctly.

    BR
    Tim 

  • Hello Tim,
       I would think that they operate similar as you mention with the major difference being that data is received over CAN.
       1. I have verified that the boot-loader receives all data and
       2. I use the flash API to write the data to flash in sector B - H.  I have verified this by using the view-> memory tool to then export the flash memory B-H and comparing it to my stand-alone application.  The flash data matches at each address so the data is written correctly.
       3. Now when my system starts, the boot-loader examines the application reset vector and if it is not 0xFFFFFFFF (indicating the flash has not been written) then it continues initializing the boot-loader.  Otherwise, it jumps to the reset vector of the application that was written to flash.
       Now the application itself does "run".  When I add the symbols for the application I can step through my application and see that it is running.  However, what I am finding is that code that accesses variables related to the TI library functions such as timer counters, gpio states, etc do not change if the code tries to increment or write to them.  
       In an attempt to understand what was going on I compared the RAM image state of the application if I run it stand-alone and then again if I run it with the boot-loader and found that the RAM images are quite different from each other.  
       The boot-loader application also uses some functions from the TI libraries because there is an external eeprom which needs to be read to determine whether the boot-loader should jump to the application.  
       I guess what I think may be happening is when the processor loads, the sections for the boot-loader are loaded into RAM, then a jump to the application occurs but then the application sections are never put into RAM or are not put into RAM properly.  
       I did try to separate the boot-loader RAM and application RAM within the linker but it did not seem to help.  Although like i mentioned I have not copied the application sections manually into RAM for the application.  
       So in summary the issue is that my boot-loader can put a new application on the chip but that application is not running properly.  I do not fully understand for the C2000 how the "copy down" works for a boot-loaded application.  
       I also believe that my boot-loader is running after c_int00.
    Thank you for your assistance.  It is greatly appreciated.
    Jacob  


    On Jun 9, 2011, at 7:02 AM, "TI E2E Community - Automated Email" <noreply@e2e.ti.com> wrote:

    Tim xu replied to Re: Custom Boot-loader jump to application in C2000 32-bit Microcontroller Forum.

    I assume your CAN boot-loader functions pretty much like my SCI boot-loader except it receives program data through CAN interface. If it's true, then much simpler. I suggest below steps:
    1. Verify CAN boot-loader receives all application data correctly
    2. Call FLASH API to program your application into Flash memory
    3. Jump to the entry point of your application, and see what will happen

    It is required to copy sections to internal RAM by your application, e.g., in F28335 platform, I have to put internal FLASH initialization routine into internal RAM.

    Tell me if I understand your question correctly.

    BR
    Tim 

     

  • Jacob,

    In our implementation, we modified the application tcf file, to make sure the application code is not been written into FLASH section A where bootloader resides.
    And we also create a APP_ENTRY in application tcf file. I attached application memory configuration in TCF for your reference

    And below are application sections

    Hope this helps!

    Best Regards
    Tim

     

  • Dear Jacob Beningo,

    I also need a feature to allow firmware update via UART (SCI).

    Our firmware size is larger than the total internal RAM size, so I started going through the long and hard way to implement a module in our software that runs from internal RAM, communicates to the host via SCI and downloads the software in small parts while burning them directly to FLASH.

    This is probably what you did right?

    There are a few disadvantages to this firmware update method:

    1. Development time is long and risky
    2. In case of power failure, serious communication error or other non-recoverable issue, the hardware will need to be accessed directly to reprogram the device

    To overcome these issued, I thought of the following design option:

    Upon receiving a command from host, write some signature to a specific flash location that tells the firmware that it is in SCI BOOT mode.

    Then, "jump" to the device SCI BOOT code and use a commercial tool to reprogram the device via UART (SCI).

    Although this method is also not 100% safe, it is safer than the previous method and easier to implement.

    My questions are:

    1. How can we "jump" to the device SCI BOOT code?
    2. Do you have an example of a module that performs such a "jump"?
    3. Do you have an example of the first scheme (without the SCI BOOT)?

    I would greatly appreciate if you can share the relevant code with me. This would greatly shorten my development time.

    Thanks,

     A.T.

    Jacob Beningo75543 said:

    Thank you for your response.  This worked very well.  Implementing your assembly code allowed me to discover that my function pointer branch code was functioning properly.  I had been writing my application to flash improperly.  S-Records were not properly being sent over CAN so incorrect application code was being written to flash. 

  • Hello A.T.,

       You are correct in that what I did was I transmitted a record at a time to the boot-loader which then wrote the record to flash.  However, the disadvantages that you list are not necessarily true.  

    1. With experience, (for me anyways) it takes 3 - 5 weeks to implement a boot-loader and since I follow a standard process for my boot-loaders there is little risk involved.  If this is your first time developing a boot-loader it will definitely take longer and there will be risks and delays in your schedule has you struggle through the process.  

    2. Every boot-loader should be extremely robust so that it can handle power failures, loss of communication, corrupted packets, etc.  Each boot-loader that I have written can handle each of the cases you listed.  The worst case that I have experienced with one of my boot-loaders is that I simply have to power cycle and start the erase, write, confirm sequence all over again.  I've never had to reprogram a system again through JTAG once a boot-loader has been put in place no matter what the circumstances.

    The boot-loader and the application are generally allocated into two separate areas of flash, partitioning them so that the application doesn't know that the boot-loader exists and so that the boot-loader only has access to erase and write to the application section of flash.  I typically use eeprom or emulated eeprom to create a mode configuration byte that the start-up code then uses to determine whether the boot-loader or the application file should be ran.   

    As far as jumping goes for the C2000 I use something similar to the code below:

    ;; TI File $Revision: /main/7 $
    ;; Checkin $Date: May 2, 2006 20:49:39 $
    ;;###########################################################################
    ;;
    ;; FILE: Init_Boot.asm
    ;;
    ;; TITLE: 280x Boot Rom Initialization and Exit routines.
    ;;
    ;; Functions:
    ;;
    ;; _InitBoot
    ;; _ExitBoot
    ;;
    ;; Notes:
    ;;
    ;;###########################################################################
    ;; $TI Release:$
    ;; $Release Date:$
    ;;###########################################################################
    .def _jumpToAppEntry

    _jumpToAppEntry:
    ; Initialize the device for running in C28x mode.
    C28OBJ ; Select C28x object mode
    C28ADDR ; Select C27x/C28x addressing

    SETC INTM;
    ZAPA;
    MOV @SP,#0;
    PUSH ACC;
    PUSH AL;
    MOV AL, #0x0a08;
    PUSH AL;
    MOVL XAR7, #0x3E8000;
    PUSH XAR7;

    POP RPC;
    POP ST1;
    POP ST0;
    POP IER;
    POP DBGIER;
    LRETR;

    The value 0x3E8000 would be set to wherever you stored the application reset vectors.  Basically once you check that byte and if you want the application call jumpToAppEntry(); from the start-up code.  If you want the boot-loader just keep running the current code.  

    I would also declare a pointer to your application reset vector and verify that it exists before jumping to it.

     const uint32* ptr = (uint32*)(0x3E8000);

    if((*ptr != 0xFFFFFFFF) && (ReflashByte != (uint8)'B') )
    {
    jumpToAppEntry();
    }

    If you need any additional please feel free to contact me.  

    [On a side note my company (Beningo Engineering) specializes in developing boot-loaders so if you find that the risk is too high or your schedule too short I would be happy to speak with you about our off the shelf solutions.  As you know I'm familiar with this part and have written not only CAN boot-loaders for it but also SCI, SPI and I2C.  ]

    Best Regards,

    Jacob

  •  

    Dear Jacob,

    Thanks allot for your detailed reply.

    I also estimated that the development time will not be short.

    Therefore, it was decided to perform a hardware change and add the built-in SCI-BOOT option which works quite well.

    I will keep your offer in mind if plans are changed.

    Best Regards,

    A.T.

  • Dear Jacob,

    It seems like this issue is brought up again by our staff, and they would like the software solution.

    In order to shorten development time, I tried to make use of the built-in SCI-BOOT code that resides in ROM and does a similar operation to the classic boot loader.

    The idea was that given an appropriate host command, our software performs a jump to the  built-in SCI-BOOT code (address 0x003ff7dd according to C:\ti\controlSUITE\libs\utilities\boot_rom\2803x\2803x_boot_rom_v1\Release\ 2803x_boot_rom.map).

    I tried a few variations of this jump, but non actually worked (the C2Prog is unable to communicate with the device).

    What is your opinion on this scheme?

    Do you have any idea why this does not actually work?

    Thanks,

    A.T.

  • Hello A.T.,

       When I first learned of the built-in boot-loader functions I thought that it was very interesting and exciting.  Unfortunately after some research into it I discovered that for most of my applications the built-in method was insufficient.  The primary reason is that in order to have a robust solution that never brinks the system we needed more control over what the boot-loader was doing such as system integrity checks, check-sums, multiple boot images, a backdoor into the boot-loader.  None of these things are included in the built in ROM solution.  The ROM solution offers the most basic function with no guarantee. 

       I believe we ran into the some of the same issues of being unable to link and jump to the internal boot-loader as well.  I think after some time I eventually just went the route of writing my own especially since it did not meet requirements.  I hope this answers most of your question but I am unsure as to why there would be issues jumping to the internal loader.

    Best Regards,

    Jacob

  • dear  Jacob !

    I'm doing the same things as your project; as metioned froms others;

    but It's difficult for me, I'm a new learner for TMS320F28335, though, i'm really interesting about the custom boot-loader as you. but this guy has token my three weeks time. could you please shared some experience or your code to me?  thank you very much!