AI×IoTの普及に伴い、組み込みシステム(エッジデバイス)には多数の機能が統合されるようになりました。これにより、デバイスを設計・開発する組み込みエンジニアにも、複数のタスクを自在に制御する設計スキルが求められています。特に重要とされるスキルは、複数のタスクの中から次に実行するタスクを選出する「スケジューラー」の理解です。スケジューラーは、タスクの開始契機となったイベントを検知し、タスクの優先度に基づいて、どの順番でタスクを次に実行するかを決めます。タスクを選出するルールを「スケジューリング・ポリシー」と呼びます。スケジューラーの挙動はすべてのプログラムの実行に関わることから、エンジニアにとって不可欠な知識です。一方、その開発(設計/実装/検証)には大きなコストが発生します。
こうした課題に対して、タスクの制御機能を提供し、効率的なシステム開発を支援できるソフトウェア・プラットフォームが「リアルタイムOS(Real-Time Operation-System:RTOS)」です。もちろん、実際の製品開発にはスケジューラだけでなく、サービスを提供するアプリケーションをはじめ、ハードウェアを制御するための「デバイスドライバ」、プログラムを効率的に開発するための「ライブラリ」も必要です。
今回の初心者講座マルチコア編では、これまで紹介したSPRESENSEのアプリケーション開発から一歩踏み込んで、SPRESENSE SDKに同梱されているリアルタイムOS「NuttX」の特長を紹介します。
SPRESENSE対応のリアルタイムOS「NuttX」を使うには
SPRESENSEに対応したリアルタイムOS「NuttX」は、SPRESENSE向けのソフトウェア開発環境「SPRESENSE SDK」に同梱されています。Visual Studio CodeとSPRESENSE SDKを組み合わせた開発環境でアプリケーションを実装し、ビルドするだけで、NuttXを含む実行ファイルを生成可能です。実行ファイルに含まれるすべての機能は、NuttXにより制御されます。つまり、SPRESENSEを使ってシステム開発をするエンジニアは、特別な操作をすることなくNuttXをシステムに取り込み、NuttXの提供する様々な恩恵を受けることができます(後述)。さらに、SPRESENSE SDKでは「カーネルコンフィグ機能」を使って、NuttXをカスタマイズし、自身の設計するサービスに最適化することも可能です。
- スケジューリング機能
- ハードウェア抽象化機能
- 多数のデバイスドライバを同梱
- POSIX/ANSI準拠のAPIによる高い移植性
- 動作検証済のリアルタイムOSとサンプルアプリケーションのペアをすぐに評価可能
目次
はじめて学ぶ、リアルタイムOS
APSでは2019年よりSPRESENSEのセミナーを開催していますが、リアルタイムOS「NuttX」を紹介した後のタイミングで「リアルタイムOSを触ったことがない」「リアルタイムOSを導入したいが何から始めるべきか」「コスト的なメリットを会社に説明したい」といった、開発に向けた具体的な質問が多く挙がります。こうした質問の背景には、組み込み開発に従事するエンジニアは多いものの、OSを利用せずCPUの上でアプリケーションを直接動作させる「ベアメタル環境」を採用している現場や、クラウド開発からエッジ開発へと手を広げた際、馴染みの深い「Linux環境」を採用している現場が多いためかと感じています。
特に、ベアメタル環境を採用している開発現場では、既存のプログラムに緻密な仕掛けを施し、仮想的なマルチタスク動作(OSを利用しない並行処理)を実現しているケースをよく耳にします。こうした現場では「OSを導入することにより、過去の開発資産が使えなくなるのではないか」といった不安が大きいようです。
そこで、NuttXを紹介する前に「リアルタイムOS」の特長を紹介します。
リアルタイムOSは簡単に導入できる
リアルタイムOSは非常に簡単に導入することができます。
まず、リアルタイムOSのソースコードを入手し、既存のソースコードと結合します。次に、CPU開始直後に実行されるプログラムからリアルタイムOSの初期化関数を呼び出すようソースコードを変更します。続いて、リアルタイムOSに、リアルタイムOSの初期化後に実行するプログラムを設定します。最後に、ビルドし、リアルタイムOSを含む実行ファイルを生成します。以降、リアルタイムOSはブラックボックスとして機能し、イベントの発生を検知して、対応するタスクを停止状態から起動可能状態へと遷移。タスクの優先度を加味しながら、スケジューリング・ポリシーに従ってタスクを実行します。
一例を挙げると、SPRESENSE SDKのリアルタイムOS「NuttX」には、リアルタイムOSの初期化後に起動するタスクとして「sdk_entry」が設定されています(図2)。この設定により、システムに電源が投入された後、もしくはリセット後、リアルタイムOSが初期化され、続いてアプリケーションの実行が開始されます。
リアルタイムOSはタスクの実行順序を簡単に設定できる
リアルタイムOSを利用することにより複数のタスクに対して、タスクの開始/中断/再開の制御が可能です。CPUが1個のシステムであっても、複数のタスクの状態をメモリ上の情報として保持し(コンテキスト)、CPU上のタスクを任意のタイミングで入れ替えることができます。NuttXはマルチコア構成(ASMP/SMP)に対応したリアルタイムOSのため、複数のタスクの制御と、複数のCPUの制御が可能です。こうした機能をベアメタル(OSレス)のシステムで実装した場合、莫大な検証工数が掛かります。リアルタイムOSの場合、リリース前に動作が検証されており、採用実績も多いため、安心して開発に着手できることはもちろん、全体的な開発コスト削減効果も期待できます。
NuttX Tasking | NuttX Implementation/Design
下記に、リアルタイムOSの提供する代表的なスケジューリング・ポリシーを列挙します。
FIFO(First-In-First-Out)スケジューリング
FIFOスケジューリング(SHCED_FF)は最も単純なスケジューリング・ポリシーです。最初に開始されたタスクが最初に終了するように、タスクの実行順序を決定します。
ラウンドロビン(Round-Robin)スケジューリング
ラウンドロビンスケジューリング(SHCED_RR)は、ハードウェア・タイマーに基づいて生成した単位時間(タイムスライス)間隔でタスクを入れ替え、タスクを並行実行するスケジューリング・ポリシーです。FIFOスケジューリングと異なり複数のタスクが均一に動くため、すべてのタスクの応答性が向上します。一方、タスク実行中に他のタスクが割り込むため、開始から終了までの実行時間は長くなります。
SPRESENSE SDKのタイムスライスは200ms(既定値、変更可能)に設定されています(図3)。
優先度ベースのスケジューリング(Priority-based Scheduling)
リアルタイムOS環境では、タスクに優先度を設定することができます。優先度を設定することで「どんなイベントにも邪魔をされず、最速で実行されるタスク」を設計することができます。このように、どのタスクを優先的に扱うかを定め、次に実行するタスクを選出するスケジューリング・ポリシーを「優先度ベースのスケジューリング」と呼びます。
SPRESENSE SDKでは、サンプルアプリケーションの優先度を図4のようにSDKコンフィグで指定することができます。
リソースの管理/調停をするためのAPIを提供
リアルタイムOSはリソースを管理/調停するためのAPIを提供します。SPRESENSE SDKの提供するリソースの管理/調停に関するAPIは、 初心者講座マルチコア編 第2回、 初心者講座マルチコア編 第6回をご参照ください。なお、これらのAPIもベアメタル環境でゼロから実装しようとすると、大きな開発工数や検証工数が発生します。
- ミューテックス・ロック
- カウンティング・セマフォ
- メッセージ・キュー
- 共有メモリ
SPRESENSE SDKが採用するリアルタイムOS「NuttX」
次に、SPRESENSE SDKが採用しているリアルタイムOS「NuttX」について学びましょう。前半では、従来のリアルタイムOS環境とNuttXの比較、後半ではLinux環境とNuttXの互換性や比較について紹介します。
NuttXは、リアルタイムOSに求められている「スケジューリング機能」に加えて、多数のデバイスドライバや各種ライブラリを統合したリッチなソフトウェア・プラットフォームです。カスタマイズ性にも優れており、必要な機能のみを選択してビルドできることから、高機能でありながら小さなフットプリント(メモリサイズ)を達成可能。メモリ資源が限られたCortex-M系のハードウェア・プラットフォームと親和性が高いリアルタイムOSです。また、既存の開発資産が豊富なLinux環境から、プログラムを移植しやすいこともNuttXの魅力のひとつです。
多数のデバイスドライバを搭載
NuttXには数多くのデバイスドライバが含まれています。組み込みシステムには欠かせないバスドライバ(i2c、spi)をはじめ、ネットワークドライバ(net、wireless、serial、usb)、車載対応(can)やネットワークやバスの先に接続されるセンサー(sensor)、LCD(lcd)、不揮発性のストレージ(eeprom)などのドライバにより、様々なデバイスに対応可能です。デバイスドライバの開発工数が不要となるため、実機上ですぐにアプリケーションを実行させることができます。多くのリアルタイムOS環境はスケジューリング機能の提供のみに留まり、デバイスの制御は自身で開発しなければならなかったため、実機上で動作検証するまでに長い時間がかかるという課題がありました。
※豊富なデバイスドライバを同梱する「Linux環境」を採用する開発現場の課題については、後述。
NuttXに同梱されるデバイスドライバ|spresense-nuttx
デバイス抽象化レイヤーを統合
実際の製品開発では、システムを構成する周辺ハードウェア(ペリフェラルデバイス)が生産停止になったり、入手が困難(製造数の低下、価格の高騰)になった場合、急遽、周辺ハードウェアの変更を求められることがあります。またPoCと実製品開発で異なるハードウェアを使うかもしれません。こうした状況に対応できるよう、NuttXはハードウェアの抽象化レイヤーを搭載。アプリケーションに、抽象化したデバイスを提供します。
アプリケーションが抽象化されたデバイスを操作すると、これらの操作をNuttXが実ハードウェアのデバイスドライバとマッピングし、デバイスドライバがハードウェアを操作、アプリケーションの期待する動作を実現できます。このレイヤリングより、アプリケーションに変更を加えることなく、ハードウェアを簡単に差し替えることができるため、高いポータビリティを達成可能です。
Linux向けのソフトウェア資産も活用できるNuttX
組み込みシステムのOSにLinuxを選択する開発現場も数多くあります。Linuxを採用することで、Linux向けに開発された膨大な量のソフトウェア資産を活用し、効率的なシステム開発を実現できます。Linuxのアプリケーションやミドルウェアは、標準規格であるPOSIX/ANSI規格のインタフェースに準拠して実装されているため、Linuxディストリビューションが異なる場合(UbuntuからRaspbianへ移行する場合)であっても手間なく移植可能です。
NuttXは、リアルタイムOSでありながら「POSIX/ANSI規格のインタフェース」を搭載しています。
POSIX/ANSI準拠のインタフェースを提供
NuttXはPOSIX(Portable Operating System Interface)/ANSI(American National Standards Institute)規格に準拠したインタフェース(API)をアプリケーションへ提供します。POSIXはLinuxが採用しているインタフェースであるため、Linux上で動作しているアプリケーションを、NuttX上へ簡単に移植可能です。
これまでPOSIX/ANSI準拠のアプリケーション資産を活用するには、Linux環境が必要とされていました。一方で、Linux環境はCortex-A系のCPUコアが必要となるため、高い消費電力や、それに伴う発熱といった課題が発生します。NuttXがPOSIX準拠のインタフェースを提供することにより、既存のソフトウェアを簡単にCortex-M系の低消費電力の環境へ移植できます。特に、SPRESENSEは超低消費電力のSoCであるため消費電力に関する課題を、まとめて解決することができます。
SPRESENSE SDKとNuttXは動作検証済のペアでリリースされる
NuttXは、オープン・ソース・ソフトウェア(OSS)のリアルタイムOSです。OSSを使った開発では「どのバージョンを使って動作検証をしたか」という情報が、ソフトウェア開発に関わるすべてのエンジニアに共有される必要があります。不整合なバージョンを使ってしまうと、検証工数の増大や、ソースコード品質の低下、開発の大きな手戻りを招く恐れがあります。
そこで、SPRESENSEの開発環境「SPRESENSE SDK」は、リリース直前にSPRESENSE SDKの本体とNuttXのバージョンを固定し、動作検証。不整合が起きないようにソフトウェアをペアにしてGitHub上でリリースしています。これにより、ソフトウェアの不整合を疑うことなく、安心して開発を進めることができます(図7)。
spresense-nuttx|SonyDevWorld GitHub
spresense|SonyDevWorld GitHub
まとめ
今回は、SPRESENSEが採用しているリアルタイムOS「NuttX」の概要について紹介しました。
次回は、今回紹介したNuttXの特長「POSIX/ANSI準拠のインタフェースを提供」について、実際にLinuxアプリケーションをSPRESENSE上へ移植する方法を紹介いたします。
SONY SPRESENSE
SPRESENSEは、Arm Cortex-M4コア(FPU機能搭載)を6コア搭載したシングルボードコンピュータです。マルチコアによる豊富な演算能力をはじめ、魅力的なペリフェラルを多数搭載しながら、電池のみでも駆動できる超低消費電力な製品です。本格的なエッジコンピューティングを是非ご体験ください。システムの試作はもちろん、PoC、製品化にもご活用いただけます。
開発者向けサイトを見る Switch-Scienceで購入する
APS学習ボード(SPRESENSE™ Extension Board用)
APS学習ボード(SPRESENSE™ Extension Board用)は、初心者講座の内容をはじめ、SPRESENSE SDKの提供するオーディオ入力機能やLCDドライバをはじめとする各種機能を、回路設計をすることなく簡単にお試しいただけるよう開発したAPSオリジナルの評価基板です。Web記事と併せてお楽しみください。
取扱説明書|APS学習ボード Switch-Scienceで購入する(ボード単体)
Switch-Scienceで購入する(部品キット)
こちらも是非
“もっと見る” マルチコア|SPRESENSE編
SPRESENSE×Neural Network Console:第4回|推論モデルを最適化し、エッジAIによるオリジナルの音声識別システムを構築する
今回の初心者講座では、SPRESENSEの「ハイレゾオーディオ入力」と「DNNRT機能」により「Neural Network Console」で生成したディープニューラルネットワーク(DNN)の推論モデルを統合。エッジ単体で完結するオリジナルの音声識別システムを構築する技法を解説いたします。
SPRESENSE×Neural Network Console:第3回|オーディオ解析に必要な学習用データを採取し、PC上で学習・推論を実行する
今回の初心者講座では、SPRESENSEに搭載されたハイレゾオーディオ入力を活用し、環境音を録音し、ディープニューラルネットワークによる音声分類に不可欠な学習用データと検証用データを生成する方法について解説します。また、PC上で動作するNeural Network Consoleによって生成した推論モデルをエッジ・デバイスへ統合するために解決すべき課題を紹介します。
SPRESENSE×Neural Network Console:第2回|異常検知に活用できるニューラルネットワークで波形の扱い方を学ぶ
SPRESENSEのDNNRT機能が扱うことのできるデータは画像だけでなく、産業分野を中心に人気が高まっている「異常検知・故障予知」に活用できる加速度センサーや大気圧センサーなどから収集した波形データも解析することができます。さらにSPRESENSEに内蔵されたハイレゾオーディオ録音機能も周辺環境を可聴域の波形データとして記録することができる優れたセンサーとして利用可能です。そこで、今回の初心者講座では、まず簡単な波形データの解析方法を例に、DNNRT機能から波形データを扱うシステムの構築方法について解説。DNNRT機能を活用した製品開発に必要となる技術を紹介いたします。