2015-10-19 57 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. 在鏈接應用程序時爲引導加載程序提供目標文件。鏈接器命令行上的順序很重要,所以如果最後提供了這些命令,它們應該僅用於提供以前輸入尚未定義的任何功能。