説明
CPU リセットが発生すると、アプリケーション コードがリセット ベクターのロケーションから実行開始します。アプリケーションの .data セクションには変更可能な初期化された変数が含まれています。アプリケーションが実行されるたびに、.data セクションの変数がアプリケーション コードの記述に合わせて変更されます。アプリケーションが .data の初期値に依存している場合、プロセッサがリセットされるたびにこのアプリケーションからの結果が予測不可能になります。
ソリューション
この問題はいろいろな形で現れますが、リセット後に malloc が NULL ポインターを返すというのが一例です。 これは malloc が .data セクション内の変数に依存しているために発生します。
この問題を解決するには、.data セクションのコピーをメモリに保存します。これは CPU がリセットされたときに .data セクションを初期化し直すために使用します。このコピーは変更されない場所であればメモリの任意の位置に保存できます。
方法 1
コピーが誤って変更されなようにするため、その保存位置としては不揮発性メモリが適切です。
次に示す手順は PowerPC プロセッサ用で、.data および .data1 セクションが連続していることが前提です。 - フラッシュから最終ディレクトリにデータをコピーするには 'copydata.c' に含まれている 'CopyData' 関数を使用します。詳細は、(ザイリンクス アプリケーション ノート XAPP642) を参照してください。
void copydata(void) { int *src_rom = (int *)XPAR_FLASH_MEM0_BASEADDR; // pointer src_rom gets the base address of flash int *dst_ram = &__data_start; // pointer dst_ram gets the value(address) of .data section int *end_ram = &__data1_end; // pointer end_ram gets the ending address of .data1 section while (dst_ram < end_ram) { // copy the data from ROM to RAM *dst_ram++ = *src_rom++; } return; } /* end of copy.c */
- $EDK/sw/lib/ppc405/src/xil-crt0.s を自分のプロジェクト ディレクトリにコピーします。
- xil-crt0.s ファイルの bl main の前に bl copydata を追加します。
/* Call __init */ bl __init /* copy data section */ bl copydata /* Let her rip */ bl main
- xil-crt0.s および copydata.c を EDK シェルでコンパイルします。
EDK_Shell> powerpc-eabi-gcc -c copydata.c -c xil-crt0.s
- -B./<path_to_copydata.o_and_xil-crt0.o_files>/ というコンパイル コマンドをソフトウェア アプリケーションに追加します。
- ソフトウェア アプリケーションをコンパイルします。
- ソフトウェア アプリケーションの ELF からのデータ セクションをバイナリ形式に抽出します。
powerpc-eabi-objcopy -O binary -j .data -j .data1 executable.elf flash.bin
- flashwriter を使用し flash.bin をフラッシュ デバイスにベース アドレスから開始して書き込みます。
CPU リセットを押すと、CopyData 関数が実行され、データ セクションがフラッシュから RAM に書き込まれます。
方法 2
方法 1 は、最終的なデザインがフラッシュにアクセスするときのオプションですが、アプリケーションをブロック RAM から実行し、フラッシュが不要な場合はこの 2 番目の方法がより適していることがあります。この 2 番目の方法は、main() 内でコピー データ ルーチンを使用したカスタム リンカー スクリプトを使用します。 このカスタム リンカー スクリプトはデータ セクションと同じサイズの .datacopy セクションを追加します。データ セクションのコピーは RAM にあります。次は通常の .data セクションとカスタムの .datacopy セクションです。
.data : { . .data : { . = ALIGN(4); __data_start = .; *(.data) *(.data.*) *(.gnu.linkonce.d.*) __data_end = .; } > ilmb_cntlr_dlmb_cntlr /* create a section */ .datacopy : { . = ALIGN(4); __datacopy = .; . += SIZEOF(.data); } > ilmb_cntlr_dlmb_cntlr
リンカー スクリプトで以前定義されていた変数を使用してセクションをある場所から別の場所にコピーする C コードは、次のとおりです。
#include "xparameters.h" #include "stdio.h" #include "xutil.h" //==================================================== volatile int i = 0xDEADBEEF; extern unsigned char __datacopy; extern unsigned char __data_start; extern unsigned char __data_end; int main (void) { unsigned char *dataCopyStart = &__datacopy; unsigned char *dataStart = &__data_start; unsigned char *dataEnd = &__data_end; if (i == 0xDEADBEEF) while(dataStart < dataEnd) *dataCopyStart++ = *dataStart++; else while(dataStart < dataEnd) *dataStart++ = *dataCopyStart++; print("-- Entering main() --\r\n"); i = 0; print("-- Exiting main() --\r\n"); return 0; }
アンサー レコード リファレンス
マスター アンサー レコード