【问题标题】:PROGMEM variable discarded even if declared as (used)即使声明为(已使用),PROGMEM 变量也会被丢弃
【发布时间】:2017-02-08 14:37:16
【问题描述】:

我正在使用 ATMEL Studio 6.2 及其带有 avr-gcc (avr8-gnu-toolchain) 的工具链。我有一个变量需要放在 Flash (PROGMEM) 中,我将其声明为全局变量:

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

编译器不抱怨,链接器也不抱怨,但是当我打开 .lss 文件时,没有找到 gPrgLen。在 .map 文件中,我们可以看到它已被列在“丢弃的输入部分”下

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

它是作为发布版本构建的,但调试版本会给出相同的结果。 如何强制链接器将此变量包含在 *(.progmem*) 部分中?

编辑
添加了static,但结果仍然相同。

这是链接器部分:

# 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"

【问题讨论】:

  • 您是否在代码中的某处尝试过(void)PROGMEM; 这一行来强制使用该变量?如果它不起作用,那么你必须在链接器文件中强制它(你有链接器文件吗?)
  • 我已经尝试在程序中使用该变量,但它仍然没有链接。 ATMEL Studio 正在生成 make 文件,但我可以在项目属性中设置“免费”选项。
  • 你能贴出makefile的链接器部分吗?
  • 更新了 makefile 链接器部分。
  • 你在使用avr-g++吗?尝试将 extern "C" 放在定义 PROGMEM 变量的行的开头,以告诉编译器不要修改它的名称。

标签: c linker avr-gcc atmelstudio progmem


【解决方案1】:

奇怪的是__attribute__((used)) 不起作用。有两个建议可以尝试。

首先,将变量从static 更改为volatile(或添加volatile)。这可能会阻止它被优化掉。

如果这不起作用,您可以在链接器中添加一行以使其“[p]retend the symbol symbol is undefined, to force links of library modules to define it” (GCC Link Options)。这是通过-u symbol--undefined=symbol 完成的。

要将其添加到 Atmel Studio 项目文件,请转到工具链 -> AVR/GNU 链接器 -> 其他。然后在 Other Linker Flags 添加--undefined=gPrgLen

我已经使用它来将修订/编译时信息嵌入到 Hex 文件中,否则它不会被使用。这样我就可以从设备中检索内存并知道它是在什么条件下构建的(主要用于在原型设计和初始固件调试期间跟踪更改)。我的 main.c 文件有一个类似于 const char codeCompileDetails[] PROGMEM = "company_name-" __DATE__ "-" __TIME__; 的全局字符数组。再加上--undefined=codeCompileDetails,这些数据(这里包括编译代码的日期和时间)总是会进入可执行文件。

【讨论】:

    猜你喜欢
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 1970-01-01
    相关资源
    最近更新 更多