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.

[FAQ] Flash - How to modify an application from RAM configuration to Flash configuration?

Other Parts Discussed in Thread: C2000WARE, UNIFLASH

Could you list the procedure involved in modifying an application from RAM based configuration to Flash based configuration in simple steps?

  • Below is applicable to TMS320F2838x, TMS320F2837x, TMS320F2807x, TMS320F28004x, TMS320F28002x, TMS320F28M35x, TMS320F28M36x.  

    In order to convert a RAM based application to the flash based one, below steps are needed:

    1. Replace RAM linker cmd file with flash linker cmd file (these are available in C2000ware).

    2. If you need to modify the flash linker cmd files, make sure to map any initialized sections only to flash (as you can notice in the linker cmd files provided in C2000Ware).

    3. When the device is configured for boot to flash, bootROM will re-direct to the flash entry point location (defined as BEGIN in TI provided flash linker cmd files) at the end of boot code execution.  Make sure there is a branch instruction at flash entry point to the beginning of code execution.  C2000Ware examples use CodeStartBranch.asm file to accomplish this.  The code in this file is allocated to codestart section.  In the flash linker cmd file, you will notice that the codestart section is mapped to the flash entry point (and hence CodeStartBranch.asm is the first code that gets executed after the bootROM execution).  This code branches to _c_int00 routine, which initializes all the global variables and then re-directs to the application main. 

    4. To achieve the best performance for flash execution, configure the flash wait-states as per the operating frequency (check datasheet) and enable prefetch/cache.  Note that any code that configures the flash control registers (Ex: Flash_initModule() in C2000Ware) must run from RAM.  Hence, the function that configures the flash wait-states and prefetch/cache should be copied to RAM before executing it.  This can be accomplished by assigning this function to .TI.ramfunc section and then copying it to RAM at runtime using memcpy() before executing it.  In the linker cmd file, this section should be mapped to flash for load and RAM for execution.  Please take a look at the flash based linker cmd files provided in C2000Ware.   

    5. Make sure the boot mode pins are configured for flash boot.  This tells bootROM that it has to re-direct to the application programmed in to the flash after boot code execution.  

    Note that all the C2000Ware example projects are provided with both RAM and Flash build configurations. To change the build configuration from RAM to Flash, users can import the project in to CCS and right click on the project and select 'Build Configurations' -> 'Set Active' -> 'Flash'.

    By selecting this Flash configuration, users can notice that:

    1. _FLASH symbol is defined in the "Predefined symbols" section under Project Build settings. This is used to define and execute any Flash-build specific code.

    2. Flash based linker command file is chosen for the application instead of a RAM based linker command file. Flash based linker command files are provided in C2000Ware for reference (Ex: XXX_FLASH_lnk_cpu1.cmd at C2000Ware_x_xx_xx_xx\device_support\XXX\common\cmd). Flash based linker command files will have codestart mapped to Flash entry point address.

    3. All the initialized sections are mapped to Flash memory in the Flash based linker command file.

    4. All the functions that need to execute from RAM (for initialization or 0-wait performance purpose) are assigned to .TI.ramfunc section in the code.

    Ex: Flash_initModule() is assigned to .TI.ramfunc section. This Flash initialization routine (configures Flash wait-states, prefetch/cache mode, power etc.) must be executed from RAM.  If flash initialization routine is not executed, note that the flash performance will be poor.  Reason:  Flash accesses are not as fast as RAM accesses.  When CPU fetches/reads from RAM, there are no additional wait cycles required.  But, flash is not 0-wait memory.  It takes certain time to fetch/read from flash.  CPU is much faster than the flash and hence, CPU has to wait for few cycles (wait states) before it can get the required data from the flash after it (CPU) issues the flash address from which it needs the data.  As the frequency of the CPU increases compared to that of the flash, the number of wait-states that the CPU has to wait to get valid data from flash will increase.  Flash initialization routine configures these wait-states (along with other flash parameters).  Since this function configures the critical flash parameters, it should not be executed from the flash itself.

    5. .TI.ramfunc section is mapped to a Flash address for “Load” and a RAM address for “RUN” in the Flash based linker command file.

    6. All the sections mapped to Flash are aligned on a 128-bit boundary using ALIGN() directive in the Flash based linker command file.

    7. memcpy() function is called in the application to copy the .TI.ramfunc content from Flash to RAM. memcpy() is called before executing any code that is assigned to .TI.ramfunc section.

    8. For EABI type executable: All uninitialized sections mapped to RAM are defined as NOINIT sections (using the directive “type=NOINIT”) in the linker cmd file.

    9. Note: During debug in CCS environment, if you need to place a breakpoint in the RAM space, you need to do it after copying the code from flash to RAM.  If you do it before the copy, the breakpoint insertion will be overwritten by the code copied via memcpy.

    Other related debug tips:

    1. Also, when running the application in standalone mode with out debugger, make sure to configure the boot mode pins for flash boot (please refer to TRM's BootROM chapter for details).

    2. Please make sure that all the variables are initialized as needed in the application.  Using uninitialized variables sometimes causes garbage values to be used for them resulting in differences in the application behavior (and between RAM and Flash based projects depending on the garbage values plugged in).

    3. If you still have issues running from flash in standalone mode (and if it works fine when debugger is connected): 

        (a) Please make sure that ECC is programmed correctly for the flash image (Make sure that AutoEccGeneration in CCS Flash Plugin GUI or UniFlash GUI is left enabled - this is the default option).

        (b) Disable watchdog in the f28x_codestartbranch.asm (WD_DISABLE  .set  0; should be replaced with WD_DISABLE  .set  1; in this asm file).  This helps to avoid watchdog reset before reaching main().  If there are lot of global variables in the application, the cinit routine may take more time to initialize all of them before reaching main.  During this time, watchdog may expire and hence suggested to disable it.  You can enable it again in the main() as needed by your application.

       (c) Please make sure that f28x_codestartbranch.asm file is included in your application and that the codestart is mapped to the flash entry point location (generally defined as BEGIN in TI provided linker CMD files) in the linker cmd file.

       (d) Please make sure that code_start (--entry_point=code_start) is added as the entry point in the project's linker options.     

            Project build settings -> Build -> C2000 Linker -> Advanced options -> Symbol Management -> --entry_point:  code_start

    Best regards,

    Vamsi