I've a running C application on STM32G0,
it uses a bootloader but its size is almost 99.8% of all space available,
this is the configuration of Bootloader Memory:
//Bootloader OK Loader script:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 36K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 10K
BOOT_CFG (r) : ORIGIN = 0x8002800, LENGTH = 2K
OTP (r) : ORIGIN = 0x8003000, LENGTH = 2K
PROG (rx) : ORIGIN = 0x8003800, LENGTH = 114K
}
and this is the configuration of application memory:
//Application OK Loader script:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 36K
FLASH (rx) : ORIGIN = 0x8003800, LENGTH = 112K
INNER_REG (r) : ORIGIN = 0x801F800, LENGTH = 2K
}
I need more space for bootloader so I've created a different loader script for both:
//Bootloader NOT-OK Loader script:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 36K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 12K
BOOT_CFG (r) : ORIGIN = 0x8003000, LENGTH = 2K
OTP (r) : ORIGIN = 0x8003800, LENGTH = 2K
PROG (rx) : ORIGIN = 0x8004000, LENGTH = 110K
}
and this is the configuration of application memory:
//Application NOT-OK Loader script:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 36K
FLASH (rx) : ORIGIN = 0x8004000, LENGTH = 110K
INNER_REG (r) : ORIGIN = 0x801F800, LENGTH = 2K
}
The new bigger bootloader seems to be ok, and also the application starts without problem,
but after a while there's an exception somewhere and I can't understand the reason:
Any idea about how I can discover and solve the problem?
Following are the full loader for bigger space bootloader:
/**
******************************************************************************
* #file LinkerScript.ld
* #author Auto-generated by STM32CubeIDE
* #brief Linker script for STM32G070RBTx Device from STM32G0 series
* 128Kbytes FLASH
* 36Kbytes RAM
*
* Set heap size, stack size and stack location according
* to application requirements.
*
* Set memory bank area and size if external memory is used
******************************************************************************
* #attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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 = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200 ; /* required amount of heap */
_Min_Stack_Size = 0x400 ; /* required amount of stack */
/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 36K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 12K
BOOT_CFG (r) : ORIGIN = 0x8003000, LENGTH = 2K
OTP (r) : ORIGIN = 0x8003800, LENGTH = 2K
PROG (rx) : ORIGIN = 0x8004000, LENGTH = 110K
}
/* Sections */
SECTIONS
{
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data into "FLASH" Rom type memory */
.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 into "FLASH" Rom type memory */
.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 :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
} >FLASH
.init_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
} >FLASH
.fini_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/*CONFIG */
.config_block :
{
. = ALIGN(8);
PROVIDE(_bg_start = .);
KEEP(*(.boot_config))
PROVIDE(_bg_end = _bg_start + 0x800);
} >BOOT_CFG
/* OTP */
.otp_block :
{
PROVIDE(_sotp = .);
KEEP(*(.device_address))
PROVIDE(_eotp = .);
} >OTP
/* PROG */
.prog_block :
{
_sprog = .;
_eprog = _sprog + 0x1b800;
} >PROG
/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections into "RAM" Ram type memory */
.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 into "RAM" Ram type memory */
. = 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;
} >RAM
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
and the loader for the corresponding application:
/**
******************************************************************************
* #file LinkerScript.ld
* #author Auto-generated by STM32CubeIDE
* #brief Linker script for STM32G070KBTx Device from STM32G0 series
* 128Kbytes FLASH
* 36Kbytes RAM
*
* Set heap size, stack size and stack location according
* to application requirements.
*
* Set memory bank area and size if external memory is used
******************************************************************************
* #attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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 = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x1000; /* required amount of heap */
_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 36K
//OTP (r) : ORIGIN = 0x8003000, LENGTH = 2K
FLASH (rx) : ORIGIN = 0x8004000, LENGTH = 110K
INNER_REG (r) : ORIGIN = 0x801F800, LENGTH = 2K
}
/* Sections */
SECTIONS
{
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data into "FLASH" Rom type memory */
.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 into "FLASH" Rom type memory */
.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 :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
} >FLASH
.init_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
} >FLASH
.fini_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/* OTP */
/*.otp_block 0x8003000: */
/*{ */
/* . = ALIGN(4); */
/* _sotp = ABSOLUTE(.) ; */
/* KEEP(*(.device_address)) */
/* . = ALIGN(4); */
/* _eotp = ABSOLUTE(.) ; */
/*} */
_device_addres_pos = 0x8003800;
/* INNER_REG */
.registro_block (NOLOAD) :
{
_ri_start = ABSOLUTE(.) ;
. = ALIGN(8);
KEEP(*(.registro_interno))
. = ALIGN(8);
_ri_stop = ABSOLUTE(.) ;
} >INNER_REG
/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections into "RAM" Ram type memory */
.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 into "RAM" Ram type memory */
. = 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;
} >RAM
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
this is how I pass from bootloader to application:
void flash_jump_to_app(void)
{
/* Function pointer to the address of the user application. */
fnc_ptr jump_to_app;
jump_to_app = (fnc_ptr)(*(volatile uint32_t*) ((&_sprog)+1u));
/* Change the main stack pointer. */
__set_MSP(*((volatile uint32_t*)(&_sprog)));
jump_to_app();
}
whilst the startup file for the application is:
/**
******************************************************************************
* #file startup_stm32g070xx.s
* #author MCD Application Team
* #brief STM32G070xx devices vector table for SW4STM32 toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Branches to main in the C library (which eventually
* calls main()).
* After Reset the Cortex-M0+ processor is in Thread mode,
* priority is Privileged, and the Stack is set to Main.
******************************************************************************
* #attention
*
* Copyright (c) 2018 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
*
******************************************************************************
*/
.syntax unified
.cpu cortex-m0
.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
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr r0, =_estack
mov sp, r0 /* 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]
adds r2, r2, #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl app_main
LoopForever:
b LoopForever
.size Reset_Handler, .-Reset_Handler
/**
* #brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
*
* #param None
* #retval : None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M0. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word 0
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WWDG_IRQHandler /* Window WatchDog */
.word 0 /* reserved */
.word RTC_TAMP_IRQHandler /* RTC through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */
.word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */
.word EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */
.word 0 /* reserved */
.word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */
.word DMA1_Channel2_3_IRQHandler /* DMA1 Channel 2 and Channel 3 */
.word DMA1_Ch4_7_DMAMUX1_OVR_IRQHandler /* DMA1 Channel 4 to Channel 7, DMAMUX1 overrun */
.word ADC1_IRQHandler /* ADC1 */
.word TIM1_BRK_UP_TRG_COM_IRQHandler /* TIM1 Break, Update, Trigger and Commutation */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word 0 /* reserved */
.word TIM3_IRQHandler /* TIM3 */
.word TIM6_IRQHandler /* TIM6 */
.word TIM7_IRQHandler /* TIM7 */
.word TIM14_IRQHandler /* TIM14 */
.word TIM15_IRQHandler /* TIM15 */
.word TIM16_IRQHandler /* TIM16 */
.word TIM17_IRQHandler /* TIM17 */
.word I2C1_IRQHandler /* I2C1 */
.word I2C2_IRQHandler /* I2C2 */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_4_IRQHandler /* USART3, USART4 */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak RTC_TAMP_IRQHandler
.thumb_set RTC_TAMP_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_1_IRQHandler
.thumb_set EXTI0_1_IRQHandler,Default_Handler
.weak EXTI2_3_IRQHandler
.thumb_set EXTI2_3_IRQHandler,Default_Handler
.weak EXTI4_15_IRQHandler
.thumb_set EXTI4_15_IRQHandler,Default_Handler
.weak DMA1_Channel1_IRQHandler
.thumb_set DMA1_Channel1_IRQHandler,Default_Handler
.weak DMA1_Channel2_3_IRQHandler
.thumb_set DMA1_Channel2_3_IRQHandler,Default_Handler
.weak DMA1_Ch4_7_DMAMUX1_OVR_IRQHandler
.thumb_set DMA1_Ch4_7_DMAMUX1_OVR_IRQHandler,Default_Handler
.weak ADC1_IRQHandler
.thumb_set ADC1_IRQHandler,Default_Handler
.weak TIM1_BRK_UP_TRG_COM_IRQHandler
.thumb_set TIM1_BRK_UP_TRG_COM_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM6_IRQHandler
.thumb_set TIM6_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak TIM14_IRQHandler
.thumb_set TIM14_IRQHandler,Default_Handler
.weak TIM15_IRQHandler
.thumb_set TIM15_IRQHandler,Default_Handler
.weak TIM16_IRQHandler
.thumb_set TIM16_IRQHandler,Default_Handler
.weak TIM17_IRQHandler
.thumb_set TIM17_IRQHandler,Default_Handler
.weak I2C1_IRQHandler
.thumb_set I2C1_IRQHandler,Default_Handler
.weak I2C2_IRQHandler
.thumb_set I2C2_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_4_IRQHandler
.thumb_set USART3_4_IRQHandler,Default_Handler
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Related
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.
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.
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
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.
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