2015-10-19 74 views
0

我想这是this问题的延续。 我编译了我的中间引导加载程序库,并验证了它的工作原理,现在是时候针对它编写一些应用程序代码。如何正确链接符号

我能够使用$(OBJCOPY) --wildcard --strip-symbol=main --strip-symbol="_*" $(TARGET).elf $(TARGET).syms从引导加载程序生成的.hex文件生成符号列表,这会给我bootloader.syms

我已经写了使用一些功能在存储库部分测试应用程序,我编译如下:

我通过GCC在引导加载程序使用的所有头文件的位置/库以及上面生成的符号文件。我已经测试过GCC按照预期来选择头文件。

Makefile文件调用:

Making: obj/main.o 
avr-gcc -Os -std=gnu99 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -static -DF_CPU=8000000UL -DBAUD= -iquote../firmware/src/ -I. -I../firmware/src/ -MP -MD -mmcu=atmega16 -c -o obj/main.o src/main.c; 
avr-gcc -Wl,-Map,app.map -Wl,--just-symbols=../firmware/bootloader.syms -T ld_script_app.x -mmcu=atmega16 obj/main.o -o app.elf 
obj/main.o: In function `main': 
main.c:(.text.startup.main+0x14): undefined reference to `lcd_init' 
main.c:(.text.startup.main+0x8e): undefined reference to `lcd_fill' 
main.c:(.text.startup.main+0x142): undefined reference to `gfx_draw_line' 
collect2: error: ld returned 1 exit status 
make: *** [app.elf] Error 1 

我不知道,虽然是什么导致了未定义的引用。我的印象是,他们会通过符号文件引用。

回答

1

我最近得到了一个两部分固件构建工作。看到这个问题和我自我回答我是如何做到这一点的:Building a two-part firmware image using GCC toolchain。 你在这里的问题有助于走上正确的轨道 - 谢谢! - 但需要采取相当多的步骤才能做到正确。

我的猜测是,你得到的未定义的引用是在引导加载程序源代码中的函数,但实际上并未在引导加载程序中使用。所以链接器将它们从完成的引导加载程序映像中删除。当您尝试链接您的应用程序时,它们不在main.obootloader.syms中,因此它们显示为未定义的引用。

如果是这样,有一些方法来解决这个问题:

  1. 尝试强制链接,即使他们不使用引导程序图像中保留这些符号。我认为有几种方法可以做到这一点。

  2. 移动这些函数来分离源文件并将它们构建到应用程序中。

  3. 在链接应用程序时为引导加载程序提供目标文件。链接器命令行上的顺序很重要,所以如果最后提供了这些命令,它们应该仅用于提供以前输入尚未定义的任何功能。