FreeRTOSを用いたOTA機能の開発。AWS IoTでデバイス管理するなら実装すべし。
はじめに
システムゼウスのIoTプロジェクトに所属している九法です。
FreeRTOSを用いたOTAの実装内容について説明します。OTAはOver-The-Airの略で、ここではWi-Fi経由でクラウドからファームウェアをダウンロードして更新することを言います。FreeRTOSにはOTAを行うためのライブラリが用意されており、クラウド側のプログラム開発を一切しなくても、AWS IoT jobsを使ってAWSクラウドからファームウェアの更新を実行できます。OTAがあるからFreeRTOSを採用する、あるいはFreeRTOSを使うならOTAの実装は必須、と言えるようなものだと思います。
1. OTAシーケンスの解説
シーケンス図に沿ってOTAの処理を説明します。
1.1. OTAジョブの開始
デバイス停止中にOTAジョブが作成された場合、デバイス起動直後に行うジョブの要求への応答としてOTAジョブ情報が返却され、OTAジョブが開始されます。
デバイス稼働中にOTAジョブが作成された場合、即時でOTAジョブが開始されます。
デバイス側ではOTAライブラリに含まれるOTAAgentがOTAを制御します。
AWS IoTにてOTAジョブを作成する手順は下記サイトを参照してください
Microchip Technology「FreeRTOS Over-the-Air Updates」
Amazon Web Services「Running OTA over MQTT」
1.2. ファームウェアのダウンロード
ジョブを取得したら、まずデータブロック配信トピックをサブスクライブし、配信に備えます。
ファームウェアは複数のデータブロックに分けてMQTTのペイロードとしてAWS IoTから受信します。たとえばWFI32-IoT Boardに実装されているデフォルトのFreeRTOSでは1ブロックあたり1024Byteとして、1ブロックずつ受信します。
ダウンロードしたファームウェアをどこに保管するかはハードウェアに依存します。例えばWFI32-IoT BoardではMCU外部にフラッシュメモリがあり、一旦そこに受信したファームウェアを書き込みます。
ファームウェアは8ブロック単位で受信します。25ブロック受け取るごとに、AWS IoTに状況を報告します。ファームウェアの全ブロックを受け取ると、次のフェーズに進みます。
1.3. OTAAgentによる新しいファームウェアの署名検証
ファームウェアをフラッシュメモリに書き込み終えると、OTAAgentがファームウェアの署名検証を行います。署名はOTAジョブ開始時に受信したOTAジョブ情報に含まれています。この署名を署名検証鍵(公開鍵)で復号し、書き込まれたファームウェアから計算したハッシュと一致することを確認します。例えばWFI32-IoT Boardに実装されているFreeRTOSのOTAデモアプリケーションでは、この署名検証鍵はMCUで動作しているアプリケーションのソースコードに直書きされています。
署名検証が成功すると、ジョブステータスを「セルフテスト」に更新する通知をAWS IoTに送り、MCUを再起動します。ここでAWS IoTにジョブステータスを通知しておく理由は、再起動後にセルフテストをしてOTAの続きの処理を実行するためです。
1.4. ブートローダーによる新しいファームウェアの署名検証と起動
MCUが再起動されると、通常はブートローダーがファームウェアの署名検証を行います。署名は前項と異なりジョブ情報に含まれるものではなく、ファームウェアイメージのディスクリプタ領域のものが対象です。これはOTAの処理ではなく、MCUが行うセキュアブートの一貫です。例えばWFI32-IoT Boardではセキュアブートが行われます。
例えばWFI32-IoT Boardに実装されているFreeRTOSでは、この署名検証鍵はMCUで動作しているブートローダーのソースコードに直書きされています。
なおブートローダーはOTAの機構で更新できません。すなわちブートローダーに含まれる署名検証鍵もOTAでは更新できません。もし署名検証鍵の更新運用をしたい場合は、ブートローダーには配置せず、セキュアエレメントなどの記憶装置に配置することになります。
署名検証が成功したら、新しいファームウェアを起動します。
1.5. セルフテストとクラウドへの完了通知
新しいファームウェアが起動すると、AWS IoTにジョブを要求します。デバイスが再起動する前にジョブステータスを「セルフテスト」にしているため、AWS IoTはセルフテストを指示するOTAジョブを返します。まずファームウェアのバージョンが上がっていることを確認し、次にセルフテストを行います。セルフテストは開発者がテストしたい内容を記述しますが、何もしなくても構いません。セルフテストが成功したらジョブステータスを成功にする通知をAWS IoTに送り、一連のOTA処理は完了します。
2. OTA機構の説明
AWS IoTとのやり取りはMQTTトピックを介して行います。使用するMQTTトピックを下図に示します。
参考:ジョブのトピック, MQTT ベースのファイル配信のトピック
2.1. ジョブの取得 パターン1
オペレーターがAWS IoTコンソールからOTAジョブを作成すると、ジョブ通知トピックにジョブドキュメントが送信されます。デバイスはこれを受け取り、OTAジョブを開始します。
2.2. ジョブの取得 パターン2
もしデバイスが動作していなかった場合、次の起動時にAWS IoTに対してジョブを要求し、その応答でジョブを取得します。デバイスがジョブを取得するとOTAが始まります。
2.3. ファームウェアの受信
デバイスはファームウェアを受信したいとき、データブロック要求トピックにメッセージを送ります。AWS IoTがこれを受け取ると、要求ブロック数に応じてデータブロック配信トピックに複数のデータブロックを送ります。例えばWFI32-IoT Boardに実装されているFreeRTOSのOTAデモアプリケーションでは、8ブロックずつの送信を要求しています。
2.4. ジョブステータスの更新
デバイスはAWS IoTにジョブステータスを通知したいときにジョブステータス更新トピックにメッセージを送ります。OTAシーケンスでは次のステータスを送ります。
- 進行中
- セルフテスト前
- 完了
- 失敗 ※中断時のみ
ジョブステータスはAWS IoTコンソールから見ることができます。
3. スマートロックデモシステムのプログラム構成
GitHubに公開している弊社で開発したスマートロックでもシステムでもOTAを実装しています。ここではその実装の概要を説明します。
ソースコードは下記リンクにあります。
関数の呼び出し関係を下図に示します。青色のアプリケーションコードの部分が本デモシステムで追加開発した部分です。
3.1. OTAAgent
OTAAgentの実体は図の「OTAAgentTask」です。OTAAgentTaskでOTA_EventProcessingTask関数が呼ばれ、AWS IoTからのメッセージを解析し、次の処理を判断して実行します。
3.2. MQTT通信
OTAライブラリはMQTTライブラリとの依存性をなくすため、インターフェースとコールバックを経由してMQTT通信を行います。例えばAWS IoTからジョブ通知メッセージを受信したときは、vprvMqttJobCallBackが呼ばれ、OTA_SignalEvent関数を使ってOTAAgentに通知します。
3.3. OTAジョブイベント
OTAAgent内でファームウェア受信完了時やセルフテストなどのイベントが発生すると、vprvOtaAppCallback関数が呼ばれます。スマートロックでもシステムではセルフテストの中身はありませんが、もしセルフテストを実装する場合はここに記述します。
おわりに
本記事ではOTAシーケンスとMQTTトピック構成、スマートロックデモシステムのプログラム構成を説明しました。これからFreeRTOSを用いてOTAを実装する皆さんの助けになれば幸いです。FreeRTOSのOTAライブラリおよびAWS IoT jobsを使用することで、フルスクラッチで開発するよりはかなり省力的にOTA機能を実装できるので、活用しない手はありません。
参考
免責事項
作者または著作権者は、契約行為、不法行為、またはそれ以外であろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用またはその他の扱いによって生じる一切の請求、損害、その他の義務について何らの責任も負わないものとします。
Discussion