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.

RTOS/TMS320F28069M: Performance Evaluation of Code running From RAM VS Code copied from Flash to RAM

Part Number: TMS320F28069M

Tool/software: TI-RTOS

Dear T.I. forum followers,

    Recently I've been working on transferring my code which was operating on RAM to a standalone application running on Flash on F28069M, In a better word, I had an application working totally fine on RAM, then for flashing it, I used --ramfunc attribute to copy the whole application from Flash to RAM in the beginning of the operation. Using the help of you guys in here I succeed and now I have a code running from Flash but the issue I'm facing now is that the performance of my code after flashing is not identical to RAM which is super critical in my application, I mean the application on the RAM works with 100% consistency of responses, but the application from Flash (copied to RAM in the beginning ) works with almost 85% of consistency. I used the initFlash() function in the beginning of my main() which improved a lot the performance but still the performances are not identical.

What I'm wondering now is what is the cause of this issue, I know that the Flash has some wait sates and it's not fast like RAM, but I'm coping the whole application in the RAM in the beginning, so what else can be the cause of the problem?

To help you to solve my issue I've attached the .map file generated using my linker command file and also the linker command file itself. 

Thanks in advance

Milad

CMD_Map.rar

  • I'd recommend attaching .zip files instead, as not everybody can open .rar files

    I assume your SW architecture is basically background code and an interrupt. And you want your interrupt to execute as fast as possible. You need also to place all the functions that are called from interrupt. This includes math functions that are contained within C run time support library.

    I find it is a lot easier if you turn on the compiler option "Place each function in a separate subsection" (Under project preferences/Build/Compiler/Advanced options/Runtime model options). Then you can easily see where each function is located
  • Thanks Mitja for the reply, I tried your method, but first of all I'm receiving some warnings like below:

    Also I can't see any difference in my generated .map file. so where can I see this: "You need also to place all the functions that are called from interrupt. This includes math functions that are contained within C run time support library."?

    Thanks in advance

    Milad

  • I don't know why you get that warning.

    Here is an excerpt from my .map file:

    .text      0    00010000    00001073     
                      00010000    00000151     F2806x_Adc.obj (.text:_AdcConversion)
                      0001080e    0000002b     F2806x_Adc.obj (.text:_InitAdc)
                      00010839    00000029     F2806x_SysCtrl.obj (.text:_InitSysCtrl)
                      000109d3    00000021     main.obj (.text:_main)
                      00010a8e    0000001e     rts2800_fpu32.lib : memcpy.obj (.text)
                      00010b35    00000019     rts2800_fpu32.lib : args_main.obj (.text)
                      00010b4e    00000019                       : exit.obj (.text)
                      00011027    00000009     rts2800_fpu32.lib : _lock.obj (.text)
                      00011030    00000008     F2806x_CodeStartBranch.obj (.text)
                      00011038    00000008     F2806x_SysCtrl.obj (.text:_DisableDog)
                      00011070    00000003     F2806x_DBGIER.obj (.text)

    ramfuncs   0    00011074    00000648     
                      00011074    00000019     rts2800_fpu32_fast_supplement.lib : div_f32.obj (.text)
                      0001108d    00000034                                       : sin_f32.obj (.text)
                      000110c1    0000002a     rts2800_fpu32.lib : l_div.obj (.text)
                      000116b8    00000004     F2806x_usDelay.obj (ramfuncs)

    As you can see I relocated the floatin point sine and divide function to the ramfuncs section.

    This is the excerpt from .cmd which does this:

        .text: >        P_FD,           PAGE = 0, ALIGN(4)

        ramfuncs:       {
                            rts2800_fpu32_fast_supplement.lib<atan2_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<div_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<cos_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<sin_f32.obj>(.text)
                            rts2800_fpu32_fast_supplement.lib<sqrt_f32.obj>(.text)
                            rts2800_fpu32.lib<l_div.obj>(.text)
                            *(ramfuncs)
                            *(.TI.ramfunc)
                            *(IQmath)
                        }
                        LOAD = P_FF,
                        RUN = P_L78,
                        LOAD_START(_RamfuncsLoadStart),
                        LOAD_SIZE(_RamfuncsLoadSize),
                        LOAD_END(_RamfuncsLoadEnd),
                        RUN_START(_RamfuncsRunStart),
                        RUN_SIZE(_RamfuncsRunSize),
                        RUN_END(_RamfuncsRunEnd),
                        PAGE = 0, ALIGN(4)

  • Thanks Mitja for your hint, actually I solved my issue in my own way, as you've mentioned before I realized that the critical function/library section of "rts2800_fpu32.lib : fs_div.obj (.text)" is still remaining inside the Flash, so I moved it to RAM using following technique and all the problems disappeared , Now I can say that it seems I'm having a very very close performance between Flash and RAM. ( I leave the steps here for the other people which I'm 100% sure that they will end up in the same problem sooner or later)

    so the way was firstly modifying the CMD file like below:

    Then in the following in .map file you can see the difference:

    Before adding  "rts2800_fpu32.lib<fs_div.obj>(.text)" in the ramfuncs section: 

    After:

    so as you can see after modifying the .cmd file the specific library from .text section(which runs from Flash) was moved to ramfuncs ( which will be copied to RAM). I've also attached my .cmd file for those who want to have a look and might need to use the ideas inside.

    Thanks again.

    CMD.txt
    /*
    //###########################################################################
    //
    // FILE:    F28069.cmd
    //
    // TITLE:   Linker Command File For F28069 Device
    //
    //###########################################################################
    // $TI Release: F2806x C/C++ Header Files and Peripheral Examples V150 $
    // $Release Date: June 16, 2015 $
    // $Copyright: Copyright (C) 2011-2015 Texas Instruments Incorporated -
    //             http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    */
    
    /* ======================================================
    // For Code Composer Studio V2.2 and later
    // ---------------------------------------
    // In addition to this memory linker command file,
    // add the header linker command file directly to the project.
    // The header linker command file is required to link the
    // peripheral structures to the proper locations within
    // the memory map.
    //
    // The header linker files are found in <base>\F2806x_headers\cmd
    //
    // For BIOS applications add:      F2806x_Headers_BIOS.cmd
    // For nonBIOS applications add:   F2806x_Headers_nonBIOS.cmd
    ========================================================= */
    
    /* ======================================================
    // For Code Composer Studio prior to V2.2
    // --------------------------------------
    // 1) Use one of the following -l statements to include the
    // header linker command file in the project. The header linker
    // file is required to link the peripheral structures to the proper
    // locations within the memory map                                    */
    
    /* Uncomment this line to include file only for non-BIOS applications */
    /* -l F2806x_Headers_nonBIOS.cmd */
    
    /* Uncomment this line to include file only for BIOS applications */
    /* -l F2806x_Headers_BIOS.cmd */
    
    /* 2) In your project add the path to <base>\F2806x_headers\cmd to the
       library search path under project->build options, linker tab,
       library search path (-i).
    /*========================================================= */
    
    /* Define the memory block start/length for the F2806x
       PAGE 0 will be used to organize program sections
       PAGE 1 will be used to organize data sections
    
       Notes:
             Memory blocks on F28069 are uniform (ie same
             physical memory) in both PAGE 0 and PAGE 1.
             That is the same memory region should not be
             defined for both PAGE 0 and PAGE 1.
             Doing so will result in corruption of program
             and/or data.
    
             Contiguous SARAM memory blocks can be combined
             if required to create a larger memory block.
    */
    
    MEMORY
    {
    PAGE 0 :   /* Program Memory */
               /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */
    /*
       RAML0       : origin = 0x008000, length = 0x000800
       RAML1       : origin = 0x008800, length = 0x000400
    */
    
       OTP         : origin = 0x3D7800, length = 0x000400     /* on-chip OTP */
    
    	FLASH		: origin = 0x3D8000, length = 0x018000
    	RAM			: origin = 0x008000, length = 0x00C000
    
    /*
       FLASHH      : origin = 0x3D8000, length = 0x004000
       FLASHG      : origin = 0x3DC000, length = 0x004000
       FLASHF      : origin = 0x3E0000, length = 0x004000
       FLASHE      : origin = 0x3E4000, length = 0x004000
       FLASHD      : origin = 0x3E8000, length = 0x004000
       FLASHC      : origin = 0x3EC000, length = 0x004000
    */
    
       FLASHA      : origin = 0x3F4000, length = 0x003F80     /* on-chip FLASH */
       CSM_RSVD    : origin = 0x3F7F80, length = 0x000076     /* Part of FLASHA.  Program with all 0x0000 when CSM is in use. */
       BEGIN       : origin = 0x3F7FF6, length = 0x000002     /* Part of FLASHA.  Used for "boot to Flash" bootloader mode. */
       CSM_PWL_P0  : origin = 0x3F7FF8, length = 0x000008     /* Part of FLASHA.  CSM password locations in FLASHA */
    
       FPUTABLES   : origin = 0x3FD860, length = 0x0006A0	  /* FPU Tables in Boot ROM */
       IQTABLES    : origin = 0x3FDF00, length = 0x000B50     /* IQ Math Tables in Boot ROM */
       IQTABLES2   : origin = 0x3FEA50, length = 0x00008C     /* IQ Math Tables in Boot ROM */
       IQTABLES3   : origin = 0x3FEADC, length = 0x0000AA	  /* IQ Math Tables in Boot ROM */
    
       ROM         : origin = 0x3FF3B0, length = 0x000C10     /* Boot ROM */
       RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM  */
       VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM  */
    
    PAGE 1 :   /* Data Memory */
               /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation */
               /* Registers remain on PAGE1                                                  */
    
    	SYSRAM			: origin = 0x000000, length = 0x000800
    
    /*
       BOOT_RSVD   : origin = 0x000000, length = 0x000050
       RAMM0       : origin = 0x000050, length = 0x0003B0
       RAMM1       : origin = 0x000400, length = 0x000400
    */
    
    
    /*
       RAML2       : origin = 0x008C00, length = 0x000400
       RAML3       : origin = 0x009000, length = 0x001000
       RAML4       : origin = 0x00A000, length = 0x002000
       RAML5       : origin = 0x00C000, length = 0x002000
       RAML6       : origin = 0x00E000, length = 0x002000
       RAML7       : origin = 0x010000, length = 0x002000
       RAML8       : origin = 0x012000, length = 0x002000
    */
    
       USB_RAM     : origin = 0x040000, length = 0x000800     /* USB RAM		  */   
       FLASHB      : origin = 0x3F0000, length = 0x004000     /* on-chip FLASH */     
    }
    
    /* Allocate sections to memory blocks.
       Note:
             codestart user defined section in DSP28_CodeStartBranch.asm used to redirect code
                       execution when booting to flash
             ramfuncs  user defined section to store functions that will be copied from Flash into RAM
    */
    
    
    SECTIONS
    {
       /* Allocate program areas: */
       .cinit              : > FLASH,     	PAGE = 0
       .pinit              : > FLASH,     	PAGE = 0
       .text               : > FLASH,     	PAGE = 0
       codestart           : > BEGIN,      	PAGE = 0
    /*
       ramfuncs            : LOAD = FLASHD,
                             RUN = RAML0,
                             LOAD_START(_RamfuncsLoadStart),
                             LOAD_END(_RamfuncsLoadEnd),
                             RUN_START(_RamfuncsRunStart),
    						 LOAD_SIZE(_RamfuncsLoadSize),
                             PAGE = 0
    */
       csmpasswds          : > CSM_PWL_P0, PAGE = 0
       csm_rsvd            : > CSM_RSVD,   PAGE = 0
    
       /* Allocate uninitalized data sections: */
       .stack              : > SYSRAM,      PAGE = 1
       .ebss               : > RAM,      	PAGE = 0
       .esysmem            : > RAM,      	PAGE = 0
    
       /* Initalized sections to go in Flash */
       /* For SDFlash to program these, they must be allocated to page 0 */
       .econst             : > FLASH,     PAGE = 0
       .switch             : > FLASH,     PAGE = 0
    
       GROUP
        {
        	.TI.ramfunc
        	ramfuncs{
        	rts2800_fpu32.lib<fs_div.obj>(.text)
        	}
        	dclfuncs
        }    LOAD = FLASH,
             RUN = RAM,
             PAGE = 0,
             TABLE(BINIT)
    
       .binit : palign=0x8, fill=0xffff > FLASH
    
       /* Allocate IQ math areas: */
       IQmath              : > FLASH,     PAGE = 0            /* Math Code */
       IQmathTables        : > IQTABLES,   PAGE = 0, TYPE = NOLOAD
       
       /* Allocate FPU math areas: */
       FPUmathTables       : > FPUTABLES,  PAGE = 0, TYPE = NOLOAD
       
       /*
       DMARAML5	           : > RAML5,      PAGE = 1
       DMARAML6	           : > RAML6,      PAGE = 1
       DMARAML7	           : > RAML7,      PAGE = 1
       DMARAML8	           : > RAML8,      PAGE = 1
       */
    
      /* Uncomment the section below if calling the IQNexp() or IQexp()
          functions from the IQMath.lib library in order to utilize the
          relevant IQ Math table in Boot ROM (This saves space and Boot ROM
          is 1 wait-state). If this section is not uncommented, IQmathTables2
          will be loaded into other memory (SARAM, Flash, etc.) and will take
          up space, but 0 wait-state is possible.
       */
       /*
       IQmathTables2    : > IQTABLES2, PAGE = 0, TYPE = NOLOAD
       {
    
                  IQmath.lib<IQNexpTable.obj> (IQmathTablesRam)
    
       }
       */
        /* Uncomment the section below if calling the IQNasin() or IQasin()
           functions from the IQMath.lib library in order to utilize the
           relevant IQ Math table in Boot ROM (This saves space and Boot ROM
           is 1 wait-state). If this section is not uncommented, IQmathTables2
           will be loaded into other memory (SARAM, Flash, etc.) and will take
           up space, but 0 wait-state is possible.
        */
        /*
        IQmathTables3    : > IQTABLES3, PAGE = 0, TYPE = NOLOAD
        {
    
                   IQmath.lib<IQNasinTable.obj> (IQmathTablesRam)
    
        }
        */
    
       /* .reset is a standard section used by the compiler.  It contains the */
       /* the address of the start of _c_int00 for C Code.   /*
       /* When using the boot ROM this section and the CPU vector */
       /* table is not needed.  Thus the default type is set here to  */
       /* DSECT  */
       .reset              : > RESET,      PAGE = 0, TYPE = DSECT
       vectors             : > VECTORS,    PAGE = 0, TYPE = DSECT
    
    
    }
    
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */
    
    

  • Glad you were able to resolve the problem and appreciate you posting the detailed solution.
  • I really recommend against using --ramfunc. Using it you move the linker settings from .cmd file and .c file, where it should be to the makefile if you have one or to CCS project settings.

    The only usage would be when you are building libraries