cancel
Showing results forĀ 
Search instead forĀ 
Did you mean:Ā 

stm32cubeIDE doesn not support declaring variable in DTCM on STM32H7 directly

SeyyedMohammad
Senior III

I've tried to create variable on DTCM memory region based on Cube package example. They've used __attribute__ ((section(".DTCM"))). But as you can see the build analyzer shows that it occupied D1 ram area not DTCM. Also by enlarging this varibale, area occupied in Flash will enlarge:o šŸ˜³.

0693W00000UoGp0QAF.png 

How to define it correctly to make build analyzer show correcly?

Note: I know we can manage it's adresses by our own. But I want to force compler to manage the memory like how it manages RAM_D1 and FLASH memory.

1 ACCEPTED SOLUTION

Accepted Solutions
Syn_BE
Associate III

Hi @SeyyedMohammadā€‹ ,

I haven't linked a variable to DTCM memory so far, but so other sections in RAM.

Perhaps the following steps can help you out:

  • open your "STM32H7xx_FLASH.ld" linker script for edit
  • under "Memory definitions" there should be something like:
    •  DTCMRAM          (xrw)  : ORIGIN = 0x20000000, LENGTH = 128K
  • go to "SECTIONS"
    • scroll down to the "/* Remove information from the compiler libraries */" - line
  • enter the following code lines ABOVE the "/* Remove information from the compiler libraries */"-line

  .DTCMRAM_sec (NOLOAD) :
  {
    *(.DTCMRAM_section) 
  } >DTCMRAM

then, define your variable the following way:

__attribute__((section(".DTCMRAM_section")))  uint32_t a[1234];

Best regards, Andy

View solution in original post

7 REPLIES 7
Syn_BE
Associate III

Hi @SeyyedMohammadā€‹ ,

I haven't linked a variable to DTCM memory so far, but so other sections in RAM.

Perhaps the following steps can help you out:

  • open your "STM32H7xx_FLASH.ld" linker script for edit
  • under "Memory definitions" there should be something like:
    •  DTCMRAM          (xrw)  : ORIGIN = 0x20000000, LENGTH = 128K
  • go to "SECTIONS"
    • scroll down to the "/* Remove information from the compiler libraries */" - line
  • enter the following code lines ABOVE the "/* Remove information from the compiler libraries */"-line

  .DTCMRAM_sec (NOLOAD) :
  {
    *(.DTCMRAM_section) 
  } >DTCMRAM

then, define your variable the following way:

__attribute__((section(".DTCMRAM_section")))  uint32_t a[1234];

Best regards, Andy

Hi @Syn_BEā€‹ 

Thank you so much, As you can see later maybe we need also startup code, doesn't? Also what is the meaning of noload?

Your way is really simple, but why in the project they have added lots of code?:wheelchair_symbol:ļæ½?

In example code we have something about DTCM in xxxxx_FLASH.ld:

/* used by the startup to initialize DTCMRAM */
  _siDTCMRAM = LOADADDR(.data_DTCMRAM);
 
  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data_DTCMRAM : 
  {
    . = ALIGN(4);
    _sDTCMRAM = .;        /* create a global symbol at data start */
    *(.data_DTCMRAM)           /* .data sections */
    *(.data_DTCMRAM*)          /* .data* sections */
 
    . = ALIGN(4);
    _eDTCMRAM = .;        /* define a global symbol at data end */
  } >DTCMRAM AT> FLASH
 
  /* Uninitialized data section */
  . = ALIGN(4);
  .bss_DTCMRAM :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss_DTCMRAM = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss_DTCMRAM;
    *(.bss_DTCMRAM)
    *(.bss_DTCMRAM*)
    *(COMMON)
 
    . = ALIGN(4);
    _ebss_DTCMRAM = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss_DTCMRAM;
  } >DTCMRAM
 
//common code between example and none example project
  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
 
  .ARM.attributes 0 : { *(.ARM.attributes) }
//End of common code
 
 
.DTCMRAM : { *(.DTCMRAM) } >DTCMRAM AT> FLASH

And it seems we neeed something in startup code:

/* Copy the data segment initializers from flash to DTCMRAM */
  movs  r1, #0
  b  LoopCopyDataInit_DTCMRAM
 
CopyDataInit_DTCMRAM:
  ldr  r3, =_siDTCMRAM
  ldr  r3, [r3, r1]
  str  r3, [r0, r1]
  adds  r1, r1, #4
 
LoopCopyDataInit_DTCMRAM:
  ldr  r0, =_sDTCMRAM
  ldr  r3, =_eDTCMRAM
  adds  r2, r0, r1
  cmp  r2, r3
  bcc  CopyDataInit_DTCMRAM
  ldr  r2, =_sbss_DTCMRAM
  b  LoopFillZerobss_DTCMRAM
/* Zero fill the bss segment. */
FillZerobss_DTCMRAM:
  movs  r3, #0
  str  r3, [r2], #4
 
LoopFillZerobss_DTCMRAM:
  ldr  r3, = _ebss_DTCMRAM
  cmp  r2, r3
  bcc  FillZerobss_DTCMRAM

 Here we have some code about DTCM on none example project xxxxx_RAM.ld:

/* 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 */
  } >DTCMRAM AT> RAM_EXEC
 
  /* 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;
  } >DTCMRAM
 
  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >DTCMRAM

What are you understanding from them? I really want to know them, plese.

Pavel A.
Evangelist III

Your DTCM sections in the link script are named .data_DTCMRAM, .bss_DTCMRAM.

So, write:  __attribute__ ((section(".bss_DTCMRAM")))

Or use any other name in the link script.

NOLOAD means the linker just has to track symbols/usage, it doesn't have to initialize the memory with any content. So not cleared to zero, and not filled with initialization data. No content for the section will appear within the .ELF or .HEX files.

The clearing/copying is handled in startup.s, and needs symbols to understand where the initial content is parked within the load image (in FLASH), and the locations and sizes of the memory to zero, and the memory to copy.

Better tools, like IAR/KEIL keep track of this in tables, and automate/hide the process as part of the scatter load process. The Arduino GNU/GCC team has also done something similar with tables, but the ST team just doesn't bother.

The Linker Script (.LD) can be as simple or complex as you choose to make it.

Remember it is processed in a mostly linear fashion, allowing the linker to decide where to put different things based on the group/section and naming the compiler, or it's user, gives different symbols.

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

Hi @Pavel A.ā€‹ 

As you can see in the question .bss_DTCMRAM and .data_DTCMRAM are defined in the example project's code and not my code. Note that in the example's code, they've used __attribute__ ((section(".DTCMRAM"))), which is conflicted yours, maybe youve missed something!?

Hello @Community memberā€‹ 

Then noload means: our varibales initial values will be neglected?

The startup code i've mentioned is what you are told that is not contained by st team? I can't understand what is exactly missed by st team? sine it seems they are handling normal variables in D1 domain as you said and the build analyzer visualize track of variables and codes, doesn't it?

Yes, maybe I've looked in the wrong snippet. Use the name defined in your link script. If the array is not initialized (zero filled), prefer BSS.