Linker sector global variables addresing problem - c

I have already produced a work-around but I have a question about what is happening here.
Setup:
StmCUBEIDE (ver 10)
Stm32F4 on custom board with lan
8Mb extra SDRAM
1Mb FLASH on single boot mode
Default start from 0x08000000
Long story short I have sliced up my memory (flash) into sectors provided in linker. See linker below:
/*
*****************************************************************************
**
** File : LinkerScript.ld
**
** Abstract : Linker script for STM32F4xx Device with
** 1024Kbytes FLASH, 192Kbytes 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.
**
** (c)Copyright Ac6.
** You may use this file as-is or modify it according to the needs of your
** project. Distribution of this file (unmodified or modified) is not
** permitted. Ac6 permit registered System Workbench for MCU users the
** rights to distribute the assembled, compiled & linked contents of this
** file as part of an application binary file, provided that it is built
** using the System Workbench for MCU toolchain.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20030000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 128K; /* required amount of heap */
_Min_Stack_Size = 2K; /* required amount of stack */
/* Specify the memory areas
* reserved sector 0 (16kb sectors)
* flash (bootloader flash) sector 4 & 5 (64kb + 128kb = 192kb)
* sectore stable sector 6 to 8 ( 128 +128 +128 = 384kb)
* sector latest sector 9 to 11 ( 128 +128 +128 = 384kb)
*
*/
MEMORY
{
FLASH_RESERVED (rxw): ORIGIN = 0x08000000, LENGTH = 16K
FLASH_SX (rw) : ORIGIN = 0x08004000, LENGTH = 32K
FLASH_COMMON (rw) : ORIGIN = 0x0800C000, LENGTH = 16K
FLASH_BOOTLOADER (rx) : ORIGIN = 0x08010000, LENGTH = 192K
FLASH_STABLE (rxw) : ORIGIN = 0x08040000, LENGTH = 384K
FLASH_LATEST (rxw) : ORIGIN = 0x080A0000, LENGTH = 384K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K
EXRAM (rwx) : ORIGIN = 0xD0000000, LENGTH = 8192K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH_BOOTLOADER */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH_BOOTLOADER
/* keep this section for OTA capabilities*/
.otaComBuff 0x08000000:
{
KEEP(*(.otaComBuff))
} >FLASH_RESERVED = 0x00
/* The program code and other data goes into FLASH_BOOTLOADER */
.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 */
} >FLASH_BOOTLOADER
/* sectors for dual boot and reserved data */
.reserved :
{
. = ALIGN(4);
__reserved_start__ = .;
KEEP(*(.reserved*))
. = ALIGN(4);
__reserved_end__ = .;
} >FLASH_RESERVED
ASSERT(LENGTH(FLASH_RESERVED) >= (__reserved_end__ -__reserved_start__), "sector Reserved overflow")
.sx (NOLOAD):
{
. = ALIGN(4);
__sx_start__ = .;
KEEP(*(.sx*))
. = ALIGN(4);
__sx_end__ = .;
} >FLASH_SX
ASSERT(LENGTH(FLASH_SX) >= (__sx_end__ -__sx_start__), "sector sx overflow")
.common :
{
. = ALIGN(4);
__common_start__ = .;
KEEP(*(.common*))
. = ALIGN(4);
__common_end__ = .;
} >FLASH_COMMON
ASSERT(LENGTH(FLASH_COMMON) >= (__common_end__ -__common_start__), "sector common overflow")
.bootloader :
{
. = ALIGN(4);
__bootloader_start__ = .;
KEEP(*(.bootloader*))
. = ALIGN(4);
__bootloader_end__ = .;
} >FLASH_BOOTLOADER
ASSERT(LENGTH(FLASH_BOOTLOADER) >= (__bootloader_end__ -__bootloader_start__), "sector bootloader overflow")
.stable :
{
. = ALIGN(4);
__stable_start__ = .;
KEEP(*(.stable*))
. = ALIGN(4);
__stable_end__ = .;
} >FLASH_STABLE
ASSERT(LENGTH(FLASH_STABLE) >= (__stable_end__ -__stable_start__), "sector stable overflow")
.latest :
{
. = ALIGN(4);
__latest_start__ = .;
KEEP(*(.latest*))
. = ALIGN(4);
__latest_end__ = .;
} >FLASH_LATEST
ASSERT(LENGTH(FLASH_LATEST) >= (__latest_end__ -__latest_start__), "sector latest overflow")
/* Constant data goes into FLASH_BOOTLOADER */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH_BOOTLOADER
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH_BOOTLOADER
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH_BOOTLOADER
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH_BOOTLOADER
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH_BOOTLOADER
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH_BOOTLOADER
/* 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_BOOTLOADER
/* 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
/* Uninitialized external data section */
. = ALIGN(4);
.extbss (NOLOAD):
{
/* This is used by the startup in order to initialize the .bss secion */
_extsbss = .; /* define a global symbol at bss start */
__extbss_start__ = _extsbss;
*(.extbss)
*(.extbss*)
*(COMMON)
. = ALIGN(4);
_extebss = .; /* define a global symbol at bss end */
__extbss_end__ = _extebss;
} >EXRAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
PROVIDE ( _max_heap = . );
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Next I have in my file:
#include "stm32f4xx_hal.h"
#include "stdint.h"
#include "FreeRTOS.h"
#include "task.h"
#include "error.h"
#include "debug.h"
extern unsigned int __bootloader_start__ ;
extern unsigned int __bootloader_end__ ;
extern unsigned int __sx_start__ ;
extern unsigned int __sx_end__ ;
/*external linker symbols for sector address feching*/
extern unsigned int __stable_start__ ;
extern unsigned int __stable_end__ ;
extern unsigned int __latest_start__ ;
extern unsigned int __latest_end__ ;
/*external linker symbol OTA flash region*/
extern unsigned int __reserved_start__ ;
#define ADR_SectorBootloaderStart ((uint32_t)(&__bootloader_start__))
#define ADR_SectorBootloaderEnd ((uint32_t)(&__bootloader_end_))
#define ADR_SectorSxStart ((uint32_t)(&__sx_start__))
#define ADR_SectorSxEnd ((uint32_t)(&__sx_end__))
#define ADR_SectorStableStart ((uint32_t)(&__stable_start__))
#define ADR_SectorStableEnd ((uint32_t)(&__stable_end__))
#define ADR_SectorLatestStart ((uint32_t)(&__latest_start__))
#define ADR_SectorLatestoEnd ((uint32_t)(&__latest_end__))
/*OTA communiaction sector*/
#define ADR_Reserved ((uint32_t)(&__reserved_start__))
Problem is that only ADR_SectorSxStart returns true address in other variables I get garbage.
On this variables depends flashing logic, for long time function for guarding bootloader sector was not working, after hardcoding addresses into function everything is OK. I need to make the rest of defines work. Any idea why it is that only one variable refers correctly?
Thank you.
#busybee
Map file gets the wrong address too:
.sx 0x0000000008004000 0x0
0x0000000008004000 . = ALIGN (0x4)
0x0000000008004000 __sx_start__ = .
*(.sx*)
0x0000000008004000 . = ALIGN (0x4)
0x0000000008004000 __sx_end__ = .
0x0000000000000001 ASSERT ((LENGTH (FLASH_SX) >= (__sx_end__ - __sx_start__)), sector sx overflow)
.common 0x000000000800c000 0x0
0x000000000800c000 . = ALIGN (0x4)
0x000000000800c000 __common_start__ = .
*(.common*)
0x000000000800c000 . = ALIGN (0x4)
0x000000000800c000 __common_end__ = .
0x0000000000000001 ASSERT ((LENGTH (FLASH_COMMON) >= (__common_end__ - __common_start__)), sector common overflow)
.bootloader 0x0000000008030a54 0x0
0x0000000008030a54 . = ALIGN (0x4)
0x0000000008030a54 __bootloader_start__ = .
*(.bootloader*)
0x0000000008030a54 . = ALIGN (0x4)
0x0000000008030a54 __bootloader_end__ = .
0x0000000000000001 ASSERT ((LENGTH (FLASH_BOOTLOADER) >= (__bootloader_end__ - __bootloader_start__)), sector bootloader overflow)
.stable 0x0000000008040000 0x0

After some time, I have found the answer. As per usual it was in plain .text in front of my eyes.
The thing is that the address of SECTOR_BOOTLOADER is in fact placed correctly telling compiler where to place all .text variables.
When you go carefully line by line, you can see that I have actually created a memory region, FLASH_BOOTLOADER, and then used it as my main program address. This is correct. Then I have placed all my .text variables, using linker, then I created my REGION BOOTLOADER.
This is linker language means that in this region first he will place my variables, incrementing address and then he will place my sector, returning me address of sector not region.
This mistake was made by not understanding linker scripts and naming issue.

Related

STM32 Code getting stuck after changing FLASH start address in linker file

I am working with the stm32f413VGT (100 pin) controller on a custom hardware.
The project I am working on will be start by the bootloader. The bootloader is flashed at address 0x8000000.
My project should start from FLASH address 0x08040000 and I have changed the address in the linker file.
*.ld file
/*
******************************************************************************
**
** File : LinkerScript.ld
**
** Author : Auto-generated by System Workbench for STM32
**
** Abstract : Linker script for STM32F413VGTx series
** 1024Kbytes FLASH and 320Kbytes 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
**
** <h2><center>© COPYRIGHT(c) 2019 STMicroelectronics</center></h2>
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
** 1. Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
** 3. Neither the name of STMicroelectronics nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x2000; /* required amount of heap */
_Min_Stack_Size = 0x4000; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
FLASH (rx) : ORIGIN = 0x08040000, LENGTH = 1024K
}
/* 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) */
*(.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
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : {
. = ALIGN(4);
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
} >FLASH
.ARM : {
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
. = ALIGN(4);
} >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 (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* 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
/* 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) }
}
Do I need to do something else to change the start address?
The project worked fine with the default FLASH address 0x08000000 (without the bootloader), but it did not work after changes in linker file.
I have tried debugging the problem and the code is getting struck on HAL_delay() function. If I remove the delay, then it is getting stuck on the first printf() function it reached.

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

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

Running a software from a flash STM32F779II

I would like to run my firmware from the flash address :0x08040000
so I partitioned the memory layout for the software as shown:
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20080000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x1000; /* required amount of heap */
_Min_Stack_Size = 0x2000; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08040000, LENGTH = 768K
FLASH2 (r) : ORIGIN = 0x08100000, LENGTH = 1024K
SRAM1 (xrw) : ORIGIN = 0x20020000, LENGTH = 368K
SRAM2 (xrw) : ORIGIN = 0x2007C000, LENGTH = 16K
DTCMRAM (wal) : ORIGIN = 0x20000000, LENGTH = 128K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
}
main_stack_base = _estack;
/* used by the startup code to populate variables used by the C code */
data_lma = LOADADDR(.data);
data_vma = ADDR(.data);
data_size = SIZEOF(.data);
/* used by the startup code to wipe memory */
ccmram_start = ORIGIN(SRAM1);
ccmram_end = ORIGIN(SRAM1) + 4;
/* used by the startup code to wipe memory */
sram_start = ORIGIN(SRAM1);
sram_end = ORIGIN(SRAM1) + LENGTH(SRAM1);
_ram_start = sram_start;
_ram_end = sram_end;
_codelen = LENGTH(FLASH);
_flash_start = ORIGIN(FLASH);
_flash_end = ORIGIN(FLASH) + LENGTH(FLASH);
_heap_start = ADDR(.heap);
_heap_end = ADDR(.heap) + SIZEOF(.heap);
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
.flash2 : ALIGN(512) {
build/firmware_rnc/frozen_mpy.o(.rodata*);
build/firmware_rnc/vendor/secp256k1-zkp/src/secp256k1.o(.rodata*);
. = ALIGN(512);
} >FLASH2 AT>FLASH2
/* The program code and other data goes into FLASH */
.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 */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH2 AT>FLASH2
.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 (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* 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 */
} >SRAM1 AT> FLASH
_sidtcmram = LOADADDR(.dtcmram);
/* DTCMRAM section
*
* IMPORTANT NOTE!
* If initialized variables will be placed in this section,
* the startup code needs to be modified to copy the init-values.
*/
.dtcmram :
{
. = ALIGN(4);
_sdtcmram = .; /* create a global symbol at dtcmram start */
*(.dtcmram)
*(.dtcmram*)
. = ALIGN(4);
_edtcmram = .; /* create a global symbol at dtcmram end */
} >DTCMRAM AT> FLASH
_sisram2 = LOADADDR(.sram2);
/* SRAM2 section
*
* IMPORTANT NOTE!
* If initialized variables will be placed in this section,
* the startup code needs to be modified to copy the init-values.
*/
.sram2 :
{
. = ALIGN(4);
_ssram2 = .; /* create a global symbol at sram2 start */
*(.sram2)
*(.sram2*)
. = ALIGN(4);
_esram2 = .; /* create a global symbol at sram2 end */
} >SRAM2 AT> FLASH
/* 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;
} >SRAM1
.heap : ALIGN(4) {
. = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */
. = ABSOLUTE(sram_end - 16K); /* this explicitly sets the end of the heap effectively giving the stack at most 16K */
} >SRAM1
.stack : ALIGN(8) {
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
} >SRAM1
/* 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) }
}
My startup looks like this:
.syntax unified
.cpu cortex-m7
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
/**
* #brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* #param None
* #retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2], #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
/* Call the application's entry point.*/
bl main
bx lr
.size Reset_Handler, .-Reset_Handler
The problem is: The firmware doesn't enter the main function and it jumps somewhere in one of the .c files always doing that.
Where is the problem ?
The address of the reset vector is determined by the
logic level on the BOOT pin at reset
contents of the nDBANK and nDBOOT bits in the user option bytes
contents of the boot address option bytes
Verify that all of these contain the right values according to chapters 2.5 and and 3.4 of the reference manual.
If they still have their default values, and the BOOT pin is pulled low, the cpu will use the value at 0x08000004 with bit 0 cleared as the start address, and the value at 0x08000000 as the initial stack pointer. You can either copy the first 8 bytes from the start of the image to 0x08000000 in the flash, or set an alternate address in the option bytes.

Give the priority of the IRAM to a specific source file in C

I'm looking for a way to give the priority of the IRAM to a specific source file and let others source files by default.
From Keil uVision I was able to do it by going in the file options :
I migrated my project to Atollic TrueSTUDIO (generated with CubeMx) and there's no options like these. I found information about how to set where starts the RAM and its size in the linker script STM32F765NG_FLASH.id.
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
}
I imagine that there's maybe a way to modify this file to specify which .c file need the priority on the IRAM, but I don't know where and how to do it.
I also found __ attribute__ that I can use in the variable declaration. When I use it, it compiles, but it breaks some functionalities of the code (it probably override other data).
uint8_t __attribute__((section(".ARM.__at_0x20000000"))) RxSerialDMABuffer[RX_DMA_BUFFER_SIZE] = {0};
uint8_t __attribute__((section(".ARM.__at_0x20001000"))) TxDMABuffer[TX_DMA_BUFFER_SIZE] = {0};
So my question is, how can I set a particular source file to have the priority to use the IRAM before all my others files without the Keil uVision options?
EDIT : This is the complete linker script
/*
*****************************************************************************
**
** File : stm32_flash.ld
**
** Abstract : Linker script for STM32F765NG Device with
** 1024KByte FLASH, 512KByte 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
**
** Environment : Atollic TrueSTUDIO(R)
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
** (c)Copyright Atollic AB.
** You may use this file as-is or modify it according to the needs of your
** project. This file may only be built (assembled or compiled and linked)
** using the Atollic TrueSTUDIO(R) product. The use of this file together
** with other tools than Atollic TrueSTUDIO(R) is not permitted.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20080000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x00002200; /* required amount of heap */
_Min_Stack_Size = 0x00001200; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
}
/* 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) */
*(.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
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >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 (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* 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
/* 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(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
TrueSTUDIO uses the GNU toolchain, so the GNU linker documentation applies. Specifically in the case the part dealing with section placement.
Something like (note the following is a fragment; your real linker script will contain much more or may be organised differently):
MEMORY
{
...
IRAM1 (xrw) : ORIGIN = 0x20020000, LENGTH = 384K
IRAM2 (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
}
SECTIONS
{
DATA_IRAM1 :
{
* (.data)
} > IRAM1 AT > FLASH
BSS_IRAM1 :
{
* (.bss)
} > IRAM1
DATA_IRAM2 :
{
Buffers.o (.data) /* locate Buffers initialised data here */
* (.data)
} > IRAM2 AT > FLASH
BSS_IRAM2 :
{
Buffers.o (.bss) /* locate Buffers zero-int data here */
* (.bss)
} > IRAM2
}
The wild card * (.bss) allows any object module's BSS to be located in the specified section, while Buffers.o (.bss) makes location of Buffers.o BSS explicit. Similarly for .data.
If you took a look at the linker script generated by Keil, you will have seen that it is directly affected by the setting in the GUI dialog and will see similar directives - the ARM linker however uses slightly different syntax than GNU I think, but it may nonetheless help, to see how it organises the memory and location for your specific part - the fragment you have posted seems somewhat generic and does not separate the IRAM for example into its specialist sections such as TCM.
To give the priority of the RAM to my buffers, I loaded them in RAM first.
By going with the file name, the linker was reporting an error for multiple definitions. So I added a section attribute to my buffers like I did in my question, but by giving a section name instead of an address.
uint8_t RxSerialDMABuffer[RX_DMA_BUFFER_SIZE] __attribute__ ((section ("BUFFERS"))) = {0};
uint8_t TxDMABuffer[TX_DMA_BUFFER_SIZE] __attribute__ ((section ("BUFFERS"))) = {0};
After this, I added the new section in RAM before the other uninitialized data.
/* Uninitialized buffers section */
.BUFFERS :
{
* (.BUFFERS)
} >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
Then I went in the Linker Address Map file and I saw all my buffers with addresses corresponding to my IRAM2 address range, and all the other uninitialized data with the next addresses in IRAM2, then IRAM1.

GDB missing line numbers

I'm debugging an embedded system with the stm32f746vg microcontroller where some speed critical sections of code are loaded in data RAM instead of flash. The rest of the non-critical code is loaded in flash, and the linker puts all of the .text sections in flash by default.
I do this relocation with nasty little function prototypes like this:
int main(void) __attribute__((section(".data")));
This forces main() to be loaded at address 0x2000 0000, which is what I want. Unfortunately, GDB expects main() to be loaded at address 0x0080 0000, where the rest of the program code is. As a result, GDB does not know where the line numbers for main() are. Is there any way to tell GDB "main() is actually at this address" ?
I DO have the newest version of arm-none-eabi-gdb and arm-none-eabi-gcc.
I am running arm-none-eabi-gcc with the -g option.
When I comment out the prototype for main that contains the __attribute__ directive, GDB has no problem finding line numbers.
Below is my linker script:
/* Entry Point */
ENTRY(Reset_Handler)
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
/**
* for the time being, we are going to buffer the image in sram1. sram1 is
* entirely dedicated to buffering images.
* DTCM_RAM will be used for user variables
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
DTCM_SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
/* RAM1 (xrw) : ORIGIN = 0x20010000, LENGTH = 240K*/
RAM1 (xrw) : ORIGIN = 0x20010000, LENGTH = 245760
RAM2 (xrw) : ORIGIN = 0x2004c000, LENGTH = 16K
ITCM_SRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 16K
}
/* Define output sections */
SECTIONS
{
/* Vectors need to be loaded at the start of flash. */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.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 */
_exit = .;
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
/* used by the startup to initialize data */
_sidata = .;
/* Initialized data sections goes into RAM, load LMA copy after code */
.data ORIGIN(DTCM_SRAM) :
{
. = 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 */
} AT > FLASH
__const_data_length__ = SIZEOF(.data);
/* 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;
} >DTCM_SRAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >DTCM_SRAM
/* ram1 section, vars must be located here explicitly */
/* Example: extern int foo(void) __attribute__ ((section (".ram1"))); */
/* No initialization is offered for this section.*/
.ram1 ORIGIN(RAM1) :
{
*(.ram1)
} >RAM1
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
These are my gcc flags
CFLAGS = -gstabs -Wall -std=gnu99 -ffunction-sections -Wno-unused-variable
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mlong-calls
CFLAGS += -I. -ggdb
CFLAGS += -DHSE_VALUE=$(HSE_VALUE)
CFLAGS += -DUSE_STDPERIPH_DRIVER
You acheive this by placing main() in special code section of your choosing, call it .fast_exec
int main(void) __attribute__((section(".fast_exec")));
Then, in the linker script, place this new section to execute from RAM. It will be copied from FLASH at start-up:
.fast_exec : {
*(.fast_exec)
} > DTCM_SRAM AT> FLASH
You can verify the effect of this, by checking the map file.
Refer to: https://stackoverflow.com/a/15142268/1096140

Resources