我想这是this问题的延续。 我已经编译了我的中间启动加载程序库并验证了它的工作情况,现在是时候编写一些应用程序代码了。
我可以使用.hex
从引导加载程序生成的$(OBJCOPY) --wildcard --strip-symbol=main --strip-symbol="_*" $(TARGET).elf $(TARGET).syms
文件中生成符号列表,这样就可以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
我不确定导致未定义引用的原因。我的印象是它们将通过符号文件引用。
答案 0 :(得分:2)
我最近有两部分固件构建工作。看到这个问题和我自己的回答:Building a two-part firmware image using GCC toolchain。 您在这里的问题有助于走上正确的轨道 - 谢谢! - 但要完成正确的步骤需要很多步骤。
我的猜测是,您获得的未定义引用是针对引导加载程序源代码中的函数,但实际上并未在引导加载程序中使用。因此链接器将它们从完成的引导加载程序映像中删除。当您尝试关联自己的应用时,它们在main.o
或bootloader.syms
中都不可用,因此它们会显示为未定义的引用。
如果是这样,有几种方法可以解决这个问题:
尝试强制链接器将这些符号保留在引导加载程序映像中,即使它们未被使用。我认为有几种方法可以做到这一点。
将这些功能移至单独的源文件并将其构建到应用程序中。
在链接应用时提供引导加载程序的目标文件。对链接器命令行进行排序非常重要,因此如果最后提供这些命令行,则它们应仅用于提供尚未由先前输入定义的任何函数。