チェックサムの計算と検証
この例では、0x8002~0x8FFFにあるROMメモリのチェックサムが計算されます。また、計算された2バイトチェックサムが0x8000に配置されます。
コマンドラインから
ielftoolを使用する場合、まず計算されたチェックサムにメモリの場所を割り当てる必要があります。注記
代わりにIDE(およびコマンドラインではない)
__checksum、__checksum_beginシンボルを使用する場合、および__checksum_endチェックサム計算時に.checksumセクションが自動的に割り当てられる場合、このステップは省略できます。2つの方法でメモリの場所を割り当てできます。
適切なサイズのグローバルC/C++またはアセンブラ定数シンボルを作成し、特定のセクション(この例では.
checksum)に配置するリンカオプション
--place_holderを使用するたとえば、シンボル
__checksumの2バイトスペースをセクション.checksumにアライメント4で割り当てるには、以下のように指定します。‑‑place_holder _ _checksum,2,.checksum,4
.checksumセクションは、必要と思われる場合に、アプリケーションにのみインクルードされます。アプリケーション自体でチェックサムが必要でない場合、リンカオプション--keep=__checksumか、リンカディレクティブkeepを使用して、セクションを強制的にインクルードします。代わりに、[プロジェクト]>[オプション]>[リンカ]>[入力]を選択し
__checksumを指定します。
.checksumセクションの配置を制御するには、リンカ設定ファイルを修正する必要があります。例えば、これを次に示します(ブロックCHECKSUMの扱いに注意してください)。define block CHECKSUM { ro section .checksum }; place in ROM_region { ro, first block CHECKSUM };注記
このステップを省略することは可能ですが、その場合は
.checksumセクションは他のリードオンリーのデータとともに自動的に配置されます。チェックサムの計算のために
ielftoolを設定する場合、いくつか検討すべき基本事項があります。チェックサムアルゴリズム
使用するチェックサムのアルゴリズムを選択します。この例ではCRC16アルゴリズムを使用します。
メモリ範囲
IDEを使用して、チェックサムを計算する1つのメモリ範囲を指定できます。コマンドラインから、範囲を指定できます。
フィルパターン
フィルパターンを指定します。不明な値を持つバイトに対して、通常は
0xFFまたは0x00です。フィルパターンはすべてのチェックサムの範囲で使用されます。
詳細については、チェックサム計算の概要を参照してください。
注意
DEから
ielftoolを実行するには、[プロジェクト]>[オプション]>[リンカ]>[チェックサム]を選択し、たとえば以下のように設定します。
一番簡単な場合は、以下のオプションを無視(またはデフォルト設定のまま)できます。補数、ビット順、語句内のバイトオーダを逆順にする、 およびチェックサム単位サイズ。
危険
コマンドラインから
ielftoolを実行するには、コマンドをたとえば以下のように指定します。ielftool ‑‑fill=0x00;0x8002–0x8FFF ‑‑checksum=__checksum:2,crc16;0x8002–0x8FFF sourceFile.out destinationFile.out注記
ielftoolでは、--strip リンカオプションを使用していないELFイメージが必要です。リンカオプションで--stripを使用している場合、それを削除し、代わりにielftoolの--stripオプションを使用します。チェックサムはプロジェクトをビルドする際に後から作成され、セクション
.checksum内の指定されたシンボル__checksum内に自動的に配置されます。1つではなく、複数範囲を指定できます。
注意
IDEを使用する場合には、次の手順を実行します。
[プロジェクト]>[オプション]>[リンカ]>[チェックサム]を選択し、未使用コードメモリを埋めるを選択解除します。
[プロジェクト]>[オプション]>[ビルドアクション]を選択し、ポストビルドコマンドラインのテキストフィールドで、必要なコマンドの残りと一緒に範囲を指定します。例:
$TOOLKIT_DIR$\bin\ielftool "$TARGET_PATH$" "$TARGET_PATH$" ‑‑fill 0x00;0x0-0x3FF;0x8002-0x8FFF ‑‑checksum=__checksum:2,crc16;0x0-0x3FF;0x8002-0x8FFF例えば、
output.outを出力ファイル名に置換します。
危険
コマンドラインを使用する場合には、次のように範囲を指定します。
ielftool
output.outoutput.out‑‑fill 0x00;0x0-0x3FF;0x8002-0x8FFF ‑‑checksum=__checksum:2,crc16;0x0-0x3FF;0x8002-0x8FFF例えば、
output.outを出力ファイル名に置換します。チェックサム計算の関数をソースコードに追加します。
ielftoolielftoolで計算されるチェックサムと同じアルゴリズムおよび設定が使用されるように注意してください。たとえば、crc16アルゴリズムの派生形で、メモリのフットプリントが小さいもの(より多くのメモリを使用する高速の派生形とは対照的に)の場合、以下のように記述します。unsigned short SmallCrc16(uint16_t sum, unsigned char *p, unsigned int len) { while (len‑‑) { int i; unsigned char byte = *(p++); for (i = 0; i < 8; ++i) { unsigned long oSum = sum; sum <<= 1; if (byte & 0x80) sum |= 1; if (oSum & 0x8000) sum ^= 0x1021; byte <<= 1; } } return sum; }このチェックサムアルゴリズムのソースコードは、製品インストールの
arm\src\linkerディレクトリにあります。チェックサムを計算して2つのチェックサムを比較し、チェックサムの値が一致しなければ適切に処置する関数への呼び出しがアプリケーションに含まれていることも確認してください。
以下のコードは、アプリケーションでどのようにチェックサムが計算されるか、また
ielftoolにより生成されたチェックサムと比較した場合の例を示します。/* The calculated checksum */ /* Linker generated symbols */ extern unsigned short const __checksum; extern int __checksum_begin; extern int __checksum_end; void TestChecksum() { unsigned short calc = 0; unsigned char zeros[2] = {0, 0}; /* Run the checksum algorithm */ calc = SmallCrc16(0, (unsigned char *) &__checksum_begin, ((unsigned char *) &__checksum_end - ((unsigned char *) &__checksum_begin)+1)); /* Fill the end of the byte sequence with zeros. */ calc = SmallCrc16(calc, zeros, 2); /* Test the checksum */ if (calc != __checksum) { printf("Incorrect checksum!\n"); abort(); /* Failure */ } /* Checksum is correct */ }
アプリケーションプロジェクトをビルドし、ダウンロードします。
ビルド時、
ielftoolがチェックサムを作成し、セクション.checksum内の指定されたシンボル__checksum内に配置します。[ダウンロードとデバッグ]を選択して、C-SPYデバッガを起動します。
実行時、
ielftoolのチェックサムと、アプリケーションが計算したチェックサムが同一であることが必要です。2つのチェックサムがお互いに異なっている場合、いくつかの理由が考えられます。チェックサム計算のトラブルシューティングを参照ください。