以下で、コードおよびサンプル プロジェクトを参照する際に、SBL = flash_based_uart_sbl_with_lfu および LFU アプリケーション = lfu_uart_cpu1_application とします。
LFU に関連する詳細手順を以下に示します。
- SBL をブートし、アプリケーションを実行します:デバイス リセット時に、SBL 内で実行が開始されます。通信ペリフェラルが初期化され、アプリケーションのコードスタート ルーチンに分岐します。コードでは、これは SBL の main() 関数 (flash_based_uart_sbl.c) で行われます。
- LFU を開始します:ユーザーは、ホストで起動される LFU コマンドを使用し、ターゲット マイコン上で LFU を呼び出します。
- アプリケーションが LFU コマンドを受信します:アプリケーションは、自らの通信ペリフェラル ISR で LFU コマンドを受信します。コードでは、これは LFU アプリケーションの SBL_uartNotifyISR() (uart_led_blinky_cpu1.c) で行われます。この関数は、SBL にジャンプしてコマンドを処理するようアプリケーションに通知するためのフラグを設定します。
- LFU コマンドを処理します:アプリケーションは SBL に分岐し、LFU コマンドを解析して処理します。コードでは、これは SBL の commandJumpTable() 関数 (flash_based_uart_sbl.c) で行われます。この関数は、コマンドを読み取り、適切な動作を実行します。
- 新しいファームウェアをダウンロードしてフラッシュにプログラムします:SBL の LFU フローは、ホストからアプリケーションのイメージを受信し、そのイメージを非アクティブなフラッシュ バンクにプログラムします。古いファームウェアのバックグラウンド タスク機能の実行は停止していますが、アプリケーションに影響を及ぼさないよう、制御 ISR は引き続き利用可能です。コードでは、これは SBL の cpu1LFUFlow() 関数 (sbl_command_flow.c) で行われます。
- アプリケーションに戻り、成功を報告します:ファームウェア イメージが正常にプログラムされると、SBL はアプリケーションに分岐し、LFU コマンドが成功したことを報告します。
- LFU 切り替え関数を RAM にコピーします:アプリケーションは、実行可能ではない非アクティブなフラッシュにある新しいファームウェアの LFU 切り替え関数を RAM にコピーし、その関数に分岐します。古いファームウェアは新しいファームウェアの切り替え関数のコピーを実行するので、固定アドレスに配置する必要があります。コードでは、LFU アプリケーションの performLFUSwitchover() 関数 (lfu_switchover.c) で実行されます。
- 新しい PIPE ベクタ テーブルを初期化します:シャドウ PIPE ベクタ テーブルに新しいファームウェアの ISR が設定されます。コードでは、これは LFU アプリケーションの lfuSwapBanks() 関数 (lfu_switchover.c) で実行されます。
- 最適な LFU 切り替えポイントを待ちます:ソフトウェア フラグ付きの単純なステート マシンを使用して、制御 ISR の終了とアイドル時間の開始を判定します。これは、制御ループ割り込み間のアイドル時間を最大限に利用できるため、切り替えの実行に最適なタイミングです。コードでは、lfuSwapBanks 関数 (lfu_switchover.c) が、INT_myCPUTIMER0_ISR() ルーチン (uart_led_blinky_cpu1.c) の最後に設定される lfu_switchover_proceed フラグを読み取ることで、これを実現します。
- LFU 切り替えを実行します:
- 割り込みが無効化されます
- 割り込みテーブルがスワップされます
- アクティブと非アクティブのフラッシュ バンクがスワップされます
- スタック ポインタが再初期化されます
- 割り込みが再度有効になります
- 実行は新しいファームウェアの main() ルーチンに分岐します
コードでは、これは LFU アプリケーションの lfuSwapBanks() 関数 (lfu_switchover.c) のセクションで、タイムクリティカルな位相としてマークされています。
- 新しいファームウェアではデバイスの初期化がスキップされ、バックグラウンド制御ループが直ちに実行を開始します