cancel
Showing results for 
Search instead for 
Did you mean: 

Initialized variable at specific location optimized out?

RAltm
Senior

Hi,

I need to place a initialized variable at the beginning of RAM. This variable won't be read or modified by the application, it's only read by the ST-Link during programming operation.

So I modified the linker script by adding a section PRJINFO (project info):

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    KEEP(*(.PRJINFO*))  /* project information */
    . = 0x20;
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
 
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH

This area is 32 byte in size and the linker shouldn't throw away this section. I created a C file which contains a 32-byte array containing some information:

uint8_t ProjectProgramVersion[32] __attribute__((section(".PRJINFO"), used)) = {
		(PRJ_SW_VER >> 20) & 0xFF,
		(PRJ_SW_VER >> 28) & 0x0F,
		(PRJ_SW_VER >> 12) & 0xFF,
		(PRJ_SW_VER >> 8)  & 0x0F,
		(PRJ_SW_VER)       & 0xFF,
		(PRJ_SW_VER_INDEV) * 0x0E
};

This should place this array in the project info section, optimizing out should be prevented by linker (KEEP keyword) and compiler (attribute used). However, it only works in the debug build. Linking the release build gives garbage when reading out the memory locations.

Any ideas what might go wrong?

Regards

13 REPLIES 13
Ozone
Lead

The usual way to prevent this is to declare such variables as volatile.

Not sure about TrueStudio, though.

RAltm
Senior

Hi Ozone,

also added volatile keyword, but it doesn't help. According to map file, the space is reserved in both builds. But it seems that in release build, the initialization fails.

Regards

What does the map file say ?

I don't quite understand the code anyway.

Since it is initialized data, it is kept in the Flash area (constants) anyway, and copied to RAM in the startup code.

Why not leaving it as "const", in the Flash area ?

RAltm
Senior

Hi Ozone,

this is an excerpt of map file from debug build:

 *(.PRJINFO*)
 .PRJINFO       0x20000000       0x20 Src\ProjectInfo.o
                0x20000000                ProjectProgramVersion
                0x00000020                . = 0x20

The release build shows nearly the same, except of that the path is temp directory of the user and the file name is something cryptic. But that's also true for other sections like .data, .rodata, etc. So I assume it's okay and caused by missing debug information/symbols.

Regarding leaving it as const in flash, it's because I want to use RDP level 1 and therefore only SRAM can be read by ST-Link, but not flash. I forgot the mention that, sorry.

Regards

Bob S
Principal

I'm not sure how the linker/startup code handles initialized RAM variables that are not in .data sections. Can you show more of the surrounding lines from the MAP file, including the start of the .data section that should also show the "load address".

Or... how about simply changing the start of RAM from 0x20000000 to 0x20000020, then at the start of main(), manually copy the data into 0x20000000?

S.Ma
Principal

I would not create a new segment in the linker file, I would just reduce the range to exclude the 32 bytes.

Then, I create a pointer which value will be the address of the 32 byte structure.

If you need intial values, just do a mem copy from a const to the pointed value.

That should work with any toolchain and avoid pragmas and macros.

If your pointer points wrongly to a non existant area, you'll get exception anyway... the HW will make sure.

Like i said 😊

Pavel A.
Evangelist III

Have you tried to actually reference this data from main() ?

-- pa

> Linking the release build gives garbage when reading out the memory locations.

What sort of garbage? Are you sure it's not compiled correctly, i.e. isn't the problem at the source side? Incorrectly defined macros or whatever is in those initializers?

If in mapfile you see the section allocated then the linker did not discard it. You may also try to have the compiler generated the "intermediate" assembler source and look at that.

JW