ベアメタル プログラミングに関する情報を探しています。私はさまざまな powerpc プラットフォームで作業しており、現在、一部のテストが Linux カーネルの影響を受けないことを証明しようとしています。これらのテストは非常に基本的なもので、asm volatile にロードおよびストアし、いくつかのベンチマーク (Coremark、Dhrystone など) も同様です。これらのテストは Linux で完全に実行されますが、実際には経験のない環境であるベアメタルでテストする必要があります。すべてのプラットフォームに u-boot がインストールされています。 powerpc-eabi cross-compiled テストを実行するには? たとえば、u-boot によって起動された gdbserver は、シリアル ポートまたはイーサネット経由で通信できますか? U-boot によって呼び出される busybox を持つことは可能ですか?
3 に答える
Uboot はブートローダーです...使用してください。おそらく、uboot を備えた xmodem ダウンローダまたは ymodem ダウンローダを持っています。プッシュが押し寄せてきた場合、プログラムをメモリへの長い一連の書き込みワードに変換してから、それに分岐することができます。
uboot はすでに RAM とシリアル ポートをセットアップしているので、とにかく uboot と話しているので、そのすべてを行う必要はありません。シリアル ポートを設定する必要はありませんが、送信レジスタが空になるようにステータス レジスタをポーリングし、送信レジスタに 1 文字を書き込むことを意味する文字の書き込み方法を見つける必要があります。文字列内のすべての文字または印刷するものについて繰り返します。
通常、C であると仮定した C プログラムへのブートストラップには、スタック ポインタの設定が最低限必要です (これは、uboot が実行されているため、スタックは既に設定されています。 uboot が行っていることと衝突しません)、C エントリ ポイントに分岐します。
高水準言語プログラム (私は C を想定しています) の書き方によっては、.bss 領域をゼロにして .data 領域をセットアップする必要がある場合があります。これは、ブートローダーを使用してプログラムを RAM にコピーし、通常、実行する必要はありません。ダウンロードして実行するバイナリには、bss がゼロになり、適切な場所に .data が既に含まれています。したがって、スタックを設定する必要さえない場合があるため、スタックとブランチをセットアップするか、単にブランチすることに戻ります。
ベア メタル プログラムの構築は、システム コールを作成するシステムがなく、あきらめたりシミュレートしたりするのが難しいため、実際の課題です。たとえば、newlib を使用すると、システム バックエンドを簡単に置き換えることができるため、作業が少し楽になります。たとえば、printfs を dhrystone に残しておくことができます (それらを削除して、必要に応じて文字列を出力したり、結果を出力する別の方法を見つけたりする必要はありません)。
C ファイルのオブジェクトへのコンパイルは簡単で、アセンブリのアセンブルも簡単で、powerpc-eabi gcc クロス コンパイラでそれを実行できるはずです。これは RAM のフラット チャンクである可能性が高いため、おそらく -Ttext 0x123450000 のようなことを行うことができます。この番号は、使用する RAM のベース アドレスです。乗算または除算、浮動小数点数、またはその他の gcc ライブラリ関数 (プロセッサが実行できるものとできないもの、またはそれらを適切に実行するためにラッパーが必要なものを置き換えるもの) がある場合、または libc 呼び出しがある場合は、それらをリンクしようとします。 . 理想的には、gcc ライブラリーのものは簡単ですが、クロス コンパイラーによっては難しい場合があります。最悪の場合、gcc ソースを使用してそれらの関数を自分でビルドします。
バイナリを逆アセンブルし、ブートストラップのエントリ ポイントがバイナリの先頭にないことを確認することを強くお勧めします。objcopy を使用して、バイナリ ファイル powerpc-...-objcopy myprog.elf -O バイナリ myprog.bin を作成します。次に、uboot プロンプトで xmodem または ymodem を使用して、そのプログラムをコピーして実行します。
バックアップ。パーツのデータシートから uart を検索してベース アドレスを特定するときは、最初に uboot プロンプトを使用して uart 送信レジスタのアドレスに書き込む必要があります。たとえば、そのアドレスに 0x30 を書き込みます。正しいアドレスがある場合は、次に、コマンドの後にubootプロンプトを再度出力する前に、出力に余分なゼロ「0」が含まれている必要があります。ubootコマンドラインからの1回の書き込みでそれを行うことができない場合は、アドレスが間違っているか、何か他のことをしているプログラムで動作することはありません.
次に、そのアドレスに書き込むことで uart に文字を出力するアセンブリ言語で非常に小さなプログラムを作成し、プロセッサの速度に応じて大きな数にカウントします。100Mhz で実行している場合は、1 億以上 (または数億から 0 までカウントダウン) までカウントし、最初に分岐して繰り返し、出力、待機出力、待機します。この小さなプログラムをビルドしてリンクし、xmodem などでダウンロードして分岐します。数秒ごとに文字を出力できない場合、より複雑なものに進むことはできません。
次の小さなプログラムでは、ステータス レジスタをポーリングし、tx バッファが空になるのを待ってから、tx レジスタに 0x30 を書き込みます。0x30 を保持するレジスタを 0x31 にインクリメントし、そのレジスタを 0x37 でインクリメントします。tx empty の待機に分岐し、新しい値 0x31 を出力し、これを無限ループにします。実行を開始すると、01234567012345670... が表示されない場合、数字が壊れることなく永遠に繰り返され、0-7 である必要があり、繰り返されると、より複雑なものに進むことができなくなります。
C エントリ ポイントに分岐する小さなブートストラップを使用して、C で最後の 2 つのプログラムを繰り返します。それらが機能しない場合は、それ以上先に進むことができません。
なしではできないと思われるライブラリ呼び出し (printf など) から始めて、単純な printf("Hello World\n"); を作成できない場合は、小さなものから始めます。すべてのリンクとシステム バックエンドなどを操作すると、Dhrystone を実行してそのシステム コールを終了することができなくなります。
コンパイラは、Dhrystone の一部を実装する必要がある memcpy または memset 呼び出しに変換する可能性が高く、これらの手作業で調整されたアセンブリ バージョンが存在する可能性が最も高く、Dhrystone のパフォーマンス数値は、これらのような関数の実装によって大きな影響を受ける可能性があり、今後も影響を受ける可能性があります。あなたは単にこれを行うことはできません
void memset ( unsigned char *d unsigned char c, unsigned int len)
{
while(len--) *(d++)=c;
}
あらゆるパフォーマンスを期待します。これらの gcc lib または gnu libc バージョンを取得するか、これらのテストの 1 つの Linux ビルドからそれらを盗む (逆アセンブルして asm を取得する) ことができます。
多くの場合、ベンチマークは実際よりも偽物です。同じ環境 (Linux またはベアメタルなど) で同じコンパイラを使用して同じベンチマーク ソースを取得し、さまざまな単純なことやさまざまなコンパイラ オプションを実行することで劇的に異なる結果を示すことは非常に簡単です。 、関数の再配置、ブートストラップへのいくつかの nops の追加など。さまざまなコードを作成したり、キャッシュを利用したり、キャッシュに傷ついたりするものなど。ベアメタルがオペレーティング システムよりも高速であることを示したい場合は、少しの作業なしでは実現しない可能性があります。i および d キャッシュを取得する必要があります。d キャッシュを取得するには、おそらく mmu を取得する必要があります。これらはすべて研究プロジェクトになる可能性があります。次に、コンパイラのビルドを制御する方法を知る必要があります。最適化がオンになっていることを確認してください。前述のように、ブートストラップで nops を追加または削除して、キャッシュ ラインに関してコード内のタイトなループの配置を変更します。オペレーティング システムでは、割り込みや処理が行われます。マルチタスクを実行している可能性があります。そのため、ベア メタルを使用すると、テストのような dhrystone を Linux と同じかそれ以上の速度で実行できるはずです。これは、ベア メタルの実装で適切なことを行っていないためです。
はい、おそらくgdbを使用してubootと通信し、プログラムをロードできます。gdbを使用したことがないかどうかはわかりません。ダム端末とxまたはyモデムを使用するか、openocd端末でjtagを使用することを好みます(gdbではなくopenocdにtelnetを使用します)。
このコミットのhttps://cirosantilli.com/linux-kernel-module-cheat/#dhrystoneで、QEMU と gem5 で実行される ARM 上の Newlib を使用して、最小限の実行可能な Dhrystone ベアメタルの例を提供しました。これを出発点として、PowerPC やその他の ISA、および実際のプラットフォームに移植することは難しくありません。
そのセットアップでは、Newlib は、 https ://electronics.stackexchange.com/questions/223929/c-standard-libraries-on-bare-metal/400077#400077 で説明されているように、syscalls 以外のすべてを実装します。 C 標準ライブラリのより大きなサブセット。
また、 crosstool-NGで構築されたツールチェーンを通じて newlib を使用しています。
そのセットアップのいくつかの重要なファイル:
- リンカー スクリプト
- システムコールの実装
使用されているフラグの一部を示す完全な make コマンド:
make \ -j 8 \ -C /home/ciro/bak/git/linux-kernel-module-cheat/submodules/dhrystone \ CC=/home/ciro/bak/git/linux-kernel-module-cheat/out/crosstool-ng/build/default/install/aarch64/bin/aarch64-unknown-elf-gcc \ 'CFLAGS_EXTRA=-nostartfiles -O0' \ 'LDFLAGS_EXTRA=-Wl,--section-start=.text=0x40000000 -T /home/ciro/bak/git/linux-kernel-module-cheat/baremetal/link.ld' \ 'EXTRA_OBJS=/home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/bootloader.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/lkmc.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/syscalls_asm.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/syscalls.o' \ OUT_DIR=/home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/submodules/dhrystone \ -B \ ;