OS・実行環境

FreeRTOS

軽量で普及したオープンソースRTOS。

概要

FreeRTOSは、組み込みシステム向けのオープンソースリアルタイムOS(RTOS)です。小さなフットプリント・移植性の高さ・豊富な実績から、世界で最も広く使われているRTOSの1つとなっています。2003年にRichard Barry氏が開発を開始し、2017年にAmazon Web Services(AWS)が開発主導権を取得してからはAWS FreeRTOSとしてIoT向け機能が拡充されています。

コアカーネルはMITライセンスで公開されており、商用製品に無償で組み込めます。Cortex-M系を中心に40以上のアーキテクチャ・100以上のコンパイラ・開発環境をサポートし、ESP32・STM32・nRF52など主要マイコンの公式SDKにも統合されています。

歴史・背景

FreeRTOSは2003年にRichard Barry氏(英国)が個人プロジェクトとして開始しました。当初はCortex-M向けではなく、古いARMやPIC向けから始まりました。オープンソース化と軽量さが評価されて急速に普及し、2011年頃には組み込みRTOS分野でトップシェアを確立しました。

2017年11月、AWSがFreeRTOSの開発・運営を引き継ぎ、同時にAWS IoT・AWSクラウドサービスとの連携を強化したAWS FreeRTOSライブラリ群を追加公開しました。これによりIoTデバイス向けのOTA更新・セキュアプロビジョニング・クラウド通信が容易になりました。

2021年にはFreeRTOS Long Term Support(LTS)バージョンが発表され、企業が長期間安定して使えるサポート体制が整いました。現在はFreeRTOS 11系が最新で、カーネル・ライブラリ・ポートが整理されたモジュール構成になっています。

技術仕様

最小フットプリント

FreeRTOSカーネルは非常に小さく動作します:

構成ROMRAM
最小構成(タスク+スケジューラのみ)約5〜6KB約4KB
典型的な構成(キュー・セマフォ含む)約10〜15KB数KB + タスクスタック

サポートアーキテクチャ(一部)

  • ARM Cortex-M0 / M0+ / M3 / M4 / M7 / M33 / M55
  • ARM Cortex-A(SMP対応)
  • RISC-V(RV32 / RV64)
  • Xtensa LX6 / LX7(ESP32シリーズ)
  • AVR、PIC32、MSP430、RL78、RX
  • x86(検証・シミュレーション用途)

コアカーネルのAPI構成

FreeRTOS カーネルAPI(主要カテゴリ):

・タスク管理
  xTaskCreate()           タスク生成
  vTaskDelete()           タスク削除
  vTaskDelay()            相対時間待ち
  vTaskDelayUntil()       絶対時間(周期実行)待ち
  uxTaskGetStackHighWaterMark()  スタック残量確認

・キュー(Queue)
  xQueueCreate()          キュー生成
  xQueueSend()            キューへ送信
  xQueueReceive()         キューから受信
  xQueueSendFromISR()     ISRから送信

・セマフォ / ミューテックス
  xSemaphoreCreateBinary()      バイナリセマフォ
  xSemaphoreCreateCounting()    カウンティングセマフォ
  xSemaphoreCreateMutex()       ミューテックス(優先度継承)
  xSemaphoreGive() / Take()     セマフォ操作

・ソフトウェアタイマー
  xTimerCreate()          タイマー生成
  xTimerStart() / Stop()  タイマー制御

・イベントグループ
  xEventGroupCreate()     イベントグループ生成
  xEventGroupSetBits()    ビットセット
  xEventGroupWaitBits()   ビット待機

・ストリームバッファ / メッセージバッファ
  xStreamBufferCreate()   ストリームバッファ生成
  xStreamBufferSend()     データ送信

configパラメータ(FreeRTOSConfig.h)

FreeRTOSの動作はFreeRTOSConfig.hで設定します:

/* FreeRTOSConfig.h の主要設定 */
#define configUSE_PREEMPTION            1       /* プリエンプション有効 */
#define configCPU_CLOCK_HZ              168000000UL /* CPUクロック (168MHz) */
#define configTICK_RATE_HZ              1000    /* ティック周波数 (1kHz=1ms) */
#define configMAX_PRIORITIES            5       /* 優先度レベル数 */
#define configMINIMAL_STACK_SIZE        128     /* 最小スタック(ワード数) */
#define configTOTAL_HEAP_SIZE           (50 * 1024) /* ヒープサイズ */
#define configUSE_MUTEXES               1       /* ミューテックス有効 */
#define configUSE_RECURSIVE_MUTEXES     1       /* 再帰ミューテックス有効 */
#define configUSE_COUNTING_SEMAPHORES   1       /* カウンティングセマフォ有効 */
#define configUSE_TIMERS                1       /* ソフトタイマー有効 */
#define configUSE_TRACE_FACILITY        1       /* トレース機能有効 */

動作原理

スケジューラの動作

FreeRTOSは固定優先度プリエンプティブスケジューリングを採用しています。スケジューラはvTaskStartScheduler()の呼び出しで起動し、その後はシステムティック割り込みごとにどのタスクを実行するかを決定します。

優先度高 ┌─────────────────────────────────┐
Task A  │####│    │####│    │####│    │
Task B  │    │####│    │####│    │####│
Task C  │    │    │    │    │    │    │ (スタベーション状態)
優先度低 └─────────────────────────────────┘
         ↑tick割り込みごとにスケジューラ判断

同優先度タスクはラウンドロビンで実行されます(configUSE_TIME_SLICING=1)。

ヒープ管理(heap_1〜heap_5)

FreeRTOSはメモリアロケーションに5つの実装を提供します:

実装特徴用途
heap_1malloc/free不可、フラグメント無し静的生成のみ
heap_2free可能、フラグメントあり固定サイズオブジェクト
heap_3標準malloc/freeをラップ標準Cライブラリ使用時
heap_4ベストフィット、隣接ブロック結合最も一般的
heap_5非連続メモリ領域に対応複数メモリバンク

コンテキストスイッチの仕組み

コンテキストスイッチはCortex-MではPendSV例外を使って実装されています:

  1. 現在タスクのCPUレジスタをスタックに保存
  2. 現在タスクのスタックポインタをTCB(Task Control Block)に保存
  3. 次の実行タスクのスタックポインタをTCBから復元
  4. 次タスクのレジスタをスタックから復元
  5. 次タスクの実行を再開

用途・ユースケース

IoTデバイス

ESP32やSTM32を使ったWi-Fi/BLE接続デバイスでは、FreeRTOSが標準的に使用されます。ESP-IDF(Espressif IoT Development Framework)はFreeRTOS上に構築されており、Wi-Fiスタック・BLEスタック・センサードライバがFreeRTOSタスクとして動作します。

/* ESP32 + FreeRTOS でのBLEスキャンとセンサー読み取りの並行実行 */
void bleTask(void *arg) {
    esp_ble_gap_start_scanning(30); // 30秒スキャン
    for (;;) {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY); // イベント待機
        processBleData();
    }
}

void sensorTask(void *arg) {
    TickType_t lastWake = xTaskGetTickCount();
    for (;;) {
        vTaskDelayUntil(&lastWake, pdMS_TO_TICKS(500)); // 500ms周期
        float temp = bme280_read_temp();
        xQueueSend(sensorQueue, &temp, 0);
    }
}

産業機器・計測器

モーター制御・PID制御・センサーデータ収集などを並行して行う産業機器でFreeRTOSが多用されます。STM32 + FreeRTOSの組み合わせはこの分野で特に広く使われています。

ウェアラブル・ヘルスケアデバイス

Nordic nRF52シリーズを使ったウェアラブルでは、FreeRTOS上にBLE(SoftDevice)・センサー処理・表示制御を並行実行するアーキテクチャが一般的です。

実装・開発のポイント

タスクの実装パターン

/* 周期タスクの推奨実装:vTaskDelayUntil で絶対時間管理 */
void periodicTask(void *pvParameters) {
    TickType_t xLastWakeTime = xTaskGetTickCount();
    const TickType_t xPeriod = pdMS_TO_TICKS(10); // 10ms周期

    for (;;) {
        // 処理実行
        processData();

        // 絶対時間で次の実行まで待機(累積誤差を防ぐ)
        vTaskDelayUntil(&xLastWakeTime, xPeriod);
    }
}

スタックオーバーフロー検出

/* FreeRTOSConfig.h */
#define configCHECK_FOR_STACK_OVERFLOW  2  /* スタックパターン検査 */

/* フック関数を実装(スタックオーバーフロー検出時に呼ばれる) */
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    /* エラーログ出力・システムリセット等の対処 */
    configASSERT(0);
}

ウォッチドッグとの連携

ウォッチドッグタイマーとFreeRTOSを組み合わせる場合、全タスクが正常動作しているときのみウォッチドッグをリセットする「タスク監視タイマー」パターンが有効です。

/* ウォッチドッグ監視タスク例 */
void watchdogTask(void *arg) {
    for (;;) {
        // 全タスクの生存確認(各タスクがEventGroupでビットをセット)
        EventBits_t bits = xEventGroupWaitBits(aliveFlags,
            TASK_A_BIT | TASK_B_BIT, pdTRUE, pdTRUE,
            pdMS_TO_TICKS(1000));
        if (bits == (TASK_A_BIT | TASK_B_IT)) {
            HAL_IWDG_Refresh(&hiwdg); // WDTリセット
        }
    }
}

他技術との比較

FreeRTOS vs Zephyr

ZephyrはFreeRTOSより後発で、より現代的なアーキテクチャを持ちます。Bluetooth・Wi-Fi・USB等の豊富なドライバがZephyrの強みです。一方、FreeRTOSは成熟度・ドキュメント・コミュニティの厚みで優ります。

項目FreeRTOSZephyr
ライセンスMITApache 2.0
最小ROM約5KB約8KB
ドライバ数限定的(HALと組み合わせ)豊富(統合型)
ビルドシステム各IDE依存CMake + west
認定取得IEC 62443, FedRAMP等IEC 61508対応中
学習コスト低いやや高い

FreeRTOS vs TOPPERS

TOPPERSはITRON仕様準拠で日本の産業・車載分野で強いです。API体系が異なり(μITRON仕様準拠)、FreeRTOSとは互換性がありません。国内の安全規格が要求される場合はTOPPERS/A3が選ばれる傾向があります。

関連用語

参考リンク