CppDependによる静的コード分析は、FreeRTOSコードベースの構造的依存関係について深いアーキテクチャ上の洞察を提供します。Dependency Structure Matrix(DSM)を活用することで、開発者はコアカーネルコンポーネントがどのように相互作用しているかを可視化できます。

主要なアーキテクチャ上の発見
- 特定された依存サイクル:分析は、コアモジュール間の循環依存を明確に示しています。
Source/timers.cがSource/tasks.cと依存サイクルを形成しています。 - DSMマッピング:Dependency Structure Matrixは、
Source/event_groups.c、Source/list.c、Source/queue.c、Source/tasks.c、Source/timers.cなどのコアコンポーネント間のファイル横断的な結合を可視化します。 - ディレクトリ構造の内訳:プロジェクトレイアウトは、メインの
freertos名前空間配下のコンポーネントを追跡します。Source/*、Source/include/*、ターゲット固有のSource/portable/実装、および外部依存関係を含みます。
深掘り:timers.cとtasks.cの依存サイクル
Dependency Structure Matrix(DSM)にドリルダウンすると、色分けによってこの結合の正確な性質が明らかになります。
- 赤いセル:赤いセルをダブルクリックすると、
Source/timers.cとSource/tasks.c間の双方向依存サイクル全体がハイライトされます。 - 緑のセル:
tasks.cの関数や構造体からtimers.cへの直接的な依存関係を表します。 - 青いセル:
timers.cからtasks.cへの逆方向の依存関係を表します。コアタスク制御、スケジューラ状態、共有構造体への参照などが含まれます。

アーキテクチャ上の改善は可能か?
純粋なソフトウェア工学の観点からは、完全に分離すること(例:タイマーを完全に独立したプラグインモジュールにする)は技術的に可能ですが、組み込みシステムには重大なトレードオフが伴います。
- パフォーマンスとオーバーヘッド:FreeRTOSは、厳しいRAMとCPUサイクル制約を持つマイクロコントローラー向けに意図的に設計されています。モジュールの分離には通常、抽象化レイヤー、関数ポインタテーブル、動的登録フックの導入が必要です。これによりRAMオーバーヘッド、ROMフットプリント、関数呼び出し遅延が増加します。
- モノリシックなリアルタイム設計:安全性が重要な、またはリソース制約のあるRTOS設計では、コアスケジューラと補助サービス(タイマーなど)の間の緊密に制御された予測可能な相互作用が、疎なプラグインアーキテクチャよりも好まれます。これにより決定的な動作と容易な静的分析(MISRAコンプライアンスなど)が保証されます。
コードサイズを最小化したり、コンパイル対象をカスタマイズしたりする場合、アプリケーションがソフトウェアタイマーを使用しないなら、CMakeLists.txtからtimers.cを完全に除外できます。tasks.c、queue.c、list.cのみが残り、フットプリントを可能な限り小さく保てます。
FreeRTOS関数間の低結合
Code Quest(CQLinq)を使用してコードベース全体のメソッド結合を分析すると、ほぼすべてのFreeRTOS関数が非常に低い結合度を維持していることがわかります。

呼び出すメソッド数(NbMethodsCalled)が10を超えるメソッドをクエリすると、結果は驚くほど少数です。
from m in Methods
where m.NbMethodsCalled > 10
select new { m, m.NbMethodsCalled }- 最小限の高結合の外れ値:
freertosソリューション全体で、このしきい値に達するか超えるメソッドはわずか4つです。 - コアキュー操作:この境界を超える唯一の関数は、
Source/queue.cの__Globalsに存在します。具体的には、xQueueGenericSend、xQueueReceive、xQueueSemaphoreTake、xQueuePeek(13〜14メソッドを呼び出し)といったコアなルーティングおよび同期プリミティブです。 - アーキテクチャ上の教訓:これは、FreeRTOS関数の大部分が粒状で自己完結型であり、厳密に制御された数のコラボレーターとしか相互作用しないことを確認しています。
粒状のモジュール性:Code Cityにおける関数レベルのアーキテクチャ
FreeRTOSコードベースを3D Code Cityのメタファーで可視化すると、プロジェクト全体で関数がどのように構造化されているかを直感的に把握できます。広大なモノリシックなコードブロックではなく、アーキテクチャレイアウトは、個々の関数を表すコンパクトで高度に特化した建物が密集した都市を示しています。

- コンパクトな関数スケール:Code Cityメトリクスは、コアルーチンがタイトで管理しやすいフットプリントを維持していることを確認しています。例えば、
pvPortMalloc(size_t)のような重要なメモリ管理ルーチンは、わずか71行のコードでありながら保守性A評価を達成しています。 - 単一責任の原則:都市全体の建物サイズの均一性は、FreeRTOSの設計哲学を強調しています。各関数は明確で焦点の絞られた目的に分離されています。
- 低複雑性と高保守性:個々のルーチンを小さく保つことで、複雑な条件ロジックと技術的負債が最小限に抑えられます。これはリアルタイムシステムにとって不可欠です。
FreeRTOSソースファイル全体の高い保守性
アーキテクチャ依存関係とメトリックグラフを分析すると、FreeRTOSはすべてのコアソースファイルとモジュールで卓越した保守性を維持していることがわかります。

- 均一な「A」評価:
Source/queue.c、Source/tasks.c、Source/timers.c、Source/portable/MemMang/heap_4.cを含むすべての主要サブシステムコンポーネントが、保守性で最高のA評価を獲得しています。 - 技術的負債ゼロ:重要なRTOS操作を処理しているにもかかわらず、
Source/queue.c(624 LOC)やSource/tasks.c(1036 LOC)などのファイルは、技術的負債が0分0秒と記録されており、コーディング標準のクリーンな遵守を証明しています。 - 高い保守性指数(MI):保守性指数はファイル全体で一貫して高く、
heap_4.c(MI: 66)の快適なスコアから、Source/timers.c(MI: 76)やポータブルヘルパーヘッダー(MI: 78)の優れた評価まで及んでいます。
Code Mapインサイト:timers.cの内部
Code Mapメトリック可視化(ブロックがコード行数でサイズ調整され、保守性で色分けされる)を通じてtimers.cのような特定のファイルを調べると、個々のルーチンがファイルのクリーンさにどのように貢献しているかを粒状的に把握できます。

- 一貫した緑色:
timers.c内の関数の大部分は鮮やかな緑色に色付けされており、高い保守性指数と低い構造的複雑さを示しています。 - バランスの取れたメソッドサイズ:
prvProcessReceivedCommandsのような大きなユーティリティブロックはレイアウトの目立つ部分を占めていますが、より小さなヘルパー関数と並んでクリーンに分割されています。 - クリーンなアーキテクチャ分散:この視覚的な内訳は、複雑なリアルタイム同期ロジックを含むファイル内でも、関数がコンパクトで明確に定義され、高度に保守可能であることを確認しています。
FreeRTOSの高レベルの設計およびアーキテクチャパターンをいくつか紹介します。
1. 移植性レイヤー(関心の明確な分離)
- ハードウェア抽象化:FreeRTOSは、汎用スケジューリングロジックをプロセッサ固有の詳細からクリーンに分離しています。
- portable/境界:コンテキストスイッチング、割り込み処理、SysTick設定などのすべてのハードウェア依存コードは、
Source/portable/ディレクトリ内に隔離されています。 - アーキテクチャ上の利点:このモジュラー設計により、コアカーネル(
tasks.c、queue.c)は数十のアーキテクチャ(ARM Cortex-M、RISC-Vなど)で100%移植可能であり続けます。
2. 不透明ポインタとデータカプセル化
- 情報隠蔽:FreeRTOSは、生のコントロールブロック構造を公開する代わりに、不透明ポインタとハンドル型(
TaskHandle_tやQueueHandle_tなど)を多用しています。 - アーキテクチャ上の利点:アプリケーションコードは、明確に定義されたAPIを通じてのみカーネルと相互作用します。これにより、ユーザータスクとカーネル内部状態の間の密結合が防止されます。
3. プラグアンドプレイのメモリ管理戦略
- 複数のヒープオプション:FreeRTOSは、5つの異なるメモリ管理実装(
heap_1.cからheap_5.c)を提供します。単純な解放なしアロケーターから、より高度な結合アルゴリズムまで対応しています。 - アーキテクチャ上の利点:これにより、組み込み開発者はメモリ動作をアーキテクチャレベルで制御できます。安全性が重要なシステム(自動車や航空宇宙など)では、決定的で断片化のないアロケーターを選択できます。
4. リアルタイム決定性のための低循環的複雑性
- 境界付き実行パス:個々の関数が小さく、低い分岐複雑性(ネストされたif-elseステートメントやループが少ない)を維持しているため、カーネルルーチンの実行時間は高度に予測可能です。
- アーキテクチャ上の利点:ハードリアルタイムオペレーティングシステム(RTOS)では、予測可能な実行時間(決定性)は正確性と同じくらい重要です。低複雑性は、スケジューラが厳格なタイミング期限を満たすことを保証します。
結論:FreeRTOS分析からの教訓
CppDependを使用したアーキテクチャ分析は、FreeRTOSがリアルタイムパフォーマンス要件とクリーンコードプラクティスをどのように両立させているかについて明確な洞察を提供します。
- 絶対的な分離よりも実用的な結合:
Source/timers.cとSource/tasks.cの間にはxTimerTaskHandleなどの共有状態による依存サイクルが存在しますが、この設計選択は抽象化オーバーヘッド、関数ポインタ間接参照、メモリフットプリントを最小限に抑えます。これはリソース制約のあるマイクロコントローラーにとって重要な優先事項です。 - 卓越したモジュール性と低結合:この単一の緊密な相互作用を除けば、コードベースは驚くほど低い結合を示しています。リポジトリ全体で10個以上の他のメソッドを呼び出す関数はわずか4つであり、複雑さは
Source/queue.cのコアキューおよび同期プリミティブに厳密に限定されています。 - 高い保守性と技術的負債ゼロ:粒状の単一責任関数を通じて、FreeRTOSは
tasks.c、timers.c、heap_4.cなどの主要ファイルで最高のA保守性評価と0秒の技術的負債を達成しています。
独自のファームウェアのアーキテクチャを確認したいですか? CppDependをダウンロードして、数分でコードベースを分析できます。別のプロジェクトを可視化した方法もご覧ください:AI生成コードから生きたCode Cityへ。
