Skip to main content
Garnett.Robert
Senior III
September 24, 2024
Question

SMCubeIDE Live Expressions - Incorrect Data Framing (Weird)

  • September 24, 2024
  • 4 replies
  • 2875 views

Hi,

 

I have a functioning project that fully compiles with only three warnings, but when I debug it and examine C structures in the live expressions viewer the the data (GovTrimControl_P structure ) appears to be offset by 4 bytes, yet the memory browser shows the correct values and when the mouse hovers over a value that value is correct:

 

Snag_190db9f0.png

 

Snag_190ed747.png

Snag_191550df.png

 

The Build Analyser also reports the address of GovTrimControl_P  correctly

Snag_1918f31c.png

Compile Problem Output:

Snag_1916f2f6.png

The values for the GovTrimControl_P structure are set at bootup to:

 

 

 

/* Parameters (default storage) */
struct P_GovTrimControl_T_
{
 real32_T FreqSP; /* Variable: FreqSP */ 
 real32_T kD; /* Variable: kD */
 real32_T kI; /* Variable: kI */ 
 real32_T kN; /* Variable: kN */
 real32_T kP; /* Variable: kP */
};

typedef struct P_GovTrimControl_T_ P_GovTrimControl_T;

/* Block parameters (default storage) */
P_GovTrimControl_T GovTrimControl_P =
{
 /* Variable: FreqSP */
 50.0F,

 /* Variable: kD */
 2.0F,

 /* Variable: kI */
 20.0F,

 /* Variable: kN */
 2.0F,

 /* Variable: kP */
 30.0F
};

 

 

The problem also occurs with another constant array where the Live Expression viewer reports incorrect framing of the underlying data.

I am running STM32CubeIDE Version

Version: 1.16.1

Build: 22882_20240916_0822 (UTC)

 

On an STM32H750B-DK Discovery kit,

 

I have attached the Linker Script File, startup file and video in the hope this might shed some light on the issue. The video shows the Backup ram memory which has the GovTrimControl_P data copied into it. The data shows the correct framing in the browser, but not in the Live Expression viewer:

 

Snag_192b6556.png

The backup ram copy function and its use are shown below:

 

 

 

void backupRamStartup(uint16_t bypassBtnState,
uint32_t code,									uint32_t* ramCode,
void* ramAddr,
void* parameters,
uint16_t size)
{
	if((bypassBtnState == 1) || (*ramCode != code))
	{
		/* The user is setting the defaults or the backupRam is empty */
		*ramCode = code;
		memcpy(ramAddr, parameters, size);
		return;
	}
	/* The backup ram contents are used to set the parameters*/
	memcpy(&parameters, &ramAddr, size);
}

/* Useage */

backupRamStartup( 								 HAL_GPIO_ReadPin(PC13_PB_DEFAULT_SET_GPIO_Port, 
PC13_PB_DEFAULT_SET_Pin),
0xC0AD1234,
&backupRAMValidationCode,
&backupRam,
&GovTrimControl_P,
sizeof(GovTrimControl_P));

 

 

 

I have never seen this occur in any of my other similar projects with older versions of the IDE.

 

Has anyone else seen this problem

 

Kind Regards

Rob

 

 

 

 

/* LINKER SCRIPT */
/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1);	/* end of "RAM_D1" Ram type memory */

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

/* Memories definition */
MEMORY
{
 DTCM_STACK 	(xrw) : ORIGIN = 0x20000000, 		LENGTH = _Min_Heap_Size + _Min_Stack_Size
 DTCM_MISC	 		(xrw) : ORIGIN = 0x20002000, 		LENGTH = 120K
 ITCMRAM 		(xrw) : ORIGIN = 0x00000000, 		LENGTH = 64K
 RAM_D1 		(xrw) : ORIGIN = 0x24000000, 		LENGTH = 512K
 RAM_D2 		(xrw) : ORIGIN = 0x30000000, 		LENGTH = 288K
 RAM_D3 		(xrw) : ORIGIN = 0x38000000, 		LENGTH = 64K
 SDRAM_FB 		(xrw) : ORIGIN = 0xD0000000, 		LENGTH = 765K
 SDRAM_USER 		(xrw) : ORIGIN = 0xD0000000 + 765K, LENGTH = 8M - 765K
 FLASH	 		(xr) : ORIGIN = 0x90000000, 		LENGTH = 2048K
 ASSETS_FLASH 		(r) : ORIGIN = 0x90200000, 		LENGTH = 126M
 BOOTLOADER 		(xrw) : ORIGIN = 0x08000000, 		LENGTH = 128k
 VBAT_SRAM_CODE	(xrw) : ORIGIN = 0x38800000, 		LENGTH = 4
 VBAT_SRAM	 		(xrw) : ORIGIN = 0x38800000 + 4, 	LENGTH = 4K - 4
}

TARGET(binary) /* specify the file format of binary file */
INPUT (../../ExtMem_Boot/bootloader.bin) /* bootloader bin file path (relative to the output folder)*/
OUTPUT_FORMAT(default) /* restore the out file format */

/* Sections */
SECTIONS
{
 .bootloader :
 {
 . = ALIGN(4);
 KEEP(../../ExtMem_Boot/bootloader.bin)
 } > BOOTLOADER

 /* The startup code into "FLASH" Rom type memory */
 .isr_vector :
 {
 __ICFEDIT_intvec_start__ = .;
 . = 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 (READONLY) : {
 . = ALIGN(4);
 *(.ARM.extab* .gnu.linkonce.armextab.*)
 . = ALIGN(4);
 } >FLASH

 .ARM (READONLY) : {
 . = ALIGN(4);
 __exidx_start = .;
 *(.ARM.exidx*)
 __exidx_end = .;
 . = ALIGN(4);
 } >FLASH

 .preinit_array (READONLY) :
 {
 . = ALIGN(4);
 PROVIDE_HIDDEN (__preinit_array_start = .);
 KEEP (*(.preinit_array*))
 PROVIDE_HIDDEN (__preinit_array_end = .);
 . = ALIGN(4);
 } >FLASH

 .init_array (READONLY) :
 {
 . = ALIGN(4);
 PROVIDE_HIDDEN (__init_array_start = .);
 KEEP (*(SORT(.init_array.*)))
 KEEP (*(.init_array*))
 PROVIDE_HIDDEN (__init_array_end = .);
 . = ALIGN(4);
 } >FLASH

 .fini_array (READONLY) :
 {
 . = 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_D1" 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_D1 AT> FLASH

 /* Uninitialized data section into "RAM_D1" 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_D1

 /* User_heap_stack section, used to check that there is enough "RAM_D1" Ram type memory left */
 ._user_heap_stack :
 {
 . = ALIGN(8);
 PROVIDE ( end = . );
 PROVIDE ( _end = . );
 . = . + _Min_Heap_Size;
 . = . + _Min_Stack_Size;
 . = ALIGN(8);
 } >DTCM_STACK


 .DTCM_MISC : {
 . = ALIGN(4);
 _sDTCM_MISC = .;
 __sDTCM_MISC__ = _sDTCM_MISC;
 *(.DTCM_MISC) /* All nominated variables */
 	. = ALIGN(4);
 _eDTCM_MISC = .;
 __eDTCM_MISC__ = _eDTCM_MISC;
 } >DTCM_MISC


 .VBAT_SRAM_CODE (NOLOAD) : {
 . = ALIGN(4);
 _sVBAT_SRAM_CODE = .;
 __sVBAT_SRAM_CODE__ = _sVBAT_SRAM_CODE;
 *(.VBAT_SRAM_CODE) /* All nominated variables */
 	. = ALIGN(4);
 _eVBAT_SRAM_CODE = .;
 __eVBAT_SRAM_CODE__ = _eVBAT_SRAM_CODE;
 } >VBAT_SRAM_CODE


 .VBAT_SRAM (NOLOAD) : {
 . = ALIGN(4);
 _sVBAT_SRAM = .;
 __sVBAT_SRAM__ = _sVBAT_SRAM;
 *(.VBAT_SRAM) /* All nominated variables */
 	. = ALIGN(4);
 _eVBAT_SRAM = .;
 __eVBAT_SRAM__ = _eVBAT_SRAM;
 } >VBAT_SRAM


 /* Remove information from the compiler libraries */
 /DISCARD/ :
 {
 libc.a ( * )
 libm.a ( * )
 libgcc.a ( * )
 }

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



 FontFlashSection :
 {
 *(FontFlashSection FontFlashSection.*)
 *(.gnu.linkonce.r.*)
 . = ALIGN(0x4);
 } >ASSETS_FLASH

 TextFlashSection :
 {
 *(TextFlashSection TextFlashSection.*)
 *(.gnu.linkonce.r.*)
 . = ALIGN(0x4);
 } >ASSETS_FLASH

 ExtFlashSection :
 {
 *(ExtFlashSection ExtFlashSection.*)
 *(.gnu.linkonce.r.*)
 . = ALIGN(0x4);
 } >ASSETS_FLASH

 BmpCacheSection (NOLOAD) : { *(BmpCacheSection) } >SDRAM_FB
 TouchGFX_Framebuffer (NOLOAD) : { *(TouchGFX_Framebuffer) } >SDRAM_FB
 TouchGFX_Framebuffer1 (NOLOAD) : { *(TouchGFX_Framebuffer1) } >SDRAM_FB
 TouchGFX_Framebuffer2 (NOLOAD) : { *(TouchGFX_Framebuffer2) } >SDRAM_FB
 Video_RGB_Buffer (NOLOAD) : { *(Video_RGB_Buffer) } >SDRAM_FB

}

/* Start-up code */

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

 

 

 

 

 

4 replies

Garnett.Robert
Senior III
September 24, 2024

Additional

 

I made a very small project with the same data structure as GovTrimControl_P and the mis-framing did not occur.

 

I then thought maybe the data appeared misaligned to the IDE which only happens with a big project so I added __attribute__((__aligned__(4))) to my variables and voila it is fixed.

 

backupRam_t __attribute__((__aligned__(4))) __attribute__((section (".VBAT_SRAM"))) backupRam;

And

P_GovTrimControl_T __attribute__((__aligned__(4))) GovTrimControl_P =
{
 /* Variable: FreqSP
 * Referenced by: '<S1>/Constant'
 */
 50.0F,...

 

Of course the data isn't misaligned as the data are floats, the IDE just thinks it is.

 

So there is a bug in the IDE, that only seems to appear in non-trivial projects.

 

Adding the alignment seems to work so All is Good.

 

 

Garnett.Robert
Senior III
September 25, 2024

The problem re-occured so it seems the attribute  aligned isn't the answer.

What a pain.

Karl Yamashita
Principal
September 28, 2024

I tried your data structure on a Nucleo-G431KB and didn't see any issues after several debugging tries. The Live Expression looked good.

 

I then grabbed a STM32H750B-DK and copied over the code from the G431.

On the first debug, the FreqSP showed 30. Somewhat similar to what you show. Unfortunately i didn't get screen grab of it.

 

I then added an attribute to align the data structure and debugged again. The data looked normal.

KarlYamashita_0-1727510757802.png

 

I removed the attribute and I tried debugging at least 15 times. I can't seem to produce the same issue. Maybe it was just a random one time fluke? 

 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Garnett.Robert
Senior III
October 2, 2024

Hi,

 

I think you are correct; it is a random bug.  I also noticed that on occasions live expressions reports booleans as numbers other than 0 or 1, this might be another peculiarity or just the same framing bug.

 

In any event although it is a nuisance as long as people are aware of it they can always check with the memory browser which is excellent as it can display the data in all the different data formats.

 

Kind Regards

Rob

Lead II
October 2, 2024

I've had this happen too. In my case setting a breakpoint, deleting the live expressions and adding them again fixed it.

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
Garnett.Robert
Senior III
January 8, 2025

This bug is a pain.

 

I found that you have to disconnect the target as well as deleting BP's and Live Expressions.

 

Every time I have to start a new debug session having to disconnect the target remove the BP's and redo the live expressions costs five minutes. Live expressions are a pretty fundamental to the debugging process they are not just a "nice to have"  Disconnects and reconnects wear out the connectors.

 

I spend more time "debugging" the IDE as I do working on my code.

Not happy.

Lead II
January 9, 2025

I've tried to see how I could programmatically (with scripts) load the live expressions since you can load startup scripts when starting a debug session. Apparently GDB supports watchpoints, but not live expressions (and even GDB watchpoints don't show up in the IDE). I think this is done using ST-link specific commands that the IDE sends. So tha


So I added live expressions and expressions to a project and saved it, then removed one and saved that. I compared the projects to see where the live expressions were stored. This didn't work. But making a backup of the workspace and comparing that after adding expressions and closing the IDE did reveal changes in the workspace folder.

Apparently live expressions are stored in this workspace file:

 

~\STM32CubeIDE\workspace_1.17.0\.metadata\.plugins\com.st.stm32cube.ide.mcu.livewatch\saved_expr.dat

 

In this file I found:

 

myVariable1
myVariable2

 

 

It is saved when closing the IDE. Closing the project does not update it. Maybe there is another way to save the workspace.

Apparently expressions are stored in this workspace file:

 

~\STM32CubeIDE\workspace_1.17.0\.metadata\.plugins\org.eclipse.core.runtime\.settings\org.eclipse.debug.core.prefs

 

At the bottom of this file I found:

 

prefWatchExpressions=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?>\r\n
<watchExpressions>\r\n 
<expression enabled\="true" text\="myVariable1"/>\r\n 
<expression enabled\="true" text\="myVariable2"/>\r\n 
\r\n
</watchExpressions>
\r\n

 

It is saved when closing the IDE. Closing the project does not update it. Maybe there is another way to save the workspace.

I was able to modify these files when the workspace was closed and it would load when the workspace was reopened. I haven't found a way to load them without restarting the workspace. Even on my fast PC the IDE takes quite a while to load.

Interestingly the breakpoints are stored elsewhere. They are stored in the workspace in a subfolder for each individual project. The expressions and live expressions are global for the entire workspace. This never make any sense to me. It always annoyed me that opening a project would load invalid expressions from a different unrelated project from the same workspace. It still doesn't make sense, but at least I now know how this happens. Poor design.

I added a breakpoint at line 150 and it showed up in this binary file:

 

~\STM32CubeIDE\workspace_1.17.0\.metadata\.plugins\org.eclipse.core.resources\.projects\MyProjectName\.markers

 

This is what I found:

 

lineNumber[some binary data]message[some binary data]#Line breakpoint: main.c [line: 150][some binary data]

 

I didn't bother trying to copy or modify these breakpoints as this is a binary file.

 

Please test if this works for you. I hope it helps.

 

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
Nadreoh
Associate II
January 8, 2026

Hi there,

My teammates also got that issue randomly with cubeIDE v1.16.1.
This bug is very random as we already had two laptop with the exact same code version and configuration with one getting this issue and not the other.

Today I got an issue with a memory offset of +8bits. Sometimes it is +32 bits...

Lead II
January 9, 2026

@Nadreoh wrote:

Today I got an issue with a memory offset of +8bits. Sometimes it is +32 bits...


?

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
Nadreoh
Associate II
January 9, 2026

I was using cubeIDE v1.16.1. and I got the same issue in the live expression where my variables are shown with a memory offset of +8bits (i.e. corrupted values).

A month ago I got the same issue with a memory offset of +32bits in the live watch only.

Sometimes the issue is persistent, sometimes it disappears. I did not find the root cause until now.