ARM STR7xxのローダースクリプト
-
03-07-2019 - |
質問
Eclipse + CDT + yagarto(gnuツールチェーン)+ OpenOCDを使用してARMをプログラムしようとしています。いくつかのサンプルプロジェクト(たとえばyagartoサイトから)で、多くのリンク情報が(セクション定義とともに)指定されたリンカースクリプト(* .ld)が見つかりました。実際、私は以前にこのファイルに直面したことはなく(IARはそれらを必要としません)、一目で理解するのが多少難しいと思います。したがって、私の質問は、すべてのプロジェクトでターゲットプロセッサ(STR710FZ2T6)にこのようなスクリプトファイルを1つ使用するか、このスクリプトの作成に慣れて各プロジェクトで作成する必要があるかということです。特定のターゲットプロセッサのすべてのプロジェクトに単一のファイルを使用できる場合、そのような普遍的なファイルを見つけることができる場所をアドバイスしてください。
解決
私の推測では、3人に1人は異なるスクリプトまたはソリューションを持っています。解決しなければならない多くの問題があり、異なるリンカーは異なる方法でそれらを解決しようとしています。 GNUは黒魔術ではないとしても難しい方法にしたと思います。
組み込みシステムの場合、多くの場合、フラッシュまたはeeprom、または他の形式の読み取り専用メモリから起動します。他のプロセッサと同様に、ARMには、リセットコードの場所や割り込みなどを伝えるベクターテーブルがあります。そのため、そのテーブルは特定の場所にある必要があり、その特定の場所に配置するようリンカーに指示する必要があります(最初) 。
使用したいスクリプトの1つは次のとおりです。
MEMORY
{
bob (RX) : ORIGIN = 0x0000000, LENGTH = 32K
joe (WAIL) : ORIGIN = 0x2000000, LENGTH = 256K
}
SECTIONS
{
JANE : { startup.o } >bob
}
私は通常、bobとjoeの代わりにramとromを名前として使用しますが、ここでは名前が何であるかは問題ではなく、単なるラベルであることを示しています。
テーマの別のバリエーション:
MEMORY
{
rom(RX) : ORIGIN = 0x00000000, LENGTH = 0x8000
ram(WAIL) : ORIGIN = 0x20000000, LENGTH = 0x2000
}
SECTIONS
{
.text : { *(.text*) } > rom
}
最初の方法では、リンカーコマンドラインにファイルを任意の順序で配置できますが、startup.oファイルにベクターテーブルが必要です。後者では、任意のファイル名を使用できますが、リンカースクリプトの最初のファイルにはベクターテーブルが必要です。
arm-thumb-elf-gcc -Wall $(COPS) vectors.o putget.o blinker2.c -T memmap -o blinker2.elf
またはldを直接使用
arm-thumb-elf-ld vectors.o putget.o blinker2.o -T memmap -o blinker2.elf
RXは、そのメモリセクションに読み込みと実行を行うようリンカーに指示します。WAILは基本的に他のすべてです。たとえば、ラムが1つしかない場合は、ラムの位置を示す行にすべてのフラグRXWAILを配置できます。その場合のローダーに応じて、開始するために分岐する場所をローダーに伝えるelfファイルに依存するか、単にエントリポイントをバイナリの先頭にすればローダーはより簡単になります。アーム(cortex-m3ではありません)には、リセットベクトルの最初のベクトルとして分岐命令があるため、RAMソリューション用にベクターテーブルを作成するふりをすることができ、動作します。
このソリューションには、私を悩ませることのない多くの問題があります。宣言中ではなく、コード内の変数を初期化します。
これ
int rx;
int main ( void )
{
rx = 7;
の代わりに
int rx=7;
int main ( void )
{
また、コードの開始時に変数がゼロであると想定することもありません。開始する前に常に何かに初期化します。スタートアップコードとリンカスクリプトをチームとして連携させることで、bssコードのリセットと非ゼロの初期化データをROMからRAMにブート時に簡単に自動化できます。 (そのint rx = 7;上記では、romのどこかから値7をコピーし、変数rxに割り当てられたramのメモリ位置に書き込むコードが必要なので、main()が開始するときに7がそこにあります。
このメソッドの結果、ブートコードも非常に簡単になりました。
.globl _start
_start:
b reset
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
hang : b hang
reset:
ldr sp,=0x10004000
bl main
b hang
スタックポインター、ヒープスペースなどをハードコーディングする必要がないように、スタートアップコードとリンカースクリプトが連携して動作することを可能にするソリューションについて確認または参照します。ここでも、複雑なスタートアップに多くの作業を投入できます。コードとリンカースクリプトを使用して、自動化を実現し、おそらく作業を節約します。自動化は、作業するとき/人的エラーを減らすことができますし、それは良いことです。また、チップを頻繁に切り替えたり、チップのファミリーで機能するコードを1ビット書いたりする場合にも、この自動化が必要になることがあります。
要点は「はい」です。ARMのすべての作業に対して1つのリンカースクリプトだけで生きることができます。ただし、そのスクリプトに合わせて作業を調整する必要があります。全員のサンプルコードで動作するスクリプトを1つ見つけることはないでしょう。スクリプトが複雑になるほど、借りるのが難しくなります。はい、上記のスクリプトはおそらくldコマンドラインで実行できますが、(gcc 2.95)動作させることができなかったため、上記の最小限のスクリプトを開発し、それ以来ずっと使用しています。何らかの理由で2番目のスクリプトを変更する必要がありましたが、4.x.xでは、確かに4.4.xでどちらかを使用できます。
他のヒント
ユニバーサルリンカースクリプトはありません。これらのスクリプトは、メモリ(RAMまたはROM)内のさまざまなデータおよびプログラムセクションを配置する場所を定義するため、非常に重要です。 IARコンパイラには何か同等のものがあります(正しく覚えていればxclファイル)。これまで、明らかにデフォルトのもののみを使用してきました。
「STR7xx Crossのオープンソースツールの使用」というSTR7xxに関する素晴らしいドキュメントがあります。 開発」。 yagartoホームページでリンクを見つけることができます。ご覧になり、リンカファイルがどのように機能するかを理解することをお勧めします。また、いくつかの理解が必要な他の構成ファイルもあります。