FreeRTOS実践入門

FreeRTOSはAmazonがサポートするオープンソースのRTOSであり、組み込み開発の現場で広く採用されています。基本的なタスク管理の使い方は資料が豊富ですが、ヒープ管理の選択・Task Notification・Stream Buffer・フック関数・FreeRTOSConfig.hの設定といったFreeRTOS固有の機能は、実装時に迷いが生じやすいポイントです。

そこでこの記事では、それらの要点を実装判断の視点から整理していきます。

FreeRTOSが選ばれる理由

FreeRTOSはAmazonがサポートするオープンソースRTOSです。ポーティング事例が豊富でCortex-MからRISC-Vまで幅広いMCUに対応しており、MITライセンスで商用利用が可能です。ドキュメントが充実しており、μITRONとともに組み込み現場で広く使われています。

ライセンスの自由度・豊富なポーティング事例・活発なコミュニティという3つの強みが、産業機器・IoT・FA分野での採用を後押ししています。

FreeRTOS固有のヒープ管理:heap_1〜5

FreeRTOSはpvPortMalloc/vPortFreeの実装として5つのヒープ管理方式を提供しています。プロジェクトの要件に応じて適切な方式を選択することが重要です。

各方式の特徴と選択基準

heap_1~5の特徴や用途について簡単に表にまとめます。

方式 特徴 適した用途
heap_1 解放不可・最もシンプル。確保だけ 起動時に静的にオブジェクトを生成し、以降変更しないシステム
heap_2 解放可能・best-fit。隣接ブロック統合なし サイズが常に同じオブジェクトの繰り返し確保・解放
heap_3 標準malloc/freeのラッパー 既存のmalloc/freeを流用したい場合
heap_4 解放可能・first-fit・隣接ブロック統合あり。断片化抑制 一般用途。最も広く採用される方式
heap_5 heap_4に加え非連続メモリ空間に対応 複数のRAM領域を一つのヒープとして扱いたい場合

heap_4が広く採用される理由

heap_4は、隣接するフリーブロックを統合する機能を持ちます。そのため、断片化を抑制しながら解放・再割り当てが可能で、heap_2より効率が高く、一般用途に最も適しています。

特別な要件がない限り、heap_4から検討することがお勧めです。

FreeRTOS固有の軽量通知:Task Notification

Task NotificationはFreeRTOS v8.2以降で使えるタスク固有の通知機構です。セマフォやキューより軽量な実装でタスク間・ISR→タスクの通知を実現します。

セマフォ・キューより軽量な1対1通知の仕組み

各タスクが内蔵する通知値(32bitの値)を直接操作するため、セマフォやキューのようなカーネルオブジェクトの動的生成が不要です。バイナリセマフォより高速かつ省メモリな通知を実現します。

xTaskNotifyGive/ulTaskNotifyTakeでバイナリ・カウンティングセマフォ相当の動作、xTaskNotify/xTaskNotifyWaitでより汎用的な値通知が使えます。

Task Notificationが使えない場面と代替手段

デフォルト設定では通知チャンネルが1つのため、複数の送信元からの通知を区別できません。複数タスクが独立したチャンネルで通知する必要がある場合はキューへの切り替えが適切です。

なお、FreeRTOS v10.4.0以降ではconfigTASK_NOTIFICATION_ARRAY_ENTRIESを設定することで複数チャンネルを持てるようになっています。

FreeRTOS固有のストリーム転送:Stream Buffer/Message Buffer

Stream BufferとMessage Bufferは、ISRとタスク間またはタスク間でのデータ転送を効率よくおこなうためのFreeRTOS固有のオブジェクトです。

Stream BufferとMessage Bufferの違い

Stream Bufferは、バイト単位での連続データストリームを転送します。バイトストリームとして扱うため、メッセージの区切りを意識しない点が特徴です。一方、Message Bufferは、可変長メッセージ単位の転送に使用します。各メッセージの先頭にサイズ情報が付加され、メッセージの区切りが保たれます。

どちらも単一送信者・単一受信者専用のロックレス設計です。複数の送信者または受信者がいる場合は別途排他制御が必要になります。

シングルコアMCUで活きるロックレス設計

送信者1つ・受信者1つという前提のもと、割り込みとタスク間のデータ転送をミューテックスなしで実現できます。ISR→タスクへの高頻度データ受け渡しでオーバーヘッドを最小化できるため、センサデータの連続収集やUART受信バッファとして活用されます。

FreeRTOS固有のフック関数

FreeRTOSはカーネルの特定タイミングでユーザ定義の処理を呼び出す「フック関数」の仕組みを持っています。問題検出や省電力制御に活用することが可能です。

スタックオーバーフロー・メモリ確保失敗を検知するフック

vApplicationStackOverflowHookは、コンテキストスイッチ時にスタック超過を検出した際に呼ばれます。引数にタスクハンドルとタスク名が渡されるため、どのタスクで発生したかを特定しやすくなっています。

FreeRTOSConfig.hのconfigCHECK_FOR_STACK_OVERFLOWを1または2に設定することで利用することが可能です。vApplicationMallocFailedHookはpvPortMallocでヒープ確保に失敗した際に呼ばれます。こちらは、ヒープ不足の早期検出に活用できます。

IdleフックとTickフックの活用場面

vApplicationIdleHookは、すべてのタスクがブロック中でIdleタスクが動いている際に呼ばれ、CPUアイドル時のWFIなどのスリープ命令の省電力処理に使います。ただし、Idleタスクは常に実行可能な状態を保つ必要があります。そのため、vTaskDelayなどのブロッキングAPIの呼び出しは禁止です。

また、vApplicationTickHookはtick割り込みのISRコンテキストから呼ばれ、FromISR系APIの使用と処理の短時間化が必須です。tick単位の定期処理をおこないたい場合に活用できますが、長い処理はタスクに委譲することを徹底する必要があります。

FreeRTOSConfig.hで押さえる主要設定

FreeRTOSConfig.hはFreeRTOSのカーネル動作を決定するコンフィグファイルです。設定ミスがシステム全体の動作に影響するため、まずは主要項目から理解しておきましょう。

カーネル動作に影響する主要な設定項目

最低限押さえておくべき、6つの主要な設定項目を簡単にまとめます。

設定項目 内容
configTICK_RATE_HZ tickの周波数。1000Hzなら1ms刻み。高くするほど精度は上がるがオーバーヘッドも増える
configMAX_PRIORITIES 使用できる優先度の最大数。大きすぎると内部テーブルのRAM消費が増えるため必要最小限に設定する
configUSE_PREEMPTION 1でプリエンプティブ、0で協調型を選択する
configUSE_TIME_SLICING 1でラウンドロビン(タイムスライス)を有効化する。同一優先度タスクの公平な実行に必要
configMINIMAL_STACK_SIZE Idleタスクのスタックサイズ(ワード単位)。小さすぎるとスタックオーバーフローの原因になる
configTOTAL_HEAP_SIZE heap_1〜5で管理するヒープサイズ。タスク・キューなどの生成に使われる

設定ミスが招く典型的なトラブル

FreeRTOSConfig.hのパラメータは、誤って設定してもコンパイルエラーにならないケースがほとんどです。そのため、設定ミスは実行時の挙動として表れ、原因の特定が難しくなります。

よくあるミスの一つが、configMAX_PRIORITIESを実際に使用している最大優先度より小さく設定してしまうケースです。この場合、超過した優先度は自動的に上限値に丸められるため、別々の優先度で動くはずのタスクが同じ優先度として扱われ、意図しない実行順序が発生します。

また、configTOTAL_HEAP_SIZEの不足もよくあるトラブルの一つです。ヒープが足りない場合、xQueueCreateはNULLを、xTaskCreateはerrCOULD_NOT_ALLOCATE_REQUIRED_MEMORYを返します。しかし、戻り値のチェックを省略していると生成失敗に気付かないままプログラムが進み、後続の処理で突然クラッシュするという形で問題が表面化します。

タスクやキューの生成直後に戻り値をconfigASSERTで検査する習慣を付けておくと、こうした問題を早期に検出できます。

まとめ

FreeRTOS固有の機能を使いこなすには、ヒープ方式の選択・Task Notificationの制約・Stream Bufferのロックレス前提条件・フック関数の呼び出しコンテキスト・FreeRTOSConfig.hの設定値の意味を正しく理解することが重要です。

これらのポイントを押さえることで、実装上のハマりどころを大きく減らすことができるでしょう。この記事を参考に、FreeRTOSに触れてみてはいかがでしょうか。

組み込みソフトの世界 トップへ戻る