cancel
Showing results for 
Search instead for 
Did you mean: 

Extremely Large Binary Size When Using DTCMRAM

EPala.2
Associate III

Hi, I am working on a project with the STM32H730. In order to make full use of the onboard memory I have the project set up to load some objects into DTCMRAM. This works, however the binary size is huge, like 403 MB, and subsequently is crashing cube programmer:

Screen Shot 2023-12-05 at 9.08.12 AM.png

It seems like something is going wrong here and a huge amount of unnecessary information is getting stored in the binary file. 

Can you recommend a way to fix this while still using DTCMRAM for data?

Here is the DTCMRAM section of my linker file, and how I am allocating objects to DTCMRAM:

/* Define output sections */

SECTIONS

{

  /* The startup code goes first into FLASH */

  .isr_vector :

  {

    . = ALIGN(4);

    KEEP(*(.isr_vector)) /* Startup code */

    . = ALIGN(4);

  } >FLASH

  

  .dtcm_ram : {

    . = ALIGN(4);

_sDTCMData=.;        

 

*(.dtcm_ram)

 

.=ALIGN(4);

_eDTCMData=.;        /* create a global symbol at DTCMData end */

   

  } >DTCMRAM

Screenshot 2023-12-05 at 1.12.44 PM.png

 

9 REPLIES 9

You need to split the .BIN files into sections. Or use .HEX or .ELF which has the meta-data for discontinuous / sparse data regions.

Secondarily you need to manage RAM initialization in startup.s, or make the sections NOLOAD

See how startup.s unpacks and clears the RAM via statics it stores in the ROM/FLASH section.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

See how the AT> directive is used here, where CCMRAM is like DTCMRAM, in this linker script (.LD) file

...
  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH

  _siccmram = LOADADDR(.ccmram);

  /* CCM-RAM section
  *
  * IMPORTANT NOTE!
  * If initialized variables will be placed in this section,
  * the startup code needs to be modified to copy the init-values.
  */
  .ccmram :
  {
    . = ALIGN(4);
    _sccmram = .;       /* create a global symbol at ccmram start */
    *(.ccmram)
    *(.ccmram*)

    . = ALIGN(4);
    _eccmram = .;       /* create a global symbol at ccmram end */
  } >CCMRAM AT> FLASH


  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM
...  
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

What does NOLOAD mean? 

How would I mark sections as such in startup.s in order to reduce filesize?

Okay so does CCMRAM just replace DTCMRAM? It's like the same thing but denotes that initialization values aren't saved in the binary?

NOLOAD would mean there is no data in the section, there would be NOBITS in the .ELF file, and you wouldn't be trying to "program" a section of RAM in STM32 Cube Programmer. Content disappears after power cycle.

https://community.st.com/t5/other-tools-mcus/defining-noload-section-in-ld-script-for-gcc/td-p/334763

https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/gjpww/index.html

https://stevens.netmeister.org/631/elf.html

 

There's a lot of documentation on the link, linker scripts, and the .ELF format on-line

The .BIN and .HEX are generated from the .ELF

Keil's FROMELF tools by default splits sparse sections into individual files, so there aren't multiple MB or GB voids in the files.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Okay, maybe to hone in on what I need specifically.

I am only using TCMRAM because I ran out of regular RAM for the project. This is an audio DSP process that involves several large delay lines and some of them need to live in TCMRAM to fit in internal memory. There is no TCM aspect I need for this, it's just to have all the delay lines fit in onboard memory.

 

I would like the TCMRAM to function exactly like regular RAM in every way (loaded how RAM gets loaded, not bloating .bin filesize).

How do I do that?

Don't involve any TCM in the linking/imaging of your app & manage the TCM directly via your code.

>>How do I do that?

If you need the memory initialized with content you need to stage it in FLASH and copy it out

} >DTCMRAM AT> FLASH

If it does not then

.dtcm_ram : (NOLOAD) {

 

Remember it processes the Linker Script in a linear fashion so the order it encounters sections, and the way you define symbols matters. I've provided a general outline of how the script flows.

In startup.s you've got to use the symbols to initialize the space by copying the content from the staging area in FLASH. See how (_edata - sdata) define the size of the staged data, _sdata where it goes, _sidata where it comes from for the ">RAM AT> FLASH" .data section

 

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Piranha
Chief II

It cannot be exactly the same, because it is not the same. Read the AN4891 and learn the differences. But a general advice is - put all the stacks and intensively accessed (like for DSP processing) variables in DTCM.