TMS320F28386S: CLA Program RAM: Exceeding Available Memory

Part Number: TMS320F28386S

I am working on a project that will have three discrete modes of operation, requiring three different aplications to be loaded into the CLA from flash memory.  

As currently configured I do not have sufficient LSRAM for all three applications, and get this error:

error #10099-D: program will not fit into available memory, or the section contains a call site that requires a trampoline that can't be generated for this section. 

In my command file, I've defined:

MEMORY
{
    RAM_CLA_PROGRAM   : origin = 0x008000, length = 0x003800    /* LS0 - LS6 */
    RAM_CLA_DATA            : origin = 0x00B800, length = 0x000800   /* LS7  */

   FLASH_Application1       : origin = 0x0B8000, length = 0x002000    /* FLASH Sector    K */
   FLASH_Application2       : origin = 0x0BA000, length = 0x002000    /* FLASH Sector L */
   FLASH_Application3       : origin = 0x0BC000, length = 0x002000    /* FLASH Sector M */

}

SECTIONS
{

    Cla1Prog_Application1        :    LOAD = FLASH_Application1,
                                                     RUN = RAM_CLA_PROGRAM,
                                                     LOAD_START(cla1Funcs_Application1_loadstart),
                                                     LOAD_SIZE(cla1Funcs_Application1_loadsize),
                                                     LOAD_END(cla1Funcs_Application1_loadend),
                                                     RUN_START(cla1Funcs_Application1_runstart),
                                                     RUN_SIZE(cla1Funcs_Application1_runsize),
                                                     RUN_END(cla1Funcs_Application1_runend),
                                                     ALIGN(8)

    Cla1Prog_Application2        :    LOAD = FLASH_Application2,
                                                     RUN = RAM_CLA_PROGRAM,
                                                     LOAD_START(cla1Funcs_Application2_loadstart),
                                                     LOAD_SIZE(cla1Funcs_Application2_loadsize),
                                                     LOAD_END(cla1Funcs_Application2_loadend),
                                                     RUN_START(cla1Funcs_Application2_runstart),
                                                     RUN_SIZE(cla1Funcs_Application2_runsize),
                                                     RUN_END(cla1Funcs_Application2_runend),
                                                     ALIGN(8)

    Cla1Prog_Application3        :    LOAD = FLASH_Application3,
                                                      RUN = RAM_CLA_PROGRAM,
                                                      LOAD_START(cla1Funcs_Application3_loadstart),
                                                      LOAD_SIZE(cla1Funcs_Application3_loadsize),
                                                      LOAD_END(cla1Funcs_Application3_loadend),
                                                      RUN_START(cla1Funcs_Application3_runstart),
                                                      RUN_SIZE(cla1Funcs_Application3_runsize),
                                                      RUN_END(cla1Funcs_Application3_runend),
                                                      ALIGN(8)

}

So what I would like to be able to do is selectively load Application 1, 2, or 3 via memcpy when I initialize the CLA:

    if(Application== Application1)
    {
        memcpy(&cla1Funcs_Application1_runstart,    &cla1Funcs_Application1_loadstart,  (uint32)&cla1Funcs_Application1_loadsize);
    }
    else if(Application== Application2)
    {
        memcpy(&cla1Funcs_Application2_runstart,    &cla1Funcs_Application2_loadstart,  (uint32)&cla1Funcs_Application2_loadsize);
    }
    else if(Application== Application3)
    {
        memcpy(&cla1Funcs_Application3_runstart,    &cla1Funcs_Application3_loadstart,  (uint32)&cla1Funcs_Application3_loadsize);
    }

The problem:

(cla1Funcs_Application1_loadsize + cla1Funcs_Application2_loadsize + cla1Funcs_Application3_loadsize) > (RAM_CLA_PROGRAM = 0x38000)

My first thought is to change the RUN location defined in SECTIONS from RAM_CLA_PROGRAM to  the RAMGSx sections (of which I have plenty of space), then copy from RAMGSx or flash toLSRAM?  This would resolve the compiler memory error, but I'd have to redefine cla1Funcs_Application1_loadstart, cla1Funcs_Application2_loadstart, or cla1Funcs_Application3_loadstart to an address on LSRAM.  If this would work, how would I implement it?  And are there other alternatives?


Thanks in advance for any insight.

  • Hi Andrew,

    Thank you for your question. I'll look into the issue and get back to you.

    Thanks,

    Ira

  • Hi Andrew,

    Apologies for the late reply. 

    The linker error occurs because all three sections share RUN = RAM_CLA_PROGRAM, so the linker sums their sizes against that single region - even though only one runs at a time.

    The cleanest fix is the UNION directive — this tells the linker the sections are mutually exclusive overlays sharing the same run address. It allocates RAM only for the largest application, not the sum.

    Restructure your .cmd file like this:

    SECTIONS
    {
    UNION run = RAM_CLA_PROGRAM, RUN_START(cla1Funcs_runstart), ALIGN(8)
    {
    GROUP load = FLASH_Application1,
    LOAD_START(cla1Funcs_Application1_loadstart),
    LOAD_SIZE(cla1Funcs_Application1_loadsize)
    {
    Cla1Prog_Application1: { /* Application1 objects */ }
    }

    GROUP load = FLASH_Application2,
    LOAD_START(cla1Funcs_Application2_loadstart),
    LOAD_SIZE(cla1Funcs_Application2_loadsize)
    {
    Cla1Prog_Application2: { /* Application2 objects */ }
    }

    GROUP load = FLASH_Application3,
    LOAD_START(cla1Funcs_Application3_loadstart),
    LOAD_SIZE(cla1Funcs_Application3_loadsize)
    {
    Cla1Prog_Application3: { /* Application3 objects */ }
    }
    }
    }

    • Each application gets its own LOAD address in Flash (unchanged)
    • All three share a single RUN address in LSRAM
    • The linker only reserves space for the largest one [2][3]
    • Your memcpy approach remains valid — you're just telling the linker these sections are mutually exclusive

    Since all three now share the same run address, your memcpy destination is the shared cla1Funcs_runstart:

    extern uint32_t cla1Funcs_runstart;
    extern uint32_t cla1Funcs_Application1_loadstart, cla1Funcs_Application1_loadsize;
    extern uint32_t cla1Funcs_Application2_loadstart, cla1Funcs_Application2_loadsize;
    extern uint32_t cla1Funcs_Application3_loadstart, cla1Funcs_Application3_loadsize;

    if (Application == Application1)
    {
    memcpy(&cla1Funcs_runstart, &cla1Funcs_Application1_loadstart,
    (uint32_t)&cla1Funcs_Application1_loadsize);
    }
    else if (Application == Application2)
    {
    memcpy(&cla1Funcs_runstart, &cla1Funcs_Application2_loadstart,
    (uint32_t)&cla1Funcs_Application2_loadsize);
    }
    else if (Application == Application3)
    {
    memcpy(&cla1Funcs_runstart, &cla1Funcs_Application3_loadstart,
    (uint32_t)&cla1Funcs_Application3_loadsize);
    }

    Thanks,

    Ira

  • Thanks Ira, I'll give this a try and see how it works.  

    with     Cla1Prog_Application1: { /* Application1 objects */ }

    I assume /* Application1 objects */ are:

    RUN_START(cla1Funcs_Application1_runstart),
    RUN_SIZE(cla1Funcs_Application1_runsize),
    RUN_END(cla1Funcs_Application1_runend)

    Thanks,

    Andy B

  • Yes, that's corrrect.