これは、どの Cortex-M パーツでも機能します...
次のようなアセンブラ関数を作成します。
__asm void boot_jump( uint32_t address )
{
LDR SP, [R0] ;Load new stack pointer address
LDR PC, [R0, #4] ;Load new program counter address
}
インライン アセンブラの構文はさまざまです。この例は Keil ARM-MDK / ARM RealView です。
次に、ブートローダーの最後に:
// Switch off core clock before switching vector table
SysTick->CTRL = 0 ;
// Switch off any other enabled interrupts too
...
// Switch vector table
SCB->VTOR = APPLICATION_START_ADDR ;
//Jump to start address
boot_jump( APPLICATION_START_ADDR ) ;
この場合の APPLICATION_START_ADDR は、リンクされたアプリケーション コードのベースまたはロケーション アドレス (この場合は 0x3200) であり、リンク マップに示されているエントリ ポイントではないことに注意してください。アプリケーション ベクタ テーブルはこのアドレスにあり、ベクタ テーブルの先頭には、アプリケーションの初期スタック ポインタ アドレスとプログラム カウンタ (実際のコード エントリ ポイント) が含まれます。
このboot_jump()
関数は、アプリケーションのベクタ テーブルからスタック ポインタとプログラム カウンタをロードし、フラッシュ メモリのベース (ブートローダのベクタ テーブル) からロードされるリセット時に何が起こるかをシミュレートします。
アプリケーション コードのリンカー設定の開始アドレスを、ブートローダーがイメージをコピーするアドレスと同じに設定しておく必要があることに注意してください。Keil デバッガーを使用している場合、ブートローダーが存在しないと (または、少なくとも手動で SP と PC を正しく設定するか、デバッガー スクリプトを使用しない限り)、デバッガーでアプリケーションを読み込んで実行することはできません。アプリケーション ベクトル アドレスではなく、ベクトル アドレスをリセットします。
ベクター テーブルを切り替える前に割り込みを無効にすることが重要です。そうしないと、アプリケーションが初期化される前に発生した割り込みがアプリケーションのハンドラーにベクターされ、準備ができていない可能性があります。
アプリケーションとブート コードの両方で使用するペリフェラルには注意してください。ペリフェラル レジスタがブート コードによって既に設定されている場合、リセット条件に関する仮定が成り立たない可能性があります。