PROGMEM variable discarded even if declared as (used)

551 Views Asked by At

I'm using ATMEL Studio 6.2 and its toolchain with avr-gcc (avr8-gnu-toolchain). I have a variable that needs to be placed in flash (PROGMEM) and I declare it as a global:

static const uint16_t gPrgLen PROGMEM __attribute__((used)) = 0;

The compiler doesn't complain and the linker doesn't complain, but when I open the .lss file, there is no gPrgLen to be found. In the .map file we can see that it has been listed under "discarded input sections"

Discarded input sections
.progmem.data.gPrgLen    0x00000000    0x2    Boot.o

It is built as a release, but a debug build gives the same result. How can I force the linker to include this variable in the *(.progmem*) section?

EDIT
Added static but still the same result.

Here is the linker part:

# All Target
all: $(OUTPUT_FILE_PATH) $(ADDITIONAL_DEPENDENCIES)

$(OUTPUT_FILE_PATH): $(OBJS) $(USER_OBJS) $(OUTPUT_FILE_DEP) $(LIB_DEP)
@echo Building target: $@
@echo Invoking: AVR/GNU Linker : 4.8.1
$(QUOTE)C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE) -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS) -Wl,-Map="Boot.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -Wl,-section-start=.text=0xf800  -mmcu=at90usb647  
@echo Finished building target: $@
"C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures  "Boot.elf" "Boot.hex"
"C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "Boot.elf" "Boot.eep" || exit 0
"C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "Boot.elf" > "Boot.lss"
"C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "Boot.elf" "Boot.srec"
"C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-size.exe" "Boot.elf"
1

There are 1 best solutions below

0
On

Odd that __attribute__((used)) isn't working. Two suggestions to try.

First, change the variable from static to volatile (or just add volatile). That may prevent it from being optimized away.

If that doesn't work, instead you can add a line to the linker to make it "[p]retend the symbol symbol is undefined, to force linking of library modules to define it" (GCC Link Options). This is done via -u symbol or --undefined=symbol.

To add it to the Atmel Studio project file, go to Toolchain -> AVR/GNU Linker -> Miscellaneous. Then in Other Linker Flags add --undefined=gPrgLen.

I've used this to embed revision/compile-time information into the Hex file where it wasn't otherwise used. That way I could retrieve the memory from a device and know under what conditions it was built (primarily for tracking changes during prototyping and initial firmware debugging). My main.c file had a global char array that looked something like const char codeCompileDetails[] PROGMEM = "company_name-" __DATE__ "-" __TIME__;. Coupled with --undefined=codeCompileDetails, that data (here including the date and time the code was compiled) always makes it into the executable.