STM32H7 problem after changing the linker script file in order to store data into DTCM RAM

1.2k views Asked by At

I am using STM32H755ZI MCU. This MCU has 1MB RAM which 512KB of it Can be directly accessed by M7 Core. I must store 45000 float samples the size of which will be around 180KB.

My first problem is that after storing around 12000 samples my program crashes.... when I store only 30000 samples, the program works correctly...

1- First question: What can be the reason?

I decided to store two arrays in RAM and store the third one in the DTCMRAM. the size of each array is around 60KB and the size of the DTCM RAM is 128KB. I was supposed to change the linker_script file.

This is how I defined the arrays:

as local variables into main function: float Data_Set_X[12000]={0}; float Data_Set_Y[12000]={0};

as a global variable: attribute((section(".dtcmram"))) float Data_Set_Z[12000];

Here is the Memory Map File MCU I used: enter image description here

Here is the default Linker Script:

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



The changed linker script file is presented as follows:
enter code here
    
    /*
    ******************************************************************************
    **
    ** 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_Heap_Size = 0x200 ;*/
    _Min_Stack_Size = 0x400 ; /* required amount of stack */      /* _Min_Stack_Size = 0x400 */
     
    
        /* Specify the memory areas */
        MEMORY
        {
        RAM_DTCM (rw)   : ORIGIN = 0x20000000, 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) }
    }

I checked the address of the DTCMRAM which starts from 0x20000000. now after these changes the performance of the program gets even worse and after storing 3640 samples into RAM the program stopped working.... it crashed.... Another thing that seems strange to me is that the build analyzer shows the ram amount for 128KB .... maybe if I find a way to increase it, that can solve my problem without using DTCM RAM... does anybody know about this issue? enter image description here

How should I change the linker script file to in order to use DTCM RAM? is there any other way using which I be able solve the mentioned problem which is storing 450000 samples?

I would appreciate and help or feedback regarding the mentioned issue. Thank you in advance.

1

There are 1 answers

0
Sylvain On

I have changed the linker file to include:

/* using RAM_D2 to hold ".myvarsRAM_D2" variables */

.myvarsRAM_D2 : { . = ALIGN(4); *(.myvarsRAM_D2) (.myvarsRAM_D2); } >RAM_D2

and defined the following macros in a .h file which I then use as prefix override:

#define MY_VARS_RAM_D2 attribute((section(".myvarsRAM_D2")))

in my code I use something like:

MY_VARS_RAM_D2 uint_8 VariableXXXX[10000]; // this will put the array in RAM_D2

You can do the same trick for all other RAM areas including DTCMRAM Good luck