Skip to main content
STork.1
Associate III
January 5, 2021
Question

How to change linker script file in order to put data into CCMRAM?

  • January 5, 2021
  • 2 replies
  • 14303 views

Hello everybody! I need to store dataset into the RAM of my MCU. I use STM32H755ZIT6, Dual Core M7+M4. The problem is that when I define buffer for my data the ram will overflow. The Ram size is 1MB but the whole data set's size is around 250KB. it seems that the RAM is not contiguous and based on my search on the internet the clue I have is to use Core Coupled Memory RAM. Around 2/3 of my data fits into the RAM and I want to store the rest of it into the CCRAM area. Sofar I unly could understood that using this statement I can store variable in CCRAM:

__attribute__((section(".ccmram-strings"))) float Data_Set_Z[15000];

When I want to assign a value into this variable, the compiler shows the RAM overflow error. I read some application notes of ST and some block of memories have different address but I don't know how to use the in linker script.

Here is the Linker script file:

here is also the RAM.ld file

/*

******************************************************************************

**

** File    : LinkerScript.ld

**

**

** Abstract  : Linker script for STM32H7 series

**        256Kbytes RAM_EXEC and 256Kbytes RAM

**

**        Set heap size, stack size and stack location according

**        to application requirements.

**

**        Set memory bank area and size if external memory is used.

**

** Target   : STMicroelectronics STM32

**

** Distribution: The file is distributed as is, without any warranty

**        of any kind.

**

*****************************************************************************

** @attention

**

** Copyright (c) 2019 STMicroelectronics.

** All rights reserved.

**

** This software component is licensed by ST under BSD 3-Clause license,

** the "License"; You may not use this file except in compliance with the

** License. You may obtain a copy of the License at:

**            opensource.org/licenses/BSD-3-Clause

**

****************************************************************************

*/

/* Entry Point */

ENTRY(Reset_Handler)

/* Highest address of the user mode stack */

_estack = 0x24080000;  /* end of RAM */

/* Generate a link error if heap and stack don't fit into RAM */

_Min_Heap_Size = 0x200 ;   /* required amount of heap */

_Min_Stack_Size = 0x400 ; /* required amount of stack */

/* Specify the memory areas */

MEMORY

{

RAM_EXEC (rx)   : ORIGIN = 0x24000000, LENGTH = 256K

RAM (xrw)   : ORIGIN = 0x24040000, LENGTH = 256K

}

/* Define output sections */

SECTIONS

{

 /* The startup code goes first into RAM_EXEC */

 .isr_vector :

 {

  . = ALIGN(4);

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

  . = ALIGN(4);

 } >RAM_EXEC

 /* The program code and other data goes into RAM_EXEC */

 .text :

 {

  . = ALIGN(4);

  *(.text)      /* .text sections (code) */

  *(.text*)     /* .text* sections (code) */

  *(.glue_7)     /* glue arm to thumb code */

  *(.glue_7t)    /* glue thumb to arm code */

  *(.eh_frame)

  KEEP (*(.init))

  KEEP (*(.fini))

  . = ALIGN(4);

  _etext = .;    /* define a global symbols at end of code */

 } >RAM_EXEC

 /* Constant data goes into RAM_EXEC */

 .rodata :

 {

  . = ALIGN(4);

  *(.rodata)     /* .rodata sections (constants, strings, etc.) */

  *(.rodata*)    /* .rodata* sections (constants, strings, etc.) */

  . = ALIGN(4);

 } >RAM_EXEC

 .ARM.extab  : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM_EXEC

 .ARM : {

  __exidx_start = .;

  *(.ARM.exidx*)

  __exidx_end = .;

 } >RAM_EXEC

 .preinit_array   :

 {

  PROVIDE_HIDDEN (__preinit_array_start = .);

  KEEP (*(.preinit_array*))

  PROVIDE_HIDDEN (__preinit_array_end = .);

 } >RAM_EXEC

 .init_array :

 {

  PROVIDE_HIDDEN (__init_array_start = .);

  KEEP (*(SORT(.init_array.*)))

  KEEP (*(.init_array*))

  PROVIDE_HIDDEN (__init_array_end = .);

 } >RAM_EXEC

 .fini_array :

 {

  PROVIDE_HIDDEN (__fini_array_start = .);

  KEEP (*(SORT(.fini_array.*)))

  KEEP (*(.fini_array*))

  PROVIDE_HIDDEN (__fini_array_end = .);

 } >RAM_EXEC

 /* 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> RAM_EXEC

  

 /* Uninitialized data section */

 . = ALIGN(4);

 .bss :

 {

  /* This is used by the startup in order to initialize the .bss secion */

  _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

 /* 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);

 } >RAM

  

 /* Remove information from the standard libraries */

 /DISCARD/ :

 {

  libc.a ( * )

  libm.a ( * )

  libgcc.a ( * )

 }

 .ARM.attributes 0 : { *(.ARM.attributes) }

}

  

another thing I am considering is that the RAM blocks are as follows:0693W000006HdaLQAS.png 

based on Linker script file I mentioned before, a 256KB block is only used . that is the reason of RAM overflow ,I think... .

2) How Can I use a bigger block? for example the block the name of which is SRAM mapped onto AXI bus 512 in the table below?

0693W000006HddUQAS.png 

Despite the searches I did I could not understand how to change the linker-script files. Is there anybody who has time to help me regarding the mentioned two questions??

I think the more logical choice is to just select the bigger RAM In D1 domain which is also provided to M7 Core I am using ....

I tried changing the address space of the ram in the .ld file . at first, it was from /* : ORIGIN = 0x24000000, LENGTH = 256K */ to /* : ORIGIN = 0x24040000, LENGTH = 256K */.

then I changed it from 0x24000000, LENGTH = 512K to : ORIGIN = 0x2407FFFF, LENGTH = 512K according to memory-map file in the user manuals but after biulding the project I still get the ram overflow messege...... Please Help :)))

here are the error messeges.

0693W000006HdfzQAC.png 

Looking forward to your replies.

Best Regards

    This topic has been closed for replies.

    2 replies

    TDK
    January 6, 2021

    This explains it well. You need to add a definition for the CCMRAM section.

    https://www.openstm32.org/Using+CCM+Memory?structure=Documentation

    "If you feel a post has answered your question, please click ""Accept as Solution""."
    STork.1
    STork.1Author
    Associate III
    January 6, 2021

    Thanks, before posting here I red this page but since I am a beginner I confused and could not exactly understand what I am supposed to do ... .

    Tesla DeLorean
    Guru
    January 6, 2021

    If you want to initialize the data you'll have to work harder, and fix startup.s too.

    Anyway, the following should direct data into a separate section

    __attribute__((section(".dtcmram"))) float Data_Set_Z[15000];

    /*
    ******************************************************************************
    **
    ** File : LinkerScript.ld
    **
    **
    ** Abstract : Linker script for STM32H7 series
    ** 256Kbytes RAM_EXEC and 256Kbytes RAM
    **
    ** Set heap size, stack size and stack location according
    ** to application requirements.
    **
    ** Set memory bank area and size if external memory is used.
    **
    ** Target : STMicroelectronics STM32
    **
    ** Distribution: The file is distributed as is, without any warranty
    ** of any kind.
    **
    *****************************************************************************
    ** @attention
    **
    ** Copyright (c) 2019 STMicroelectronics.
    ** All rights reserved.
    **
    ** This software component is licensed by ST under BSD 3-Clause license,
    ** the "License"; You may not use this file except in compliance with the
    ** License. You may obtain a copy of the License at:
    ** opensource.org/licenses/BSD-3-Clause
    **
    ****************************************************************************
    */
     
    /* Entry Point */
    ENTRY(Reset_Handler)
     
    /* Highest address of the user mode stack */
    _estack = 0x24080000; /* end of RAM */
    /* Generate a link error if heap and stack don't fit into RAM */
    _Min_Heap_Size = 0x200 ; /* required amount of heap */
    _Min_Stack_Size = 0x400 ; /* required amount of stack */
     
    /* Specify the memory areas */
    MEMORY
    {
    RAM_DTCM (rw) : ORIGIN = 0x00000000, LENGTH = 128K
    RAM_EXEC (rx) : ORIGIN = 0x24000000, LENGTH = 256K
    RAM (xrw) : ORIGIN = 0x24040000, LENGTH = 256K
    }
     
    /* Define output sections */
    SECTIONS
    {
     /* The startup code goes first into RAM_EXEC */
     .isr_vector :
     {
     . = ALIGN(4);
     KEEP(*(.isr_vector)) /* Startup code */
     . = ALIGN(4);
     } >RAM_EXEC
     
     .dtcm (NOLOAD) :
     {
     *(.dtcmram)
     *(.dtcmram*)
     } >RAM_DTCM
     
     /* The program code and other data goes into RAM_EXEC */
     .text :
     {
     . = ALIGN(4);
     *(.text) /* .text sections (code) */
     *(.text*) /* .text* sections (code) */
     *(.glue_7) /* glue arm to thumb code */
     *(.glue_7t) /* glue thumb to arm code */
     *(.eh_frame)
     
     KEEP (*(.init))
     KEEP (*(.fini))
     
     . = ALIGN(4);
     _etext = .; /* define a global symbols at end of code */
     } >RAM_EXEC
     
     /* Constant data goes into RAM_EXEC */
     .rodata :
     {
     . = ALIGN(4);
     *(.rodata) /* .rodata sections (constants, strings, etc.) */
     *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
     . = ALIGN(4);
     } >RAM_EXEC
     
     .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM_EXEC
     .ARM : {
     __exidx_start = .;
     *(.ARM.exidx*)
     __exidx_end = .;
     } >RAM_EXEC
     
     .preinit_array :
     {
     PROVIDE_HIDDEN (__preinit_array_start = .);
     KEEP (*(.preinit_array*))
     PROVIDE_HIDDEN (__preinit_array_end = .);
     } >RAM_EXEC
     .init_array :
     {
     PROVIDE_HIDDEN (__init_array_start = .);
     KEEP (*(SORT(.init_array.*)))
     KEEP (*(.init_array*))
     PROVIDE_HIDDEN (__init_array_end = .);
     } >RAM_EXEC
     .fini_array :
     {
     PROVIDE_HIDDEN (__fini_array_start = .);
     KEEP (*(SORT(.fini_array.*)))
     KEEP (*(.fini_array*))
     PROVIDE_HIDDEN (__fini_array_end = .);
     } >RAM_EXEC
     
     /* 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> RAM_EXEC
     
     
     /* Uninitialized data section */
     . = ALIGN(4);
     .bss :
     {
     /* This is used by the startup in order to initialize the .bss secion */
     _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
     
     /* 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);
     } >RAM
     
     
     /* Remove information from the standard libraries */
     /DISCARD/ :
     {
     libc.a ( * )
     libm.a ( * )
     libgcc.a ( * )
     }
     
     .ARM.attributes 0 : { *(.ARM.attributes) }
    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    STork.1
    STork.1Author
    Associate III
    January 6, 2021

    Thanks Tesla DeLorean, I still get the same RAM overflow errors. If you have time can you please explain what changes did you do in the linker script?

    I red it but it was vague for me ....

    Tesla DeLorean
    Guru
    January 6, 2021

    The data still has to fit.

    Not clear why the entire code/data needs to be in RAM. You might want to look at alternate ways of loading the RAM, ones where it doesn't need to copy initialized statics from one section to another, basically halving the available resources.

    Perhaps you can look at the .MAP file as see where all the resources are being sucked up? You can make the MEMORYs unduly large so the linker can get closure, and then walk the file.

    >>.. but since I am a beginner I confused and could not exactly understand what I am supposed to do ... .

    In support cases it important impart the skills you do have, not the ones you don't.

    Any MCU related stuff? Any linker/loader fundamentals? High School / College level?

    >>If you have time can you please explain what changes did you do in the linker script? I read it but it was vague for me ....

    The MEMORY portion tells the linker about the memory spaces available to it within the device. This can be a constrained subset of all resources.

    The SECTION portion tells the linker about how to allocate sub-portions of the memory for different things, code/text, data, bss/uninitialized statics, ie stuff you assume starts with zeros in it. It controls the ordering of things, it can put things in the first bucket that meet the criterion expressed in the script.

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