コンテンツにスキップ

MCU ファームウェア更新

この文書は Orion の Main と CAN ノードの更新手順・実装を記録する。CM4 から送る走行コマンドの共通定義とは別に、更新プロトコル、Flash 配置、ノード構成、給電条件は機種ごとに確認する。Atlas の更新仕様は未記載である。

CM4 から、UART でつながった Main(STM32G474)を更新する。CAN 上の Sub、左右 BLDC、Power(STM32F303)は、Main をゲートウェイにして更新する。Main は A/B の 2 スロットを持ち、CAN ノードはアプリ領域が 1 つだけである。転送したデータと書込み結果は CRC32C で確認する。

対象とノード

対象 CM4 側ツール 経路 CAN バス / node ID
Main cm4/firmware/main_ab_updater.py UART(Main の bootloader と OFW1 で通信) —
Sub cm4/firmware/sub_can_updater_v2.py UART(OFW2)→ Main ゲートウェイ → CAN CAN1 / 4
右 BLDC 同上 同上 CAN1 / 16
左 BLDC 同上 同上 CAN2 / 17
Power 同上 同上 100(ツールの指定は CAN1。ゲートウェイは安全停止のときに応答があったバスへ切り替える)
バージョン確認 cm4/firmware/fw_version_reader.py UART(FWVR) 全ノード
  • sub_can_updater_v2.py は 1 回の更新で CAN1 と CAN2 のノードを 1 つずつ選べる(--node-can1 既定 4、--node-can2 既定 0xFF = 使わない)。左右の BLDC には同じイメージを両バスへ並列に送れる。
  • ノード番号とバスは、実機の配線に合わせて指定する。

更新順序

  1. 対象、イメージ、給電状態を確認する。通常のUART利用を止め、更新ツールだけが通信を使う。
  2. Sub と BLDC のイメージを更新し、確定する。
  3. Power を安全停止してから更新する。Power は Sub と BLDC への給電を制御しているので、この順序を守る。
  4. Main の稼働していないスロットを更新する。Main は CAN 更新のゲートウェイなので最後にする。
  5. fw_version_reader.py で全対象の build ID と CRC32C を確認し、Main の稼働スロットが CONFIRMED であることを確認する。
  6. 通常運用へ戻し、制御通信と必要な周辺機能を確認する。

all_can_updater.py は Power→Sub→BLDC の順にすべての対象を bootloader へ移してから転送する。Power を先に bootloader へ移すと Sub と BLDC への給電が切れるので、この給電構成では全ノードの一括更新に使わない。更新中の通信エラーや、再起動後の不一致は成功として扱わない。対象と状態を確認してから再開する。

CM4側の操作手順

ツールの導入、サービスの停止・復帰、実行コマンドはOrion_CM4のFW更新手順を参照する。この文書は更新順序・プロトコル・機器間の条件を定義する。

仕組み

更新モードへの切り替え

Orion の CM4 は通常の CM4→Main パケット の byte 1..4 に FWUP を入れ、byte 5 のコマンドで Main に指示する。以下は Orion の UART 更新の仕様で、Atlas の SPI による更新手順は未記載である。

byte 5 動作
1 CAN 更新ゲートウェイを開始する
2 ゲートウェイ動作中に、指定した CAN フレームを CAN1 へ送る
3 ゲートウェイを終了し、Main を再起動する
4 Main bootloader の UART 更新へ移る(Main 自身の更新)
5 Main bootloader で PENDING のスロットを CONFIRMED にする

4 と 5 では、現在の稼働スロットと要求を保存して再起動し、bootloader が受け取る。

Main の A/B 更新

main_ab_updater.py は、Main bootloader の OFW1 UART(12 バイトのヘッダ、chunk 896 バイト)で稼働していないスロットへ書き込む。書き終えたスロットは PENDING として起動し、CM4 が CONFIRM を送ると CONFIRMED になる。PENDING のスロットの起動が 3 回確定しなかった場合、bootloader はもう一方の CONFIRMED のスロットへ戻す。Flash 配置と起動判定は Orion ブートローダー を参照。

CAN ノードの更新(Main ゲートウェイ)

CAN上のIDとデータフレームはOrion CAN契約を参照する。

Main のアプリ内にある fw_update_gateway.c が、CM4 から受けた OFW2 フレームを CAN へ展開する。

  • UART フレーム:magic OFW2、version、type、sequence、length、ヘッダ CRC16、payload(最大 907 バイト)、CRC32C。同じ sequence を再び受けたら、前回の応答を返す。
  • ENTER で CAN1 と CAN2 に別々の node ID を指定できる。使わないバスは 0xFF。左右の BLDC には同じイメージを両バスへ並列に送り、応答はバスごとに確認する。status と確定 offset が両方で一致したときだけ成功とする。
  • 応答がタイムアウトしたら HELLO で確定 offset を問い合わせ、書込み済みの chunk を二重に書かない。
  • Power の更新前にキッカーを安全状態にし、Power の状態が安定したことを確認する。
  • ゲートウェイの動作中は、通常の走行制御、ブザー、テレメトリ送信を止める。

バージョン確認(FWVR)

Main の各スロットのイメージ先頭 +0x400 には、FWVR magic と Unix 秒の build ID が置かれる(CAN ノード側のファームウェアの配置は、この文書群では確認していない)。

  1. CM4 は共通の CM4→Main パケット の byte 1..4 に FWVR を入れて送る。
  2. Main は自身の両スロットを直接読み、対象とノード に示す CAN ノードへ照会する。Power への照会は両バスに送る。
  3. 応答のないノードにだけ 40 ms 間隔で再照会し、250 ms 後に 6 対象の build ID と image CRC32C を 60 バイトの応答にまとめて CM4 へ返す。

fw_version_reader.py は期待するバイナリを指定すると、実機の内容と比べた結果も表示する。Main のビルドスクリプトは、ビルドごとに Git hash と dirty 状態を Script/Logs/Build/ に JSON で保存する(Orion 概要)。