ベアメタル環境のcortex-m3 CPUのプロジェクトに取り組んでいます。ソフトウェアのアップグレードが必要なため、CPU 上の実行可能イメージがフラッシュ メモリ内の 2 つのアドレスのいずれかにある可能性があり、これが問題を引き起こします。イメージの開始アドレスは、静的リンケージ中ではなく、ロード時にのみ認識されます。よくわかりませんが、これは動的ローディングとは言えませんが、私はこれについての専門家ではないので、ここで誤解される可能性があります。OS も動的ローダーもない場合に、ロード時にのみベース アドレスを指定できるように、イメージをコンパイルしてリンクする方法はありますか?
2 に答える
あなたのようなベアメタル組み込みシステムの場合、これはコードを位置独立コードとしても知られる再配置可能なコードとしてコンパイル/リンクすることによって達成されます。
これがどのように達成されるかはプロセッサの影響を受け、実際のアプローチは開発ツールセットによって実装されるため、クロス開発ツールのドキュメントを参照する必要があります。通常、コンパイラとリンカーのオプションのセット (リンカー コマンド スクリプトがある場合はそれを含む) が、レイアウト方法とそれらへのアクセスに使用されるレジスタを決定します。
MMU (CM3 ではなく、申し訳ありません) をサポートするプラットフォーム (プロセッサと OS) で作業している場合は、少し簡単になります。コードは物理メモリのどこにでも配置できますが、MMU を介してその論理アドレスを配置できます。スペースは異なる場合があります。したがって、リンク時にコードとデータのアドレスを固定することができ、ロード時にMMUを介して論理アドレス空間が設定され、プログラムは賢明ではありません。
この他の SO の質問 ( 「cortex-m3 に位置に依存しないコードをロードしようとしています」 ) も役立つ場合があります。
デバイスがリセットされたときに、2 つの可能な場所のどちらから実行を開始するかを決定する方法が必要です。ただし、通常、ベアメタル デバイスには、リセット時に実行される開始位置が 1 つしかありません (一部のコントローラーは、デバイスのピンのロジック レベルに基づいて 2 つまたはそれ以上のエントリ ポイントから選択できます)。
同様の要件があり、次のスキームを考え出しました。
- 小さなブートローダー プログラムが必要です。これは、リセット時に CPU の制御を取得するプログラムになるようにビルドおよびリンクされています。
- メイン プログラム イメージは、実際には 2 回 (可能な場所ごとに 1 回) ビルドされます。注: 2 つの可能な読み込み場所は固定されており、ブートローダーによって認識されます。
- プログラム イメージの先頭に小さなデータ構造があり、ブートローダにとって重要な情報がいくつか含まれています。その中には、プログラムのエントリ ポイント アドレスとプログラム イメージのチェックサムがあります。
ブートローダーは、固定された既知の場所を調べて、2 つの可能なイメージのチェックサムを計算します。
- 有効な画像が見つからない場合は、単純にループします (ウォッチドッグはデバイスをリセットしますが、それは実際には問題ではありません。有効なメイン プログラムがロードされるまでは時間がかかります)。
- 有効な画像が 1 つだけ見つかった場合、それがジャンプ先のエントリ ポイントです。
- 両方のイメージが有効であることがわかった場合は、データ構造内の他の情報を使用して、どちらを制御するかを決定します (バージョン情報、最新の既知の良好な状態、ポリシーが何であれ)。
これの鍵は、ブートローダーが単純で愚かでなければならないということです。簡単にアップグレードできるわけではないので、バグがないように十分に愚かである必要があります。
これで、イメージを実行していない場所にフラッシュすることで、実行中にデバイスをアップグレードできます (私たちが持っている Cortex-M3 デバイスではこれが許可されています。LPC1758 でこれが許可されていない場合は、RAM から実行する何かを実行する必要があります)。フラッシュ更新)。リセットすると、ブートローダーが新しくフラッシュされたイメージを取得します。
システムは、ブートローダーを実行して安定させるために少し前もって作業を行う必要がありますが、一度機能すると、更新は 100% 信頼できます (新しいフラッシュが完了しない場合、チェックサムを行うのは古いイメージだけなので、次のリセット時に実行されます - ブリックなし)。主な欠点 (これは大きな欠点です) は、フラッシュが 2 つの競合するイメージを保持できる必要があるため、メイン プログラム用のフラッシュ アドレス空間の半分を本質的に失うことです。