4

SAM4S 用に、セクター 0 に位置し、セクター 1 にアプリケーションをロードするブートローダーを作成しました。ただし、問題は、新しい関数にジャンプしようとすると、例外が生成されるように見えることです (デバッガーは Dummy_Handler() に移動します)。 .

ブートローダーには、マップに次のエントリが含まれています。

.application    0x00410000        0x0
                0x00410000                . = ALIGN (0x4)
                0x00410000                _sappl = .
                0x00410004                _sjump = (. + 0x4)

アプリケーション イメージ マップ ファイルには次のものが含まれます。

.vectors       0x00410000       0xd0 src/ASF/sam/utils/cmsis/sam4s/source/templates/gcc/startup_sam4s.o
                0x00410000                exception_table
…
.text.Reset_Handler
                0x0041569c      0x100 src/ASF/sam/utils/cmsis/sam4s/source/templates/gcc/startup_sam4s.o
                0x0041569c                Reset_Handler

例外テーブルは次のように定義されます。

const DeviceVectors exception_table = {

        /* Configure Initial Stack Pointer, using linker-generated symbols */
        .pvStack = (void*) (&_estack),

        .pfnReset_Handler      = (void*) Reset_Handler,

ブートローダーは、アプリケーションのジャンプ ポイントを次のように宣言します。

extern void (*_sjump) ();

そして、次の呼び出しを行います。

_sjump();

0x00410004 のメモリ コンテンツは 0x0041569d であり、これがワード アラインされていないことに気付きました。これは、Thumb 命令を使用しているからでしょうか? いずれにせよ、なぜ 0x0041569c ではないのでしょうか? またはもっと重要なのは、なぜこれが例外になるのですか?

ありがとう、

デヴァン

更新:これを 見つけましが、私にはうまくいかないようです:

void (*user_code_entry)(void);
unsigned *p; 
p = (uint32_t)&_sappl + 4;
user_code_entry = (void (*)(void))(*p - 1);

if(applGood && tempGood) {
    SCB->VTOR = &_sappl;

    PrintHex(p);
    PrintHex(*p);
    PrintHex(user_code_entry);

    user_code_entry();

}

コードは次のように出力されます: 00410004 0041569D 0041569C

更新の更新: C 関数ポインターでジャンプしようとしたコードは、次の逆アセンブリを生成しました:

--- D:\Zebra\PSPT_SAM4S\PSPT_SAM4S\SAM4S_PSPT\BOOTLOADER\Debug/.././BOOTLOADER.c 
user_code_entry(); 
004005BA ldr    r3, [r7, #4]     
004005BC blx    r3

次のアセンブリでこれを機能させることができました。

"mov   r1, r0        \n"
"ldr   r0, [r1, #4]  \n"
"ldr   sp, [r1]      \n"
"blx   r0"

これに基づいて、スタックのリセットが必要かどうか疑問に思います。もしそうなら、Cでそれを達成することは可能ですか?

4

2 に答える 2

3

SAM4Eでも同じ問題がありました。あなたの問題が何であるかを推測することはできませんが、私が抱えていた困難と私が使用した情報を指摘することができます.

私のブートローダは、ファームウェアのいくつかの部分を正しいメモリ位置に保存していませんでした。これにより、dummy_handler 例外が発生していました。アドレス計算のエラーを修正すると、ブートローダーは完全に機能しました。

私の提案:

  • ATMEL の例に従ってください。ドキュメントサンプル コードで十分です。main.c は、ブートローダーがどのように動作するかを理解するのに十分です。最初にパーティショニングの詳細に入る必要はありません。
  • RAM から関数/ISR を実行する方法をお読みください。
  • この Web ページでは、Intel HEX フォーマットについて説明します。
  • 最後に、ブートローダがアップグレードを完了したら、フラッシュを読み取ってホスト コンピュータに送り返すことができます。次に、元の画像と比較します (スクリプトを使用)。それがブートローダーのデバッグ方法です。

役立つかもしれない他のアイデア:

  • 書く前に各ページを消去しますか?
  • 消去/書き込みする前に、各メモリ空間のロックを解除しますか?
  • ブートローダーのセクションをロックして、誤って上書きしないようにすることができます
  • アップグレードされたファームウェアのセクションをロックできます。

指す必要があるアドレスは、0x00410004 ではなく 0x00410000 です。binary_execIntel Hex フォーマット (レコード タイプ 05) と組み合わせたAtmel のサンプル コード (関数を参照) は、この問題を解決するはずです。

この情報が少しでもお役に立てれば幸いです!

于 2015-02-13T18:34:18.683 に答える