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.

CCS/TMS320F28377S: RAM saving

Part Number: TMS320F28377S

Tool/software: Code Composer Studio

Hi,

Customer is using F28377S for their application. The size of RAM seems not enough after compiling.

From the map, we find "0008b764    00000ec5     interrupt.obj (ramfuncs:retain)" and "0008cbee    00000451     interrupt.obj (ramfuncs)". The interrupt.obj is saved two times. What's the different? Is there any way to save ramfuncs:retain?

Another question about hole. Is there any way to use these holes for application or parameters, by some way?

Here's part of the map.

ramfuncs   0    00088008    00005ce1     RUN ADDR = 0000b000
                  00088008    000027da     Pwm_Output.obj (ramfuncs)
                  0008a7e2    00000f82     control.obj (ramfuncs)
                  0008b764    00000ec5     interrupt.obj (ramfuncs:retain)
                  0008c629    000005c5     ADCSample.obj (ramfuncs)
                  0008cbee    00000451     interrupt.obj (ramfuncs)
                  0008d03f    000001ee     can_driver.obj (ramfuncs)
                  0008d22d    00000178     SCI.obj (ramfuncs)
                  0008d3a5    0000011b     can_comm.obj (ramfuncs)
                  0008d4c0    00000106     W25Q64_Flash.obj (ramfuncs)
                  0008d5c6    000000c4     BusProtTask.obj (ramfuncs)
                  0008d68a    000000c1     OS_lib_28335.lib : OS_CPU_A.obj (ramfuncs)
                  0008d74b    0000004a     F2837xS_SysCtrl.obj (ramfuncs)
                  0008d795    00000004     F2837xS_usDelay.obj (ramfuncs)
                  0008d799    00000001     --HOLE-- [fill = 0]
                  0008d79a    00000259     F021_API_F2837xD_FPU32.lib : FlashStateMachine.obj (.text:__Fapi_setupFlashStateMachine)
                  0008d9f3    0000019d                                : Program.obj (.text:_Fapi_issueProgrammingCommand)
                  0008db90    00000034                                : Init.obj (.text:_Fapi_initializeAPI)
                  0008dbc4    0000002e                                : Utilities.obj (.text:_Fapi_calculateFletcherChecksum)
                  0008dbf2    0000002d                                : FlashStateMachine.obj (.text:__Fapi_issueFsmCommand)
                  0008dc1f    0000002c                                : Utilities.obj (.text:__Fapi_divideUnsignedLong)
                  0008dc4b    00000025                                : FlashStateMachine.obj (.text:_Fapi_setActiveFlashBank)
                  0008dc70    00000022                                : FlashStateMachine.obj (.text:__Fapi_setupSectorsForWrite)
                  0008dc92    00000020                                : Async.obj (.text:_Fapi_issueAsyncCommandWithAddress)
                  0008dcb2    0000000d                                : Utilities.obj (.text:__Fapi_scaleCycleValues)
                  0008dcbf    00000006                                : FlashStateMachine.obj (.text:_Fapi_getFsmStatus)
                  0008dcc5    00000003     --HOLE-- [fill = 0]
                  0008dcc8    0000000c                                : Init.obj (.ebss) [fill = 0]
                  0008dcd4    0000000b                                : Utilities.obj (.text:__Fapi_calculateOtpChecksum)
                  0008dcdf    0000000a                                : FlashStateMachine.obj (.text:_Fapi_checkFsmForReady)

Thanks a lot.

Br, Jordan

  • Jordan Zhou said:
    From the map, we find "0008b764    00000ec5     interrupt.obj (ramfuncs:retain)" and "0008cbee    00000451     interrupt.obj (ramfuncs)". The interrupt.obj is saved two times. What's the different?

    This is a case of one output section using two input sections from one object file.  That's not typical.  But there is nothing wrong with it.  To understand this better, please learn about the terms in italics from the article Linker Command File Primer.

    Jordan Zhou said:
    Is there any way to save ramfuncs:retain?

    I'm sure you need this input section for correct execution of the system.  So, no.

    Jordan Zhou said:
    Another question about hole.

    I'm not sure why you have any holes at all.  I'm even more curious about this ...

    Jordan Zhou said:
               0008dcc8    0000000c                                : Init.obj (.ebss) [fill = 0]

    How does the .ebss section from one file end up in the ramfuncs output section?  

    There is something more going on here.  I'm not sure what all I need to see in order to understand it.  But I think it makes sense to start with the linker command file.  Please attach the linker command file to your next post.  Note the forum accepts only a few types of files for attachment.  So, add the file extension ".txt" to it.  So, you'll end up posting a file with a name like 28377S_FLASH_lnk.cmd.txt.

    Thanks and regards,

    -George

  • George,

    About the issue "From the map, we find "0008b764    00000ec5     interrupt.obj (ramfuncs:retain)" and "0008cbee    00000451     interrupt.obj (ramfuncs)". The interrupt.obj is saved two times", here's the cmd and code structure. Hole issue is in another project.

    In the code structure, there's ProjectA, which includes several *.c files like A.c, B.c, C.c and D.c. Inside each *.c file, there are several functions. Some are executed in Flash, some are copied to RAM and executed in RAM. These RAM functions are called by three functions: interrupt, FUNCB1 and FCNCC1. These three functions are also executed in RAM.

    All of the RAM functions are defined as "#pragma DATA_SECTION(xxx, xxx)".

    Let me know if there's any way to save RAM.

    Thanks a lot.

    Br, Jordan

    #ifdef CLA_C
    // Define a size for the CLA scratchpad area that will be used
    // by the CLA compiler for local symbols and temps
    // Also force references to the special symbols that mark the
    // scratchpad are.
    CLA_SCRATCHPAD_SIZE = 0x100;
    --undef_sym=__cla_scratchpad_end
    --undef_sym=__cla_scratchpad_start
    #endif //CLA_C
    
    MEMORY
    {
    PAGE 0 : /* Program Memory */
    /* Memory (RAM/FLASH) blocks can be moved to PAGE1 for data allocation */
    /* BEGIN is used for the "boot to Flash" bootloader mode */
    
    BEGIN : origin = 0x080000, length = 0x000008
    RAMM0 : origin = 0x000122, length = 0x0002DE
    // RAMD0 : origin = 0x00B000, length = 0x000800
    
    // RAMLS3 : origin = 0x009800, length = 0x00800
    RAMLS4 : origin = 0x009000, length = 0x002000
    /*RAMLS4 : origin = 0x00A000, length = 0x000800
    RAMLS5 : origin = 0x00A800, length = 0x000800*/
    RAMGS12 : origin = 0x0b000, length = 0x007A00
    /*RAMGS13 : origin = 0x019000, length = 0x001000
    RAMGS14 : origin = 0x01A000, length = 0x001000
    RAMGS15 : origin = 0x01B000, length = 0x001000*/
    RESET : origin = 0x3FFFC0, length = 0x000002
    
    /* Flash sectors */
    FLASHA : origin = 0x080008, length = 0x007FE8 /* on-chip Flash */
    /* FLASHB : origin = 0x082000, length = 0x002000 /*on-chip Flash */
    /* FLASHC : origin = 0x084000, length = 0x002000 /* on-chip Flash */
    /* FLASHD : origin = 0x086000, length = 0x002000 on-chip Flash */
    FLASHFLAG : origin = 0x087ff0, length = 0x000008
    SBOOT : origin = 0x088000, length = 0x000008
    
    FLASHE : origin = 0x088008, length = 0x01fff7 /* /*on-chip Flash */
    /* FLASHF : origin = 0x090000, length = 0x008000 /* on-chip Flash */
    /* FLASHG : origin = 0x098000, length = 0x008000 /* on-chip Flash */
    /* FLASHH : origin = 0x0A0000, length = 0x008000 /* on-chip Flash */
    /* FLASHI : origin = 0x0A8000, length = 0x010000 on-chip Flash */
    /*FLASHJ : origin = 0x0B0000, length = 0x008000 on-chip Flash */
    FLASHK : origin = 0x0B8000, length = 0x002000 /* on-chip Flash */
    FLASHL : origin = 0x0BA000, length = 0x002000 /* on-chip Flash */
    FLASHM : origin = 0x0BC000, length = 0x002000 /* on-chip Flash */
    FLASHN : origin = 0x0BE000, length = 0x002000 /* on-chip Flash */ 
    
    PAGE 1 : /* Data Memory */
    /* Memory (RAM/FLASH) blocks can be moved to PAGE0 for program allocation */
    
    BOOT_RSVD : origin = 0x000002, length = 0x000120 /* Part of M0, BOOT rom will use this for stack */
    RAMM1 : origin = 0x000400, length = 0x000400 /* on-chip RAM block M1 */
    // RAMD1 : origin = 0x00B800, length = 0x000800
    RAMLS0 : origin = 0x008000, length = 0x000800
    RAMLS1 : origin = 0x008800, length = 0x00800
    // RAMLS2 : origin = 0x009000, length = 0x000800
    
    // RAMGS0 : origin = 0x00C000, length = 0x001000
    // RAMGS1 : origin = 0x00D000, length = 0x001000
    // RAMGS2 : origin = 0x00E000, length = 0x001000
    // RAMGS3 : origin = 0x00F000, length = 0x001000
    RAMGS4 : origin = 0x012A00, length = 0x000200
    RAMGS5 : origin = 0x012c00, length = 0x000200
    RAMGS6 : origin = 0x012e00, length = 0x000200
    //RAMGS7 : origin = 0x012000, length = 0x001000
    //RAMGS8 : origin = 0x014000, length = 0x000500
    //RAMGS9 : origin = 0x013000, length = 0x000500
    RAMGS10 : origin = 0x013000, length = 0x005000
    /*RAMGS11 : origin = 0x017000, length = 0x001000*/
    
    
    CPU2TOCPU1RAM : origin = 0x03F800, length = 0x000400
    CPU1TOCPU2RAM : origin = 0x03FC00, length = 0x000400
    
    CLA1_MSGRAMLOW : origin = 0x001480, length = 0x000080 /*caojh 20151225 add for cla*/
    CLA1_MSGRAMHIGH : origin = 0x001500, length = 0x000080
    }
    
    
    SECTIONS
    {
    /* Allocate program areas: */
    .cinit : > FLASHE PAGE = 0, ALIGN(4)
    .pinit : > FLASHE PAGE = 0, ALIGN(4)
    .text : > FLASHE PAGE = 0, ALIGN(4)
    codestart : > BEGIN PAGE = 0, ALIGN(4)
    bootstart : > SBOOT PAGE = 0
    flashflag : > FLASHFLAG PAGE = 0, ALIGN(4)
    
    GROUP
    {
    ramfuncs
    
    { -l F021_API_F2837xD_FPU32.lib}
    //Cla1Prog
    
    } LOAD = FLASHE,
    RUN = RAMGS12 ,
    LOAD_START(_RamfuncsLoadStart),
    LOAD_SIZE(_RamfuncsLoadSize),
    LOAD_END(_RamfuncsLoadEnd),
    RUN_START(_RamfuncsRunStart),
    RUN_SIZE(_RamfuncsRunSize),
    RUN_END(_RamfuncsRunEnd),
    PAGE = 0, ALIGN(4)
    
    /* Allocate uninitalized data sections: */
    .stack : > RAMM1 PAGE = 1
    .ebss : > RAMGS10 PAGE = 1
    .esysmem : > RAMGS6 PAGE = 1
    OSStack : > RAMLS0 PAGE = 1
    
    /* Initalized sections go in Flash */
    .econst : > FLASHE PAGE = 0, ALIGN(4)
    .switch : > FLASHE PAGE = 0, ALIGN(4)
    
    .reset : > RESET, PAGE = 0, TYPE = DSECT /* not used, */
    
    Filter_RegsFile : > RAMGS4, PAGE = 1
    
    /*SHARERAMGS0 : > RAMGS0, PAGE = 1
    SHARERAMGS1 : > RAMGS1, PAGE = 1
    ramgs0 : > RAMGS0, PAGE = 1
    ramgs1 : > RAMGS1, PAGE = 1*/
    
    /* The following section definitions are required when using the IPC API Drivers */ 
    /*GROUP : > CPU1TOCPU2RAM, PAGE = 1
    {
    PUTBUFFER 
    PUTWRITEIDX 
    GETREADIDX 
    }
    
    GROUP : > CPU2TOCPU1RAM, PAGE = 1
    {
    GETBUFFER : TYPE = DSECT
    GETWRITEIDX : TYPE = DSECT
    PUTREADIDX : TYPE = DSECT
    }*/
    
    /* Allocate IQ math areas: */
    /*IQmath : > FLASHM, PAGE = 0, ALIGN(4)*/ /* Math Code */
    /*IQmathTables : > FLASHN, PAGE = 0, ALIGN(4)*/
    
    /* The following section definition are for SDFM examples */ 
    /*Filter1_RegsFile : > RAMGS1, PAGE = 1, fill=0x1111
    Filter2_RegsFile : > RAMGS2, PAGE = 1, fill=0x2222
    Filter3_RegsFile : > RAMGS3, PAGE = 1, fill=0x3333
    Filter4_RegsFile : > RAMGS4, PAGE = 1, fill=0x4444
    Difference_RegsFile : >RAMGS5, PAGE = 1, fill=0x3333*/
    
    
    /* CLA specific sections */ /*caojh 20151225 add for cla*/
    Cla1Prog : LOAD = FLASHE,
    RUN = RAMLS4,
    LOAD_START(_Cla1funcsLoadStart),
    LOAD_END(_Cla1funcsLoadEnd),
    RUN_START(_Cla1funcsRunStart),
    LOAD_SIZE(_Cla1funcsLoadSize),
    PAGE = 0
    
    CLADataLS1 : > RAMLS1, PAGE = 1
    // CLADataLS2 : > RAMLS1, PAGE = 1
    
    Cla1ToCpuMsgRAM : > CLA1_MSGRAMLOW, PAGE = 1
    CpuToCla1MsgRAM : > CLA1_MSGRAMHIGH, PAGE = 1
    CLAmathTables : > RAMLS1, PAGE = 1
    CLA1mathTables : > RAMLS1, PAGE = 1
    
    #ifdef CLA_C /*caojh 20151225 add for cla*/
    /* CLA C compiler sections */
    //
    // Must be allocated to memory the CLA has write access to
    //
    CLAscratch :
    { *.obj(CLAscratch)
    . += CLA_SCRATCHPAD_SIZE;
    *.obj(CLAscratch_end) } > RAMLS1, PAGE = 1
    
    .scratchpad : > RAMLS1, PAGE = 1
    .bss_cla : > RAMLS1, PAGE = 1
    .const_cla : LOAD = FLASHE,
    RUN = RAMLS1,
    RUN_START(_Cla1ConstRunStart),
    LOAD_START(_Cla1ConstLoadStart),
    LOAD_SIZE(_Cla1ConstLoadSize),
    PAGE = 1
    #endif //CLA_C
    
    }
    
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */
    
      

  • First, you are more likely to be successful in saving RAM by looking at the program's data. Look especially for global or static variables that can be declared "const."

    It's possible to save RAM space by overlaying some functions at run time; with an overlay, you copy the function from FLASH to RAM as needed. The drawback is that if you call different overlaid functions multiple times, you may copy them into RAM repeatedly, which may be slower than just running them out of FLASH. It depends a great deal on the structure of your program. Furthermore, any function called as part of the interrupt handling probably should not be an overlay function, as the interrupt might be occurring during the execution of some other overlaid function.
  • I want to comment on something I saw in the linker command file ...

    GROUP
    {
    ramfuncs
    
    { -l F021_API_F2837xD_FPU32.lib}
    //Cla1Prog
    
    }

    The code on line 5 causes all the input sections from that library to be in the ramfuncs output section.  I doubt you mean to do that.

    Thanks and regards,

    -George

  • In customer's code, there's Flash API library, which is executed only one time. After that, it can be moved out RAM. How to move it out? Or how to do the overlay?
    Thanks a lot.
    Br, Jordan
  • George,
    I don't understand.
    "From the map, we find "0008b764 00000ec5 interrupt.obj (ramfuncs:retain)" and "0008cbee 00000451 interrupt.obj (ramfuncs)". The interrupt.obj is saved two times". Inside interrupt, there's no any functions are related to "{ -l F021_API_F2837xD_FPU32.lib}". It is not called there.

    "This is a case of one output section using two input sections from one object file", can you help me to identify the two input sections?

    Thanks a lot.
    Br, Jordan
  • Jordan Zhou said:
    In customer's code, there's Flash API library, which is executed only one time. After that, it can be moved out RAM. How to move it out? Or how to do the overlay?

    Please see the application note Advanced Linker Techniques for Convenient and Efficient Memory Usage.  Note how it uses the features UNION, copy tables, and the RTS function copy_in to implement an overlay.  It has example code for a C6000 system, so you cannot use it directly.  But you can adapt it to your C2000 system.

    Thanks and regards,

    -George

  • Jordan Zhou said:
    "This is a case of one output section using two input sections from one object file", can you help me to identify the two input sections?

    To identify them exactly, I need your source code.  Rather than do that, I will show you an example.  Consider this contrived C program in one source file.

    /* file.c */
    
    int simple_function();
    
    #ifdef SEPARATE_SECTIONS
    #pragma CODE_SECTION(main, ".text:mmm")
    #endif
    int main()
    {
        return simple_function();
    }
    
    
    #ifdef SEPARATE_SECTIONS
    #pragma CODE_SECTION(simple_function, ".text:sss")
    #endif
    int simple_function()
    {
        return 10;
    }

    Suppose I build it while not defining the preprocessor symbol SEPARATE_SECTIONS.  This means the #pragma CODE_SECTION lines are ignored.  In the map file, for the output section .text, I see one entry for all the code from this source file ...

                      00000120    00000005     file.obj (.text)

    Now build again, but define SEPARATE_SECTIONS.  Now the #pragma CODE_SECTIONS lines cause each function to go in a different input section with the name shown.  Now I see this in the map file ...

                      00000120    00000003     file.obj (.text:mmm)
                      00000123    00000002     rts2800_ml.lib : pre_init.obj (.text)
                      00000125    00000002     file.obj (.text:sss)

    This is a case of two input sections from one file appearing in one output section.  In this particular case, they are even separated in memory, with a function from the RTS library coming between them.

    You probably have something similar in your situation.

    Thanks and regards,

    -George

  • George,

    About the hole, here's the info from customer.

    Here attached the map and cmd.

    Will you take a look and give us some suggestions?

    Thanks a lot.

    Br, Jordan

    CMD_Map.rar

  • Holes like that between .ebss objects is usually caused by one of two things: 1) alignment, or 2) blocking. I suspect blocking. In order to generate efficient DP-relative addressing modes, the compiler will force the linker to allocate .ebss objects larger than 0x40 such that they start on an address that is 0x40-word-aligned. Please see this blog post with techniques for reducing the wasted space:
    e2e.ti.com/.../data-blocking-in-the-c2000-mcu-compiler-explained