1

stm32 にフラッシュ メモリの領域を保存して、独自の構成情報を保存したいと考えています。

これを行うには、フラッシュ メモリの 2 番目のセクターを STM32F2/STM32F4 (0x08004000-0x08007FFF に格納された 16kb) に保存します。

インターネットとstackoverflowをチェックすると、これを行う4つの方法があります

1)

#pragma location=0x08004000 __no_init const char ReservedArea[16*1024];

2)

__no_init const char ReservedArea[16*1024] @0x08004000;

3) セクションの作成 + #pragma location=

プロジェクト ICF:

place at address mem: 0x08004000 { readonly section ConfigSection };

cファイル:

#pragma location="ConfigSection" __no_init const char ReservedArea[16*1024];

4)

プロジェクト .icf ファイルでセクションを定義するIAR がカスタム データのメモリ領域を定義する

バグまたは問題が見つかりました

方法 1 ~ 3で問題ありません。リンカーには、変数用のスペース領域が含まれています。16 進エディタで生成された .bin ファイルを確認するか、デバッグして、変数が @ 0x08004000 であることを確認できます。

これらの方法で見つかった問題は、iar リンカが 0x08000800 ~ 0x08003FFF の間の 12k バイトを超える未使用のフラッシュ メモリを残すことです。これを確認する最善の方法は、var を削除してコンパイルし、bin ファイルのサイズをメモに書き込んでから、変数を追加することです。これを行うと、新しい bin ファイルのサイズが正確に 16kb でなければならないときに、16kb を超えていることがわかります。

アドレスを 0x08004000 から 0x0800C000 に変更せずに移動すると、ファイル サイズがさらに 32k バイト増加し、以前の領域はすべて 0x00 に設定され、bin ファイルでは使用されません。これは私たちのプロジェクトにとって大きな問題です。bin ファイルの残りの未使用領域を使用してファームウェアの更新を可能にするからです。

マップ ファイルを確認すると、予約ゾーンの前のエリアも未使用であることがわかります。

これを修正する方法をいくつか試しましたが、うまくいきませんでした。たとえば、アドレスで 2 つの変数を定義する、何時間もプレイする、リンカ オプションをチェックする、最適化する、他の #pragma オプションを使用するなどです。

4番目の方法については、変数をシステムに保存しますが、必要なアドレスを取得できません。おそらく問題は、両方の領域がアドレス空間を共有していたことです。

icf ファイル

   define region LANGUAGE_region   = mem:[from 0x08004000 to 0x08007FFF];
   define region ROM_region      = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
   define region RAM_region      = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

   "LANGUAGE_PLACE":place at start of LANGUAGE_region  { section .LANGUAGE_PLACE.noinit };

cコード

extern const char ReservedArea[16*1024] @".LANGUAGE_PLACE.noinit";

const char ReservedArea[16*1024];

それは私の問題ですか?バグですか?どんなヒントでも大歓迎です。

前もって感謝します。

4

3 に答える 3

3

これは私にはバグのようには聞こえませんが、対処する必要がある問題です。.bin ファイルは、ファイルの各バイトがメモリ内のバイトにマップされる raw メモリ ファイルです。.bin ファイルが、オフセット 0x4000 または 0xC0000 にあるバイトを表し、その前にあるすべてのバイトを表すことを期待するにはどうすればよいでしょうか? .bin ファイルには、後続のセクションの相対オフセットを維持するために、2 つのメモリ セクション間のすべての未使用バイトを含める必要があります。

未使用のバイトが 0x00 であるため、最初に消去しないとプログラムできないという懸念はありますか? その場合、リンカ (または .bin ファイルの作成に使用しているプログラム) を構成して、未使用のすべてのバイトに 0x00 の代わりに 0xFF を使用することができます。リンカ (またはコマンド ライン) オプションを確認してください。

または、.bin ファイルに大量の未使用メモリが含まれているため、ダウンロードと再プログラムに時間がかかることが懸念されますか? それとも、.bin ファイルが大きすぎて、ファームウェアの更新用に予約したメモリ領域に収まりませんか? いずれの場合も、解決策は、ファームウェアの更新を 2 つの部分に分割することです。たとえば、最初の部分には、0x08000000 で始まり、コードが終了する場所で終了するコードのみが含まれます。2 番目の部分には、0x08004000 から始まるデータが含まれます。分割された 2 つの .bin ファイルのサイズは、間に未使用のメモリをすべて含める必要がないため、結合された .bin ファイルよりもはるかに小さくなります。ファームウェアの更新ルーチンは、各部分を認識して適切なメモリ アドレスにプログラムできるほどスマートである必要があります。

個別の .bin ファイルを扱いたくない場合は、.bin ファイルではなく .hex ファイルをダウンロードすることを検討できます。.hex ファイルはメモリ バイトの 1 対 1 のマッピングではなく、未使用のメモリ領域をスキップできるコード化された情報が含まれています。ただし、組み込みファームウェアの更新ルーチンは、フラッシュをプログラムする前に hex ファイルをデコードできるほどスマートである必要があります。

于 2016-05-11T14:53:27.210 に答える
1

いくつかの定数を既知の FLASH アドレスに配置しようとしていますが、上記の方法を使用しても結果が得られません。プラグマの場所を試してみましたが、まったく結果が得られず、@ も使用しましたが、IAR はこれについて不平を言っています。保存したい変数はFWのバージョンなので、12バイトの値を持ち、このようにグローバル値として宣言します(意味したい関数の外にあるため、.cのすべての関数からアクセスできます):

#pragma location=0x00001FF0
__no_init const uint8_t version[12] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B};

次のような IAR ドキュメントも確認しました: Technical Note 27498

役立つ場合は IAR 6.5 を使用しています (一部のメソッドでは 6.70 以降が必要であることに気付いたためです!

編集:

さて、今では次のように動作します:

.icf ファイル内:

/* Now I have a read only section in the ROM address 0x00001FF4 */
"ROM":
place at address mem:0x00001FF4 { readonly section .version };

.c ソース ファイル内:

#pragma location=".version"
__root const uint8_t version[12] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B};

よろしくお願いします、

イヴァン

于 2016-07-20T07:12:48.240 に答える