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.

TM4C1294KCPDT: CCS adding ARM pragma data sections creates huge bin file

Guru 55913 points
Part Number: TM4C1294KCPDT

Hello,

The memory allocation shows the compiled project is below 1 megabyte after moving parts of flash functions to RAM via 6 pragma statements. However the compiled bin file grew to 512MB and was initially 106KB without moving functions from flash to RAM via #pragma. Why is the *.out file size 934KB relatively small and why does the Memory Allocation tool show much smaller bin file size?

  • Please see the article An Introduction to Binary Files.  Among other things, it explains how a binary file can become very large, and how you can avoid that problem.

    Thanks and regards,

    -George

  • Hi George,

    Why you didn't answer the questions or any part of them?

    I don't need an introduction to binary files. The project is the same, only some parts were moved to RAM from Flash via #pragma. The CPU and stack pointer should handle the push/pops jump and return addresses of call far's. More jumping than calling in my opinion, the IP should simply move to different memory address.  That is a function of the CPU to know where parts of a program exist in memory by call stack and IP. What are all the ARM trampolines being created for, that didn't occur on C2000 CPU?

    The Memory Allocation tool disagrees with compiled bin file size only after hex2bin.exe runs does it grow from 106KB to 524MB. Something else has gone wrong, there are no warnings the sections are invalid trampolines like C2000 compiler produces. Also added linker command --minimize_trampolines has no effect, there are 50 or more in each new section added in black text. A few holes would be acceptable as shown in the MAP file.

    Yet again the application in flash and RAM are nowhere the size of the output bin file. The Memory Allocation tool is supposed to reflect the build, only after compile completes without errors and hex2bin.exe created for flash memory loads.

    Notice even adding one pragma (ISR function) bin file bloats to 524MB the other sections returned to flash.

  • I have seen problems similar to yours many times.  Please read the article.  It addresses your problem.

    Thanks and regards,

    -George

  • I read the article and it does not address 500 megabyte hole from adding single pragma of 308 bytes. The compiler seems to be adding thousands of bytes for single call far, for each 8 byte trampoline of 308 byte pragma it seems.

    Do you believe 3 trampolines (8 bytes each) can be equal to 500 Megabytes in binary file output? We can't view the 500MB binary file as it will freeze the hexadecimal viewing tool. 

  • I read the article and it does not address 500 megabyte hole

    Yes it does.  The example has a hole in it.  It occurs because there is a gap in memory between initialized sections.  Your hole occurs for the same reason.  This is the only reason a hole may occur in a binary file.  Your hole is much bigger, because the distance in memory between the initialized sections is much greater.   The article also discusses how to avoid such holes.

    Thanks and regards,

    -George

  •  The article also discusses how to avoid such holes.

    Find it odd the C2000 has no such issues when additional pragma defines are placed at the end of the CMD file. Moving the ARM pragma section above the other RAM defined sections did not stop the huge hole from forming. The other section defines are Flash related. Why would anyone think to move a RAM pragma above Flash section for a flash written firmware?

    BTW: The article referenced (*.out) file size not the MkHex4Bin.exe file size.  Oddly the smallest sized pragma is always shown at the end Memory Allocation from largest to smallest size RAM module. The *.out file remains reasonably small 930KB. The compiler and linker do not resolve --gap-fill directive. 

  • However the compiled bin file grew to 512MB and was initially 106KB without moving functions from flash to RAM via #pragma.

    On the TM4C1294KCPDT the flash starts at address 0 and the RAM at address 0x20000000 (512MB). The use of the #pragma to set the load address of functions to RAM causes the binary file to become 512MB as the binary file format can't have holes in the address range.

    The other issue with using the #pragma to set the load address of functions to RAM is that on a device reset / power cycle there is no mechanism to load the functions into RAM. Therefore, such a program can only be run from the CCS debugger.

    To place functions in RAM, using the TI ARM compiler, instead use __attribute ((ramfunc)) on a function in the source code. E.g.:

    __attribute ((ramfunc))
    void
    UARTIntHandler(void)

    And in the linker command file declare .binit and .TI.ramfunc sections. E.g.:

    /* Section allocation in memory */
    
    SECTIONS
    {
        .intvecs:   > APP_BASE
        .text   :   > FLASH
        .const  :   > FLASH
        .cinit  :   > FLASH
        .pinit  :   > FLASH
        .init_array : > FLASH
        .binit > FLASH
    
        .vtable :   > RAM_BASE
        .data   :   > SRAM
        .bss    :   > SRAM
        .sysmem :   > SRAM
        .stack  :   > SRAM
    #ifdef  __TI_COMPILER_VERSION__
    #if     __TI_COMPILER_VERSION__ >= 15009000
        .TI.ramfunc : {} load=FLASH, run=SRAM, table(BINIT)
    #endif
    #endif
    }
    

    This causes the run time start up code to copy the functions from the load address in FLASH to the run address in SRAM, without causing the binary file to become 512MB.

  • Hi Chester,

    I have more than one pragma to load into RAM address and leave bulk of configuration functions in flash. The ARM compiler should be handling proper pragma sections in CMD file without adding holes as there is no text covering this conundrum. The C2000 compiler lets us know if the CMD file has created sections with trampolines.

    The default TM4C1294 project CMD file was very generic in scope and with bootloader application loaded to flash starting at 0x4000 even more so. Adding .binit > FLASH might help to load several pragmas from various functions. The bootloader copies into RAM points back to the flash vector table or something along those lines, even though it has it's own vector table. That might be why the *.bin file is growing so large.

  • Therefore, such a program can only be run from the CCS debugger.

    The application (main.c) should have mcopy() added as to copy .TI.ramfunc CODE_SECTION from flash to RAM. Seemingly the ARM compiler should add pragma offset address after copying #pragma functions. Forgot to add mcopy() command, perhaps cause for the large memory hole.

    C2000 mcopy(), pragma and CMD file section:

    #include <stddef.h>

    device.h:

    extern uint16_t RamfuncsLoadStart;
    extern uint16_t RamfuncsLoadEnd;
    extern uint16_t RamfuncsLoadSize;
    extern uint16_t RamfuncsRunStart;
    extern uint16_t RamfuncsRunEnd;
    extern uint16_t RamfuncsRunSize;

    // The RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart symbols
    // are created by the linker. Refer to the device.h CMD file.
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

    MEMORY
    {
        PAGE 0 :

       RAMLS0_1         : origin = 0x008000, length = 0x001000 //4096KB

       RAMLS2_3         : origin = 0x009100, length = 0x000F00 //4096KB -16 words, errata advisory read past end of memory bank cause CRC errors.

    }

    #pragma CODE_SECTION(myISR, ".TI.ramfunc")

    SECTIONS {
          codestart : > BEGIN, ALIGN(4)

    // RAM address locations of only the first pragma required, all other (data_section) pragma have simple section shown below

         .TI.ramfunc : LOAD = FLASHB0_SA,
                              RUN = RAMLS2_3, // RAM bank
                              LOAD_START(RamfuncsLoadStart),
                              LOAD_SIZE(RamfuncsLoadSize),
                              LOAD_END(RamfuncsLoadEnd),
                              RUN_START(RamfuncsRunStart),
                              RUN_SIZE(RamfuncsRunSize),
                              RUN_END(RamfuncsRunEnd),
                              ALIGN(4)

    }

    Placed above function: #pragma DATA_SECTION (MyParams, ".params.ramdata");

    SECTIONS {

        .params.ramdata : > RAMLS0_1 //defined memory as flash page 0 or 1

        .myvars.ramdata  : > RAMLS0_1

    }

  • I created more complex tm4c1294 CMD file with 4 SRAM 65KB Sections (262KB) in Page 0. Similar to C2000 CMD file syntax above with 3 mcopy() placements and SRAM_0 default as; .bss, .stack, .vtable, .data defines. Not had chance to load it but the *.bin file size is 107KB after main.c asserts mcopy() commands. Notice the Flash retains the 3 pragma sections after mcopy() into RAM also needed to have occur in a C2000 project.