2011-06-18 20 views
9

私はGCC 4.3を使用してARM7TDMIプロジェクトに取り組んでいますが、特定のケースで長い呼び出しを使用するようにコンパイラに指示するのは難しいです。gccのRAMとROMのセクション間のlong_calls

ビルドプロセスは、ELF実行ファイル(最も関連LDFLAGSは-Wl,--gc-sections -Wl,-static -Wl,-n -nostdlibが含まれ、カスタムリンカスクリプト)にそれらのすべてをリンクし、その後、(最も関連するCFLAGSは-Os -ffunction-sections -fdata-sections -mthumb -mthumb-interworkを含め)各.Cソースファイルの再配置可能ELFオブジェクトファイルを生成するarm-eabi-gccを実行します。その後、ELFファイルはarm-eabi-objcopy -O binaryでraw実行可能ファイルに変換され、起動時にカスタムブートローダがROMからRAM(コードとデータの両方を含む単一のSRAM)にコピーします。だから、すべてがRAMから実行され、.rodataがRAMに存在し、すべてが素早く進み、起動後にROMを完全に無視します。

これを変更しようとしています。特定の選択されたROデータと選択機能のテキストは、ROMにのみ存在し、必要に応じて実行時にアクセスできます。私は、リンカースクリプトを変更して、2つの新しいセクション".flashdata"".flashtext"を知りました。どちらもROMの固定アドレスに置く必要があります。私はまた__attribute__((__section__(".flashdata")))__attribute__((__section__(".flashtext"),__long_call__))を適切にCコードに振りかけました。古いobjcopyには-R .flashdata -R .flashtextが追加されています。ブートローダーが適切な処理を実行できるように2つの出力ファイルがあり、ROMセクションは予想されるメモリマップされた場所に表示されます。

このすべてが正常に動作します - 私は.flashdataセクションにタグ付けされた文字列をprintfのできる、と私は__section__(".flashtext")属性の隣にあるため__long_call__属性の長い呼び出しを使用するために知っている(RAMの不足しているコードから.flashtext関数を呼び出すことができます)。そのROMベースの関数は、他のROMベースの関数を喜んでショートコールすることができ、RAMベースの呼び出し元に戻すことができます。

ROMベースの機能からRAMベースの機能にコールするときに問題が発生します。これは、長い呼び出しでなければなりません。私はどこでも長い呼び出しを使いたくないので、私はCFLAGSの中で-mlong_callsを望んでいません。私がすべての機能をROMに集めてrom.cにまとめると、そのファイルを-mlong-callsで構築することができます。しかし、私はそれを避け、機能を一般的に目的別にグループ化しておくことを強く望み、ROMから実行するのに適切な場所に少数のタグを付けるだけです。

なお、これはgcc3.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__))の代わりに使用できます。それは悲しいことに、魔法のように、コンパイル時に発生したすべての関数呼び出しに対して長い呼び出しを使用するよう強制しません。

組織的には、実行速度の遅いコードをすべてコンテキスト内で1つのファイルにグループ化し、一般カテゴリの他のコードから分離するのは正しいことではありません。私がまだ考えていない選択肢があると教えてください。なぜ、-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 -built rom.cにグループ化する代わりに、別の回避策があります。この回避策の場合、治療は病気よりも悪いです:

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

オプティマイザはあなたの裏をかくませんが、bxはANに-ingので、それが私の場合は問題ではないように、あなたは+1を必要とします奇数アドレスは親指モードを示し、私のコードはすべて親指です。しかし、私は、各ポインタが戻り値の型と引数リストに一致するように明示的にキャストする必要があるので、すべての関数呼び出しをラップする汎用マクロを作成する方法はないと考えています。あなたが提供していないライブラリ関数さえ呼び出すことができます。

3

私はあなたが自動的にしたいことをする方法がないと思う。私は1つの提案がありますが、それはあなたが望むものではありません。

このような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ファイルにいくつかの関数を入れるほうが簡単になります。

関連する問題