2024-10-15 01:06 AM
Hello,
I'm currently working on a project using the STM32L431CCTx microcontroller from the STM32L4 series. My goal is to retain specific variables in SRAM2 across MCU resets to maintain state and ensure data integrity using a CRC mechanism. However, I'm encountering an issue where these variables are being reset to zero every time the MCU undergoes a reset, despite verifying their placement in SRAM2.
Despite correctly placing the variables in SRAM2 and verifying their addresses, every time the MCU is reset, both myVariable and myCRC are reset to 0. Upon inspecting the startup code, I've identified that the variables in SRAM2 are being zeroed out during the FillZerobss routine.
I defined my variable in the main.c like this
/* USER CODE BEGIN PV */
volatile uint32_t my_var __attribute__((section(".ram2")));
/* USER CODE END PV */
As its seen in the picture my variable is stored in the sram2, and its value is 50 after, I click the reset button on the ide, it goes back to 0
Here is my linker script
/*
******************************************************************************
**
** @file : LinkerScript.ld
**
** @author : Auto-generated by STM32CubeIDE
**
** @brief : Linker script for STM32L431CCTx Device from STM32L4 series
** 256KBytes FLASH
** 64KBytes RAM
** 16KBytes RAM2
**
** 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) 2024 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/
/* 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 = 64K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K
RAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 16K
}
/* 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
/* 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 */
*(.RamFunc) /* .RamFunc sections */
*(.RamFunc*) /* .RamFunc* 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
.ram2 (NOLOAD):
{
_sram2 = .;
*(.ram2*)
. = ALIGN(4);
_eram2 = .;
} >RAM2
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
And here is the relevant part of startup script. which is generated by stm32cubeide
.syntax unified
.cpu cortex-m4
.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
.equ BootRAM, 0xF1E0F85F
/**
* @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 */
/* Call the clock system initialization function.*/
bl SystemInit
/* Copy the data segment initializers from flash to SRAM */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
/* Zero fill the bss segment. */
ldr r2, =_sbss
ldr r4, =_ebss
movs r3, #0
b LoopFillZerobss
FillZerobss:
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
cmp r2, r4
bcc FillZerobss
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
LoopForever:
b LoopForever
.size Reset_Handler, .-Reset_Handler
What am I doing wrong
Solved! Go to Solution.
2024-10-15 02:17 AM
You'll have to review the script and map file to understand why this is get encumbered into the regions startup.s has symbols for and initializes.
I'd probably hide the memory from the Linker entirely and use pointers and structures to access, preserve and manage data, be it NVRAM, BKPRAM or RAM2
2024-10-15 01:43 AM
Perhaps don't tell the Linker about the areas you want left alone.
Or mark them as NOLOAD
Or modify startup.s to not touch them.
Access via a pointer
2024-10-15 01:48 AM - edited 2024-10-15 02:00 AM
I have the NOLOAD on that are in my linker file,
.ram2 (NOLOAD):
I also tried adding this for test purpose, I added this to my linker
.no_init :
{
*(.no_init)
} > RAM
then created a variable in that section to store it in no-init. And that variable stayed the same between resets. But then I changed it to RAM2
.no_init :
{
*(.no_init)
} > RAM2
when I tried with this one it went back to zero at reset
2024-10-15 02:17 AM
You'll have to review the script and map file to understand why this is get encumbered into the regions startup.s has symbols for and initializes.
I'd probably hide the memory from the Linker entirely and use pointers and structures to access, preserve and manage data, be it NVRAM, BKPRAM or RAM2
2024-10-15 03:27 AM
@Tesla DeLorean wrote:I'd probably hide the memory from the Linker entirely and use pointers and structures to access, preserve and manage data, be it NVRAM, BKPRAM or RAM2
I tried it but the result is the same
2024-10-15 04:08 AM
@Tesla DeLorean wrote:You'll have to review the script and map file to understand why this is get encumbered into the regions startup.s has symbols for and initializes.
I updated my startup script to avoid zeroing the RAM2 region, and this successfully resolved the issue.
Thanks