我在使用GCC 4.3的ARM7TDMI項目上工作,我有一些困難,告訴編譯器在某些情況下使用長時間調用,而不是其他情況。long_calls在裸機上的RAM和ROM部分ARM與gcc
構建過程中運行arm-eabi-gcc
產生重定位的ELF目標文件爲每個.c的源代碼文件(最相關的CFLAGS包括-Os -ffunction-sections -fdata-sections -mthumb -mthumb-interwork
),然後鏈接他們都爲ELF可執行文件(最相關的LDFLAGS包括-Wl,--gc-sections -Wl,-static -Wl,-n -nostdlib
,以及自定義鏈接腳本) 。然後ELF文件被轉換爲arm-eabi-objcopy -O binary
的原始可執行文件,並且在啓動時,自定義引導加載程序將其從ROM複製到RAM(包含代碼和數據的單個SRAM)。所以一切都從RAM執行,.rodata
存在於RAM中,並且一切都快速進行,引導後完全忽略ROM。
我現在正試圖改變這種情況,以便某些選定的RO數據和選擇函數的文本只能存在ROM中,並在運行時根據需要進行訪問。我修改了鏈接描述文件,以瞭解兩個新章節".flashdata"
和".flashtext"
,它們都應該放置在ROM中的固定地址處。我也在整個C代碼中散佈了__attribute__((__section__(".flashdata")))
和__attribute__((__section__(".flashtext"),__long_call__))
,並且我已經重新編譯構建過程,以便舊objcopy現在添加-R .flashdata -R .flashtext
,並且我爲每個這些部分都做了第二個objcopy,其中-j
,然後將兩個輸出文件,以便引導加載程序可以做正確的事情,ROM部分出現在預期的內存映射位置。
這一切工作正常 - 我可以printf的標記進入.flashdata
部分字符串,我可以從代碼運行的RAM(它知道使用的,因爲__long_call__
屬性的長調用調用.flashtext
功能旁__section__(".flashtext")
屬性)。基於ROM的功能可以愉快地短時間調用其他基於ROM的功能,並且可以返回到其基於RAM的調用方。
問題在於試圖從基於ROM的函數調用基於RAM的函數,該函數也必須是長時間調用。我不想在任何地方使用長時間通話,所以我不想在我的CFLAGS中使用-mLong_calls。如果我把所有的功能都集成到一個ROM中,我可以用-mlong-calls
構建一個文件,並且一切正常。但是,我強烈希望避免這種情況,並且將功能按照目的進行分組,只需在ROM中適當地添加一些標記即可。
順便說一下,這在gcc 3.4下是不夠的。使用-mlong-calls
讓編譯器思考正確的事情,但它不能貫徹,因爲它只願意與幫助者執行長跳轉_call_via_rX
......這些都住在RAM中,只能通過長時間訪問才能訪問。 This was fixed in the linker in gcc 4.0, but not backported to anything in the 3.x tree。
因爲我使用gcc 4.3,所以我現在可以回撥到RAM中,這真是太好了。如果我能以某種方式標記基於ROM的函數中的代碼來強制它使用長時間調用,那將會更好。有一個#pragma long_calls
,但它隻影響聲明,所以我可以使用它而不是__attribute__((__long_call__))
。遺憾的是,它不會奇蹟般地強制編譯器在其生效時遇到的所有函數調用都使用長調用。
組織上,將所有慢速運行的代碼分組到單個文件中,與上下文無關並與其他常規類別中的代碼分開,這是不正確的。請告訴我,我還沒有考慮過一個選項。爲什麼不是-ffunction-sections或代碼是在不同的部分(.text
與.flashtext
)自動修復我的問題?
順便說一句,當鏈接器發現編譯器使用了一個短暫的調用,但沒有足夠的空間來管理重定位時,出錯的是:relocation truncated to fit: R_ARM_THM_CALL against symbol
foo'.text.foo中定義的部分objs/foo.o (and the section
.text.foo is used instead of
.text because of
- CFLAGS中的「功能部分」)。