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.

Compiler/LAUNCHXL-F28379D: Linker file to run program from Flash with --ramfunc=on compiler flag

Part Number: LAUNCHXL-F28379D
Other Parts Discussed in Thread: CONTROLSUITE, C2000WARE

Tool/software: TI C/C++ Compiler

Dear all,

I have a couple of questions regarding the linker file design, I will clearly emphasize the questions. Please find attached a minimum working example for the target device (blinky LED for LAUNCHXL-F28379D), but I would say this questions applies to C2000 series microcontrollers in general. You do not have to modify the project, it is ready for build and debug.

Blinky.zip

1. Save program to Flash, and run it from Flash

I have this case working with the help of example projects found in controlSUITE for the considered device. However, I also have a problem here. If you open the linker file in the project, you will see a macro flag "OLD_BOOT". If you define this flag, the linker will use the working variant to run the program from Flash, as follows:

  • Save the program in FLASHE sector.
  • Run the program from FLASHE sector, unless function is defined with "ramfunc" attribute.
  • In case there are functions that need to be run from RAM, place them in RAMGS0_5 sector.
  • The "codestart" section points to first word in FLASHA sector.

In this example I do not like the fact that I'm using FLASHA sector for the "codestart" section, since the entire program is saved in FLASHE sector. So I tried to define the "codestart" section to also reside in the FLASHE sector. You can simulate this case by removing the "OLD_BOOT" macro in the linker file. It does not work! When I build and debug the program, it works on the LaunchPad in the debug mode, but as soon as I reset the device, the program stops working, i.e. it does not boot. I assume that the program counter ends up somewhere in weed. I am not sure why is that. Q1 Does the program always go to 0x080000 (FLASHA) after reset to see where to jump next? If not, Q2 How can I fix the linker file to have the "codestart" section also in FLASHE sector?

2. Save program to Flash, and partially run from RAM

In this case I use the linker file with "OLD_BOOT" macro defined, i.e., the "codestart" section resides in FLASHA sector.

I defined the doBlink() function with "ramfunc" attribute, and I also have defined CPU1, _FLASH, and _LAUNCHXL_F28379D macro flags in "Build - C2000 Compiler - Predefined Symbols" project properties. These flags will instruct the built-in InitSysCtrl() function to copy functions from Flash to RAM.

3. Save program to Flash, and run it from RAM

In this case I use the linker file with "OLD_BOOT" macro defined, i.e., the "codestart" section resides in FLASHA sector.

The former case defined only one function to be run from RAM. However, you can set "ramfunc" attribute globally to all functions in "Build - C2000 Compiler - Advanced Options- Runtime Model Options" by setting the "Run functions from RAM. (--ramfunc)" to "on". In this case the main() function should be placed to RAM as well. However, this program does not even work in the debug mode, i.e., program counter ends up in weed as soon as I boot the device. Q3 How can I fix the linker file to support thix case?

Conclusion

There are three questions, I read a lot of documents and old threads trying to fix the issue, but without any luck. I appreciate if someone can provide support.

Thank you!

Marko.

  • I think I managed to answer question Q3 by using "binit" section in the linker file. Here is what I did:

    • Defined the "OLD_BOOT" macro in the linker file, i.e., the "codestart" section is placed at 0x080000 (FLASHA sector).
    • Added "TABLE(BINIT)" to ".TI.ramfunc:" section after "RUN = RAMGS0_5" (ofc without quotes)
    • Added ".binit" section as follows: ".binit: > FLASHE PAGE = 0, ALIGN(4)"

    This will automatically copy the program from Flash to RAM during boot, and jump to main() in RAM after that. Due to this I removed the "_FLASH" macro from "Predefined Symbols", so that memcpy() and InitFlash() functions are not called in InitSysCtrl() function. We do not need memcpy() function as binit copies program from Flash to RAM, but we do however need to initialize Flash. Below the InitSysCtrl() I have put the InitFlash() function to initialize Flash. Q4 Am I right when I say that we do not need memcpy() function in the program with binit?

    With this approach two new (minor) issues appeared:

    • When I "Start" the program, the program is not paused when it reaches main(), but it immediately starts working. Q5 Can I have it as before, i.e., for program to pause when it reaches main()?
    • When I "Terminate" the program, i.e., debug session, the program is stopped. I need to manually reset it to make it run again. Q6 Can I have it as before, i.e., for program to keep running when I hit "Terminate"?

    I still do not have a solution for Q1 and Q2 from previous post.

    Additional question. I use the "F2837xD_Headers_nonBIOS_cpu1.cmd" from the controlSUITE. However, comparing that file to "F2837xD_Headers_BIOS_cpu1.cmd", the only difference is that the latter has "TYPE=DSECT" specifier for PieVectTableFile in SECTIONS. Q7 What is practical difference between the two Header files?

    Thank you!

    Marko.

  • Marko,

    Please note the device support in controlSUITE is no longer being maintained. I will strongly suggest you reference the examples in C2000Ware. There are example for Flash applications and build configurations.

    Here is a page that explains the structure of a linker command file: https://processors.wiki.ti.com/index.php/C28x_Compiler_-_Understanding_Linking

    Please see this link for helpful information for programming with flash.

    Regards,

    Ozino

  • Dear Ozino,

    I appreciate your recommendation for a page that explains structure of a linker command.

    Also, thank you for recommendation to use C2000Ware, I will use it in my future projects.

    However, if you read both of my posts you will see that the question is more detailed than "How to write a linker file". I have a set of questions with specific problems that I could not find answer to after reading the recommended "C28x Compiler - Understand Linking" page, C2000 compiler datasheet, and bunch of old threads posted by other users.

    I repeat all the questions here:

    Q1 Does the program always go to 0x080000 (FLASHA) after reset to see where to jump next?
    Q2 If answer to Q1 is no, how can I fix the linker file in the attached project to have the "codestart" section also in FLASHE sector?
    Q3 How can I fix the linker file to support thix case? (--ramfunc=on)
    Q4 Am I right when I say that we do not need memcpy() function in the program with binit?
    Q5 Can I have it as before, i.e., for program to pause when it reaches main()?
    Q6 Can I have it as before, i.e., for program to keep running when I hit "Terminate"?
    Q7 What is practical difference between the two Header files?


    For a more detailed explanation around these questions, please see the first two posts of this thread.

    I would appreciate if you could remove "TI Thinks Resolved" tag from your post, as it does not answer any of the questions in this thread.

    Thank you!

    Marko.

  • Marko,

    Please find answers below for your queries:

    1) When "Flash boot mode" is selected, BROM jumps to Flash entry point located at 0x80000.   In the linker command files provided in C2000Ware, you will notice that the codestart is mapped to 0x80000 (Flash entry-point after device boot).  And the code at code_start will branch to _c_int00 whereever it is located.  You can refer to F2837xD_CodeStartBranch.asm provided in C2000Ware examples. 

    2) As mentioned above, codestart must be mapped to Flash entry point 0x80000.

    3) You already figured it out.

    4) Yes, you don't need memcpy() in this case.

    5) I have not tried this before and hence I did not notice this behavior. Your observation might be correct since load main() is not run main() anymore.  But, just in case, did you change any settings in the "Program/Memory Load Options" OR in the "Auto Run and Launch Options" in the debugger? These options are available in CCS Debug view -> Tools -> Debugger Options.  Did you try using a break point manually? If yes, did that work?

    6) We can look in to this. When you say it worked when you reset again, did you do that by connecting the debugger OR did you do a power cycle with standalone Flash boot option?  Do you have watchdog enabled in your application?  If yes, is it serviced periodically?   

    I may have to loop in our compiler/CCS teams for further help on #5 and #6.  I will loop them in based on your replies.

    7) For applications that use RTOS, SYS/BIOS supplies its own default ISR for the vector table and hence PieVectTableFile is not allocated/included in the output file.  This is accomplished by doing TYPE=DSECT (tells to not allocate space in the memory map and hence it is not part of the output executable).

    Thanks and regards,
    Vamsi 

  • Dear Vamsi,

    Thank you for your detailed response!

    I have few sub-questions regarding your answer.

    1) It would make sense to have the "codestart" section in memory location other than 0x80000 (beginning of Flash sector A) only in case we use bootloader. Correct?

    4) I also tried with leaving the memcpy() function, since it is used by default in InitSysCtrl() if you define "_FLASH" symbol in "Predefined Symbols". It also works. On boot the "binit" copies program from Flash to RAM and then when program reaches memcpy() it jumps back to Flash and repeats the copy procedure. Correct?

    5) I did not change anything, all the settings were set to default values. I did not try to use a break point manually, will try it.

    6) The watchdog is disabled. When I say "reset" I mean power cycle. When I press "Terminate" in Debug session, the program on MCU stops and I have to power cycle to start the MCU again.

    Thank you!

    Marko.

  • Marko,

    Glad that it helped.

    1) Yes, if you use your custom bootloader which starts at 0x80000, then your application codestart should be at other location and your custom loader would jump there.

    4) I think it is redundant.  But I don't think it will cause a failure.

    Regarding your other questions:

    5) Ok, thank you for the details.  Then, I think this case might need manual breakpoint.  If you want me to take this further and analyze if there is a way to stop at main(), I would suggest to start a new post so that we can assign it to our compiler/CCS team.  Please let me know.

    6) Ok, thank you for the details.  It should continue to execute after you terminate and should not need you to power cycle the board for the application to execute again.  Could you open a new post for this as well?  Or may be one post to talk both 5 and 6 together.  

    Thanks and regards,
    Vamsi

  • Vamsi,

    This is just to let you know that I opened a new post regarding questions 5) and 6): click here.

    Once again, thank you for your support!

    Best regards,
    Marko.

  • Marko,

    Thank you. I will ask our CCS team to take a look at it.

    Thanks and regards,

    Vamsi