cancel
Showing results for 
Search instead for 
Did you mean: 

Where in Cube IDE are the linker options?

PHolt.1
Senior III

For example how does one put an array or a stack into the CCM RAM?

10 REPLIES 10
TDK
Guru

The linker script is used to define where things go. See:

https://www.openstm32.org/Using%2BCCM%2BMemory

If you feel a post has answered your question, please click "Accept as Solution".
PHolt.1
Senior III

Thanks. Does the Cube IDE generate the linker script, or do you have to edit it manually?

I am familiar with text data bss and such; not familiar with the way it is done with a 32F4.

CubeIDE generates a linker script. If you want something different, you need to edit it accordingly. It's in the top level directory in project explorer.
If you feel a post has answered your question, please click "Accept as Solution".
PHolt.1
Senior III

I can see the file

/* Entry Point */

ENTRY(Reset_Handler)

/* Highest address of the user mode stack */

_estack = 0x20020000;  /* end of 128K RAM on AHB bus*/

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

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

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

/* Specify the memory areas */

MEMORY

{

 FLASH (rx)   : ORIGIN = 0x08000000, LENGTH = 1024K

 RAM (xrw)    : ORIGIN = 0x20000000, LENGTH = 192K

 MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K

}

/* Define output sections */

SECTIONS

{

 /* The startup code goes first into FLASH */

 .isr_vector :

 {

  . = ALIGN(4);

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

  . = ALIGN(4);

 } >FLASH

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

 .text :

 {

  . = ALIGN(4);

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

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

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

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

  *(.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 */

 } >FLASH

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

  .ARM : {

  __exidx_start = .;

   *(.ARM.exidx*)

   __exidx_end = .;

  } >FLASH

 .preinit_array   :

 {

  PROVIDE_HIDDEN (__preinit_array_start = .);

  KEEP (*(.preinit_array*))

  PROVIDE_HIDDEN (__preinit_array_end = .);

 } >FLASH

 .init_array :

 {

  PROVIDE_HIDDEN (__init_array_start = .);

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

  KEEP (*(.init_array*))

  PROVIDE_HIDDEN (__init_array_end = .);

 } >FLASH

 .fini_array :

 {

  PROVIDE_HIDDEN (__fini_array_start = .);

  KEEP (*(.fini_array*))

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

  PROVIDE_HIDDEN (__fini_array_end = .);

 } >FLASH

 /* used by the startup to initialize data */

 _sidata = .;

 /* Initialized data sections goes into RAM, load LMA copy after code */

 .data : AT ( _sidata )

 {

  . = 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

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

 /* MEMORY_bank1 section, code must be located here explicitly      */

 /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */

 .memory_b1_text :

 {

  *(.mb1text)    /* .mb1text sections (code) */

  *(.mb1text*)    /* .mb1text* sections (code) */

  *(.mb1rodata)   /* read-only data (constants) */

  *(.mb1rodata*)

 } >MEMORY_B1

 /* Remove information from the standard libraries */

 /DISCARD/ :

 {

  libc.a ( * )

  libm.a ( * )

  libgcc.a ( * )

 }

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

}

I am trying to work out what this does (it was done by someone else). I can understand the following:

FLASH (rx)   : ORIGIN = 0x08000000, LENGTH = 1024K - this is the 32F417 total flash

RAM (xrw)    : ORIGIN = 0x20000000, LENGTH = 192K - this is the 32F417 total RAM

MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K - this I have no idea and can't find any meaningful reference to it

_estack = 0x20020000; - this appears to set the stack to base of RAM plus 128k, so that leaves the top 64k of RAM unused. Is that right?

It thus looks like this is about the simplest setup one could have... correct?

CCM memory is not being used for anything, From the ref manual : CCM (core coupled memory) mapped at address 0x1000 0000. There is 64k of it. That is below the above RAM so clearly not used. But the 32F4 data sheet says "Up to 192+4 Kbytes of SRAM including 64-Kbyte of CCM (core coupled memory) data RAM" so maybe the CCM is the upper 64k? In which case some remapping must be going on. Or maybe the 192k is not contiguous; you just get 128k and the 64k CCM memory is elsewhere.

    

TDK
Guru

See the reference manual for the memory mapping. In this case:

0693W00000AO110QAD.png 

The memory at 0x20000000 is SRAM and is 128 kB long. The length is incorrect in your linker file and if you try to use more than 128kB your program won't work.

The CCMRAM is at 0x10000000 and is 64kB long. This is not in your linker file, but you can add it. It is not remapped anywhere.

It's common to put the stack at the end of SRAM. You can move it to the end of CCMRAM if you want for a small performance increase and potential pitfalls (DMA can't access CCMRAM).

0x60000000 is in FMC, but since the length is 0, it can't be used in your linker. You could delete it without issue.

If you feel a post has answered your question, please click "Accept as Solution".
PHolt.1
Senior III

Thanks for an excellent reply. I have documented what I have as follows:

MEMORY MAP

FLASH (rx)   : ORIGIN = 0x08000000, LENGTH = 1024K

RAM (xrw)   : ORIGIN = 0x20000000, LENGTH = 192K BUT only 128k is contiguous

MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K - unknown

CCM MEMORY (xrw): ORIGIN = 0x10000000, LENGTH - 64k - not used

The 192k is a mistake in the linker file; it should read 128k.

The CCM memory should be used for the stack (enables code to run while DMA is running) but there is a gotcha: DMA and probably other peripherals can’t access it.

_estack = 0x20020000;  /* end of 128K RAM on AHB bus*/

Currently we are not using DMA, but will be. And the STM ethernet library uses DMA but AIUI uses its own dedicated DMA controller, so it is a question of whether that library is using DMA to transfer to some buffer on the stack. Hmmm ��

 I still have no idea what MEMORY_B1 is.

PHolt.1
Senior III

After a load of googling I think I have sussed it. The FMC (address 0x60000000) is used on the 32F4 development board for the LCD controller. We started with this board but the current product has no LCD, and if it had one I would use something SPI-interfaced.

PHolt.1
Senior III

I am not able to get a variable placed in CCMRAM. The variable is a 1k buffer which is declared with:

uint8_t inbuf[PKT_BUF_LEN] __attribute__((section("ccmram")));

and the new linker script is

/* Entry Point */

ENTRY(Reset_Handler)

/* Highest address of the user mode stack */

_estack = 0x20020000;  /* end of 128K RAM on AHB bus*/

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

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

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

/* Specify the memory areas */

/* CCMRAM added PH 12/5/2021 - cannot use with DMA */

MEMORY

{

 FLASH (rx)   : ORIGIN = 0x08000000, LENGTH = 1024K

 RAM (xrw)    : ORIGIN = 0x20000000, LENGTH = 128K

 MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K

 CCMRAM (rw)   : ORIGIN = 0x10000000, LENGTH = 64K

}

/* Define output sections */

SECTIONS

{

 /* The startup code goes first into FLASH */

 .isr_vector :

 {

  . = ALIGN(4);

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

  . = ALIGN(4);

 } >FLASH

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

 .text :

 {

  . = ALIGN(4);

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

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

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

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

  *(.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 */

 } >FLASH

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

  .ARM : {

  __exidx_start = .;

   *(.ARM.exidx*)

   __exidx_end = .;

  } >FLASH

 .preinit_array   :

 {

  PROVIDE_HIDDEN (__preinit_array_start = .);

  KEEP (*(.preinit_array*))

  PROVIDE_HIDDEN (__preinit_array_end = .);

 } >FLASH

 .init_array :

 {

  PROVIDE_HIDDEN (__init_array_start = .);

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

  KEEP (*(.init_array*))

  PROVIDE_HIDDEN (__init_array_end = .);

 } >FLASH

 .fini_array :

 {

  PROVIDE_HIDDEN (__fini_array_start = .);

  KEEP (*(.fini_array*))

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

  PROVIDE_HIDDEN (__fini_array_end = .);

 } >FLASH

 /* used by the startup to initialize data */

 _sidata = .;

 /* Initialized data sections goes into RAM, load LMA copy after code */

 .data : AT ( _sidata )

 {

  . = 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

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

 /* MEMORY_bank1 section, code must be located here explicitly      */

 /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */

 .memory_b1_text :

 {

  *(.mb1text)    /* .mb1text sections (code) */

  *(.mb1text*)    /* .mb1text* sections (code) */

  *(.mb1rodata)   /* read-only data (constants) */

  *(.mb1rodata*)

 } >MEMORY_B1

  

 /* CCM-RAM section 

 * 

 * IMPORTANT NOTE! 

 * If variables placed in this section must be zero initialized,

 * the startup code needs to be modified to initialize this section.  

 * PH 12/5/2021

 */

 .ccmram :

 {

  . = ALIGN(4);

  _sccmram = .;    /* create a global symbol at ccmram start */

  *(.ccmram)

  *(.ccmram*)

   

  . = ALIGN(4);

  _eccmram = .;    /* create a global symbol at ccmram end */

 } >CCMRAM

 /* Remove information from the standard libraries */

 /DISCARD/ :

 {

  libc.a ( * )

  libm.a ( * )

  libgcc.a ( * )

 }

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

}

I followed the instructions here

https://www.openstm32.org/Using%2BCCM%2BMemory

Stepping through the code shows inbuf at an address of 0x20000000-something so obviously it is not working, plus the free RAM, currently ~3k, has not gone up

https://peter-ftp.co.uk/screenshots/202105120611622607.jpg

PHolt.1
Senior III

Found it, after a load more googling. The above site is wrong. One has to put the stuff before the variable name e.g.

#define CCMRAM __attribute__((section(".ccmram")))

CCMRAM uint8_t inbuf[PKT_BUF_LEN];

and sure enough I have gained 1k on the main RAM :)

https://peter-ftp.co.uk/screenshots/202105125111634607.jpg