Compiler/PROCESSOR-SDK-AM335X: ARM Binary application huge due to holes in memory section

Part Number: PROCESSOR-SDK-AM335X

Tool/software: TI C/C++ Compiler

Setup:

AM3359 ICEv2 application
Compiler version TI v5.1.11
XDC 3.25.4.88
SYSBIOS 6.35.4.50
Industrial SDK: am335x_sysbios_ind_sdk_1.1.0.4

Hi, I am working on moving some critical section  sysbios (KNL and HWI APIs) from DDR to SRAM as mentioned in this Wiki link  (attached new linker command) 

With these changes app.out works OK, size is ~3.3MB, and I can download it and run it via CCS+JTAG.

However, I need to test my changes using  an SD card (customer's test application requires multiple resets). When running postbuild scripts the final binary is huge, about 1GB! .

I have been trying different settings for stripping unnecessary information and debug information but the size is mainly the same. Below examples of what I have tried:

Test1: arm-none-eabi-objcopy.exe -O binary -R .ARM.exidx -R .ARM.extab -R .debug_aranges -R .debug_info -R .debug_abbrev -R debug_pubnames -R debug_aranges -R debug_pubtypes -R .debug_line -R .debug_frame -R .debug_str -R .debug_loc -R .debug_ranges app.out app.bin

Test2: arm-none-eabi-objcopy.exe -O binary  --strip-all --strip-debug --strip-unneeded app.out app.bin

Test3: arm-none-eabi-objcopy.exe -O binary -j .init -j ti.sysbios.family.arm.a8.mmuTableSection -j .knl -j .hwi -j .sysbios -j .stack -j .bss -j .neardata -j rodata -j .cinit -j .args -j .vecs -j xdc.meta -j .text -j .const.1 -j cost.2 -j .data app.out app.bin

I read online that the issue is the "hole" between memory sections in this case DDR and SRAM. 

Question to the compiler experts:

- Is there any trick that I can use in order to take out the "hole"?

- is there any objcopy configuration that I can try?

- Any other idea is also welcome =)

am335x.cmd

Thank you,

Paula

  • Unfortunately, you are up against a fundamental limitation of binary files.  Any hole in the memory map is filled with zeros.  There is nothing else that can be done.

    Thanks and regards,

    -George


    TI C/C++ Compiler Forum Moderator
    Please click Verify Answer on the best reply to your question
    The CCS Youtube Channel
     has short how-to videos
    The 
    Compiler Wiki answers most common questions
    Track an issue with SDOWP. Enter your bug id in the Search box.

  • Paula Carrillo
    - Any other idea is also welcome =)

    The SYS/BIOS functions which need to run in SRAM need to be given a run address in SRAM, and a load address in DDR. That means that the binary file won't then have to fill the "hole" between the DDR and SRAM. Start-up code is required to copy the SYS/BIOS functions from the load address in DDR to the run address in SRAM.

    I tried modifying a SYS/BIOS program for a AM437x IDK. In the .cfg file the following was added:

    /* Place all the knl APIs in OCMCRAM */
    var knl_section_name = ".knl : { __knl_load__ = LOADADDR (.knl); __knl_start__ = .; *.*(.text.ti_sysbios_knl*); . = ALIGN (4); __knl_end__ = .; }";
    
    Program.sectMap[knl_section_name] = new Program.SectionSpec ();
    Program.sectMap[knl_section_name].loadSegment = "EXT_RAM";
    Program.sectMap[knl_section_name].runSegment = "OCMCRAM";
    
    /* Install a reset function which relocates the .knl section from the load address in EXT_RAM (DDR3) to OCMCRAM */
    var Reset = xdc.useModule("xdc.runtime.Reset");
    Reset.fxns[Reset.fxns.length++] = "&copy_kernel_funcs";

    And the following C code was added:

    extern unsigned int __knl_load__, __knl_start__, __knl_end__;
    
    xdc_Void copy_kernel_funcs(void)
    {
        unsigned int * kl;
        unsigned int * ks;
        unsigned int * ke;
    
        /* relocate the .knl section */
        kl = & __knl_load__;
        ks = & __knl_start__;
        ke = & __knl_end__;
        if (kl != ks) {
            while (ks < ke) {
                *ks = *kl;
                kl++;
                ks++;
            }
        }
    }

    The .cfg changes configure SYS/BIOS to create a .knl section in the generated linker script which has the load address of the required functions in DDR and the run address in SRAM, and registers a start-up function called copy_kernel_funcs() to copy the contents of the .knl section from DDR to SRAM. The changes were based upon how the .data section is handled.

    I tested that with the changes the example still ran using the CCS debugger and checked that the ti_sysbios_knl* functions were running in SRAM. I haven't checked that the binary file ran from SD card, but the generated binary file size was 84,348  bytes which shows that doesn't include the "hole" between DDR and SRAM.

    The names of the memory region would need to be changed to match your target.

  • In reply to Chester Gillon:

    Hi Chester, thank you so much, this seems to be exactly what I need. A quick question, where did you add your .c code?. I tried few places (main.c, cfg, linker cmd) without luck.

    Thanks again for all your help,
    Paula
  • In reply to Paula Carrillo:

    Paula Carrillo
    A quick question, where did you add your .c code?

    I added the copy_kernel_funcs() function in the C source file which contained the main() function. I have attached the complete example for reference. clock_IDK_AM437X_CortexA.zip

    Paula Carrillo
    I tried few places (main.c, cfg, linker cmd) without luck.

    Did you get an error compiling the project, or did the program fail when run?

  • In reply to Chester Gillon:

    Hi Chester, I am getting an error while compiling.

    Error is:
    #10008-D configPkg/linker.cmd cannot find file ".knl" app  line 159 C/C++ Problem

    Maybe it is because I have an additional linker command file linked to my project (the one I attached in my first post), that app.cfg  cannot add a .knl section.. I will try few things and let you know.

    thank you,

    Paula 

  • In reply to Paula Carrillo:

    Hi Chester, actually previous error was really complaining for "(" in below's app.cfg code line

    var knl_section_name = ".knl : { __knl_load__ = LOADADDR (.knl); __knl_start__ = .; *.*(.text.ti_sysbios_knl*); . = ALIGN (4); __knl_end__ = .; }";

    I wasn't able to figure out how to make it work, so I use your idea of loading KNL and HWI sections in DDR and running them from SRAM,  inside my project linker command as shown below:

    am335x.cmd 


    /* place all the knl and Hwi APIs in SRAM_HI */ .knlhwi: { *.*(.text:*ti_sysbios_knl*) *.*(.text:*ti_sysbios*_Hwi_*) } load > DDR3, run > SRAM_HI, align =0x4 LOAD_START(__knlhwi_load__) RUN_START(__knlhwi_start__) RUN_END(__knlhwi_end__)

    In main.c I added the copy function as you suggested:

    extern unsigned int __knlhwi_load__, __knlhwi_start__, __knlhwi_end__;
    
    xdc_Void copy_kernel_hwi_funcs(void)
    {
        unsigned int * kl;
        unsigned int * ks;
        unsigned int * ke;
        /* relocate the .knl section */
        kl = & __knlhwi_load__;
        ks = & __knlhwi_start__;
        ke = & __knlhwi_end__;
        if (kl != ks) {
            while (ks < ke) {
                *ks = *kl;
                kl++;
                ks++;
            }
        }
    }

    And in my app.cfg I left your lines for XDC "reset" function: 

    /* Install a reset function which relocates the .knlhwi section from the load address in EXT_RAM (DDR3) to SRAM_HI */
    var Reset = xdc.useModule("xdc.runtime.Reset");
    Reset.fxns[Reset.fxns.length++] = "&copy_kernel_hwi_funcs";
    


    With those changes now KNL and HWI are in SRAM and binary SD has not holes, so it has a decent size.
    Thanks for all your help,
    Paula

  • In reply to Paula Carrillo:

    Paula Carrillo
    Hi Chester, actually previous error was really complaining for "(" in below's app.cfg code line

    var knl_section_name = ".knl : { __knl_load__ = LOADADDR (.knl); __knl_start__ = .; *.*(.text.ti_sysbios_knl*); . = ALIGN (4); __knl_end__ = .; }";

    The problem was that I didn't read your original post correctly; the mention of arm-none-eabi-objcopy.exe made me think the GCC ARM compiler was in use whereas you did say the TI ARM compiler was being used.

    The GCC and TI compilers use a different syntax for the SECTIONS which explains the errors. The above suggested .cfg code line is for the GCC compiler.