2011-06-18 31 views
9

我在使用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中的「功能部分」)。

回答

3

看來問題可能在gcc 4.3.3及更高版本中得到解決,但我一直在使用4.3.2。我創建了一個不會執行的寵物示例,但演示了不同部分的使用以及由此產生的鏈接錯誤。它無法使用Codesourcery的arm-2008q3進行構建,但它確實使用arm-2009q1及更高版本進行構建。我需要更多時間來更新整個項目才能使用更新的gcc版本,所以我不能肯定地說這可以解決我的問題,但我強烈懷疑它的確存在。另外,我還有另一種解決方法,將所有基於ROM的函數分組爲-mthumb-calls - 構建的rom.c:通過函數指針調用所有內容。在這個解決辦法的情況下,治療比疾病更糟糕:

((void(*)(void*, void*, int))&memcpy+1)(&dest, &src, len); 

您需要+1以便優化不智取你,但它不是一個問題,在我的情況,因爲bx -ing到奇數地址表示拇指模式,我的所有代碼都是拇指。然而,我不相信有一種方法可以使通用宏來包裝所有這樣的函數調用,因爲每個指針都需要顯式強制轉換以匹配返回類型和參數列表 - 實際上,您最終會明確地重新聲明每個函數你想打電話,甚至是你不提供的庫函數。

3

我懷疑沒有辦法自動做你想做的事。我確實有一個建議,雖然它不完全是你想要的。

聲明RAM功能(在ram_funcs.h,說的)這樣的:

int foo() RAM_CALL; 

然後把你的所有ROM功能整合到他們自己的文件,並啓動每個這些文件是這樣的:

#define RAM_CALL __attribute__((__long_call__)) 
#include "ram_funcs.h" 

其他文件將使用:

#define RAM_CALL 
#include "ram_funcs.h" 

這不是比使用好得多,但至少它把邏輯放在函數本身附近,而不是在某些編譯選項中。例如,使每個.c文件中放入一些函數變得更容易。