パッケージから取り出したばかりの、MKのブートローダーを使用するための通常のアルゴリズム:
- プログラマー/デバッガーを使用して、ブートローダーがフラッシュされます
- ボードに取り付けられたMK
- ブートローダーを使用して、メインファームウェアが事前定義されたインターフェイスにロードされます
これは、製品のプロトタイプや小規模な生産に非常に適しています。 また、大規模生産の場合はどうなりますか? または、組み立ては機械(または機械の機能を持つ人)によって行われますか? 次に、アルゴリズムから3番目のポイントを削除するのが合理的です-メインプログラムとブートローダーを1つのファームウェアに結合します。
私の練習では、このようなファームウェアを取得するかなり不気味な方法に出会いました-ブートローダーコードを含むHEXファイルは、メインファームウェアのHEXファイルに単純に追加されました。 もちろん。 このアプローチには、誰にでも言える権利がありますが、最終的な「別のフランケンシュタインの名前のファームウェア」は正常に機能しました。 しかし、この問題を解決するためのもっと正しい方法があるべきだという気持ちは、私を去りませんでした。
インターネットでソリューションを探したとき、そのソリューションの簡単で明確な説明がなかったことに不愉快な驚きを覚えました。 実際、これが、この状況に対する私の解決策を説明する出版物を書くきっかけになりました。 この問題を解決するという私のビジョンはおそらく最も正しいものとは異なりますが、HEXファイルをステッチするよりもはるかに論理的です。
出版のトピックに移る前に、使用された簡略化とツールのリストを提供したいと思います。
- MPLAB IDE v8.85(はい、非常に古いIDE)
- Microchip C30 Toolsuite v3.12
- COFF形式のオブジェクトファイル(つまり、このtoolchain-aのデフォルト)
- ブートローダーとメインプログラムの場所は静的です
- ローダーは0x400にあります
- メインプログラムは0x2000にあります
- 0x0200から0x0400のアドレスのメモリ-未使用
そして最も重要なことは、この出版物には特定のローダーのソースがないことです。
ブートローダーをメインプロジェクトにリンクする
コンパイルするだけ...
最も単純なケースから始めましょう。 良い祖父フロストは新年のために既製のローダーを送ってくれました。 そして、彼はすでに名声のために一生懸命働いて、あなたのためにそれをコンパイルしてコンパイルしました。 だから、あなたの手の中(USBフラッシュドライブ/ネットワーク/ハードドライブ)にファイルがあります-UltraBoot3000.blob。 アルゴリズムは非常に単純です-プロジェクトに追加するだけです。
MPLAB IDEに関しては、「オブジェクトファイル」カテゴリに追加する必要があります。 残念ながら、デフォルトでは、拡張子「o」を持つファイルのみがこのカテゴリに追加できます。 また、拡張子が「o」のファイルは、プログラムのコンパイル中にも取得されることに注意してください。 誤ってブートローダーファイルを混同して忘れないようにするために、別の拡張子、たとえばblob-バイナリリンクオブジェクトを使用することをお勧めします。 IDEがblobファイルを「オブジェクトファイル」カテゴリに配置するには、このカテゴリのフィルタ設定を調整する必要があります。 このカテゴリーを右クリックして、「フィルター...」項目を選択します。 表示されるウィンドウで、セミコロンを通るフィールドに、必要なフィルターテンプレートを追加します。 この場合、フィールドには次のフィルターの説明が含まれている必要があります。
*.o;*.blob
フィルターを構成した後、ブートローダーファイルをプロジェクトに追加できます。
compプロセスを開始します... NO! やめて!
ブートローダーでファームウェアを正しくアセンブルするには、正しいリンカースクリプトが必要です。 もちろん、Grandfather Frostがこのスクリプトを送信するほど親切な場合は、プロジェクトに追加するだけで(MPLAB IDEは「gld」拡張子のファイルをサポートします)、プロジェクトのビルドプロセスを開始し、組み込みコードで正しいファームウェアファイルを取得しますブートローダー。
しかし、祖父がこのスクリプトを忘れた場合、またはこのブートローダーを作成したのがあなたであり、それをあなた/他の人のプロジェクトに埋め込む必要がある場合はどうでしょうか? 続きを読む...
リンカースクリプトの準備
実際には、スクリプトを最初から作成しないでください。 コンパイラにバンドルされてインストールされているスクリプトをわずかにやり直すだけで十分です。 このスクリプトは、フォルダー「$ {ToolChainPath} \ support \ dsPIC33F \ gld \」にあります。 注:以下、$ {ToolChainPath}はC30コンパイラがインストールされたパスです。デフォルトでは、「c:\ Program Files \ Microchip \ MPLAB C30 \」です。 たとえば、dsPIC33FJ128GP802 MKなどのデバイスのデフォルトスクリプトをそこからコピーします。これは、ファイル「p33FJ128GP802.gld」になります。
最初のステップは、ブートローダー領域の開始とメインプログラムを説明する2文字を入力することです。 たとえば、次のように:
_Booter = 0x000400;
_mainFW = 0x002000;
次に、プログラムフィールドのMEMORY構造{...}で、ブートローダーの先頭に対応する初期位置(原点)と長さ(長さ)を指定し、フラッシュメモリのサイズからブートローダーの先頭を引いた値を指定します。 このようなもの:
program (xr) : ORIGIN = 0x400,LENGTH = (0x15800 - 0x400)
次のステップは、リセットベクトルを調整することです。 SECTIONS {...}の構造には、「命令のリセット」の説明があります。 次のように見えることが必要です。
.reset :
{
SHORT(ABSOLUTE(_Booter));
SHORT(0x04);
SHORT((ABSOLUTE(_Booter) >> 16) & 0x7F);
SHORT(0);
} >reset
ブートローダーゾーンの説明を追加するためだけに残ります。 ゾーンはSECTIONS {...}構造に記述されています。 この説明は、「。text」ゾーンの説明の前に挿入する必要があります。 説明は次のとおりです。
.boot _Booter :
{
*(.booter);
. = _mainFW - _Booter;
} >program = 0xFFFF
これでスクリプトの準備ができました。
ブートローダーの作成
プログラムからブートローダーを作成する
最初に注意したいのは、ブートローダーは独立したプログラムであってはならないということです。 もちろん、ブートローダーをデバッグするプロセスでは、スタンドアロンプログラムとして実装できます。 ただし、別のプログラムに統合する予定がある場合は、すぐに特別に準備する必要があります。
それで、プログラムが失うものは、ブートローダーに変わります:
- 構成ビットの説明
- 割り込みベクトル
- ベクターをリセット
さらに、フラッシュメモリに保存されているブートローダー定数をメインプログラムのコードに正しく埋め込むことはできません。 したがって、それらも放棄する必要があります。 注:実際には、方法がありますが、大量使用の場合はブートローダーの定数を拒否する方が簡単です。
ソースコードの改訂
改良は簡単です。 構成ビットを記述するすべてのマクロを削除します。 グローバル定数の使用は除外します。
プロジェクトのセットアップ
また、プロジェクト設定を確認し、必要に応じて調整する必要があります。 すべての変更は、タブ「MPLAB LINK30」、カテゴリ「一般」にあります。 チェックボックスを設定します。データテンプレートをパックしません。 ハンドルを作成しないでください。 デフォルトのISRを作成しないでください。 未使用のセクションを削除します。
リンカースクリプトの改良
ローダーを備えたメインプログラムと同様に、スクリプトはデフォルトのスクリプトとは異なります。 そのため、デフォルトのスクリプトを使用して、次の変更を行います。
MEMORY {...}の構造は、データとプログラムの2つの位置に縮小されます。 さらに、プログラムの先頭と長さは、ブートローダー領域の先頭と長さに対応しています。
{
data (a!xr) : ORIGIN = 0x800, LENGTH = 0x4000
program (xr) : ORIGIN = 0x400, LENGTH = 0x1C00
}
SECTIONS {...}構造の「Reset Instruction」の説明を完全に削除します。 同じ構造で、「構成ワード」の説明を削除します。 割り込みベクターを記述するSECTIONS {...}構造を完全に削除します(「割り込みベクターテーブルのセクションマップ」)。
SECTIONS {...}構造では、「。text」ゾーンの説明を改良し、ゾーンの名前を「.booter」に置き換えて、次の形式にします。
.booter 0x400 :
{
*(.init);
*(.user_init);
*(.handle);
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */
*(.lib*);
*(.dinit);
*(.text);
} >program
当然、結果のスクリプトをプロジェクトに追加する必要があります。
出力ファイルの後処理
前の手順の後、コンパイルプロセスを開始できます。 ビルドプロセスの出力(MPLAB IDEの場合は、[出力]ウィンドウの[ビルド]タブに表示されます)で、アセンブリの結果を確認できます。 たとえば、次のように:
Program Memory [Origin = 0x400, Length = 0x1c00]
section address length (PC units) length (bytes) (dec)
------- ------- ----------------- --------------------
.booter 0x400 0x7d0 0xbb8 (3000)
Total program memory used (bytes): 0xbb8 (3000) 27%
Data Memory [Origin = 0x800, Length = 0x4000]
section address alignment gaps total length (dec)
------- ------- -------------- -------------------
.nbss 0x800 0 0xa2c (2604)
bootdata 0x47c0 0 0x40 (64)
Total data memory used (bytes): 0xa6c (2668) 16%
プログラムメモリに複数のセクションがある場合、上記の手順を完全に完了していない可能性があります。 「.booter」という名前のセクションが1つだけあれば、すべてが正しく行われます。
また、データメモリ内のセクションの数にも注意を払う必要があります。
次に、出力ファイルを後処理する必要があります。 後処理は、拡張子が「cof」のファイルを使用して実行されます。 このファイルを含むフォルダー内のコマンドラインを開きます。 ファイルの名前がultraboot.cofであるとし、コマンドを実行します:
"${ToolChainPath}\bin\pic30-strip.exe" -s --remove-section=.nbss --remove-section=bootdata -o ultraboot.blob ultraboot.cof
$ {ToolChainPath}を実際のパスに置き換えることを忘れないでください。 オプションの数「--remove-section = ...」は、データメモリ内のセクション数に対応する必要があります(リンカの出力から)。
次に、結果のバイナリファイルの最終チェックをローダーで実行する必要があります。 チーム:
"${ToolChainPath}\bin\pic30-objdump.exe" -ht ultraboot.blob
出力は次のようになります。
ultraboot.blob: file format coff-pic30
Sections:
Idx Name Size VMA LMA File off Algn
0 .booter 000007d0 00000400 00000400 00000058 2**1
CONTENTS, ALLOC, LOAD, CODE
SYMBOL TABLE:
no symbols
「.booter」という名前のセクションが1つだけあり、シンボルテーブルにシンボルがないことがわかる場合、すべてが正しく行われていると想定できます。
そして、リンカのファイルの例へのリンクの最後に: