FreeRTOS主要API実践解説と最適化技術

タスク管理APIの選択基準

API機能ISRセーフ版適用シナリオ
xTaskCreate動的タスク生成不可一般用途タスク作成
xTaskCreateStatic静的メモリ割り当てタスク不可メモリ制約環境
vTaskDeleteタスク削除不可動的ライフサイクル管理
vTaskDelay相対時間遅延不可簡易遅延処理
vTaskDelayUntil絶対時間同期遅延不可周期処理タスク
xTaskNotifyGive軽量通知送信xTaskNotifyGiveFromISR高速同期処理

周期制御タスク実装例

void cycleControlTask(void *arg) {
TickType_t nextSyncTime = xTaskGetTickCount();
const TickType_t interval = pdMS_TO_TICKS(20); // 20ms周期

while (1) {
// メイン処理ロジック
vTaskDelayUntil(&nextSyncTime, interval);
}
}

通信メカニズム比較

特性キュータスク通知
データ容量可変サイズデータ32bit値/ポインタ
メモリ使用量高(バッファ必要)極低(TCB内利用)
処理速度中程度極高速
複数受信者対応単一タスク限定
ブロッキング対応対応対応

キュー実装サンプル

QueueHandle_t sensorQueue = xQueueCreate(10, sizeof(SensorReading));

SensorReading data = { .value = 45.2, .timestamp = xTaskGetTickCount() };
xQueueSend(sensorQueue, &data, portMAX_DELAY);

SensorReading rxData;
if (xQueueReceive(sensorQueue, &rxData, pdMS_TO_TICKS(50))) {
processSensorData(rxData);
}

タスク通知実装サンプル

xTaskNotifyGive(taskHandle);

ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

同期メカニズム最適化

タイプ生成関数特徴
バイナリセマフォxSemaphoreCreateBinaryオン/オフ状態管理
カウンティングセマフォxSemaphoreCreateCountingカウンタ上限設定可能
ミューテックスxSemaphoreCreateMutex優先度継承機能搭載
再帰ミューテックスxSemaphoreCreateRecursiveMutex同一タスクによる多重取得

リソース保護実装例

SemaphoreHandle_t resourceLock = xSemaphoreCreateMutex();

void criticalSectionTask(void *param) {
if (xSemaphoreTake(resourceLock, pdMS_TO_TICKS(200)) == pdTRUE) {
// 共有リソースアクセス
xSemaphoreGive(resourceLock);
}
}

割り込み処理最適化

void UART_IRQHandler(void) {
BaseType_t contextSwitchRequired = pdFALSE;

uint8_t receivedByte = UART_Read();
xQueueSendFromISR(uartRxQueue, &receivedByte, &contextSwitchRequired);
xSemaphoreGiveFromISR(dataAvailableSem, &contextSwitchRequired);

portYIELD_FROM_ISR(contextSwitchRequired);
}

遅延処理実装

void deferredHandler(void *param, uint32_t value) {
// 長時間処理実行
}

xTimerPendFunctionCallFromISR(
deferredHandler,
(void*)sensorData,
0,
&contextSwitchRequired
);

メモリ管理テクニック

void monitorHeapUsage(void) {
printf("Free: %u, Min: %u\n",
xPortGetFreeHeapSize(),
xPortGetMinimumEverFreeHeapSize());
}

void vApplicationIdleHook(void) {
static TickType_t lastCheck = 0;
if (xTaskGetTickCount() - lastCheck > pdMS_TO_TICKS(10000)) {
monitorHeapUsage();
lastCheck = xTaskGetTickCount();
}
}

静的メモリ割り当て例

static StaticTask_t taskControlBlock;
static StackType_t taskStack[128];

xTaskCreateStatic(
taskEntry,
"PeriodicTask",
128,
NULL,
tskIDLE_PRIORITY + 2,
taskStack,
&taskControlBlock
);

トラブルシューティング手法

スタック監視設定

// FreeRTOSConfig.h
#define configCHECK_FOR_STACK_OVERFLOW 2

void vApplicationStackOverflowHook(TaskHandle_t task, const char *name) {
printf("Stack overflow in %s\n", name);
HAL_Deinit(); // ハードウェア初期化
}

優先度反転対策

SemaphoreHandle_t mutexHandle = xSemaphoreCreateMutex();

void highPriorityTask(void *param) {
xSemaphoreTake(mutexHandle, portMAX_DELAY);
// クリティカルセクション(短時間)
xSemaphoreGive(mutexHandle);
}

高度な同期パターン

状態機械連携

typedef enum { IDLE, ACTIVE, ERROR } SystemState;

void stateMachineTask(void *param) {
SystemState currentState = IDLE;

while (1) {
uint32_t notification;
if (xTaskNotifyWait(0, 0xFF, ¬ification, 100) == pdTRUE) {
currentState = (SystemState)(notification & 0xFF);
}

switch (currentState) {
case IDLE: /* 待機処理 */ break;
case ACTIVE: /* 実行処理 */ break;
case ERROR: /* エラー処理 */ break;
}
}
}

複合イベント同期

EventGroupHandle_t systemEvents = xEventGroupCreate();

// イベント設定
xEventGroupSetBits(systemEvents, SENSOR_READY_BIT);

// 複数イベント待機
EventBits_t bits = xEventGroupWaitBits(
systemEvents,
SENSOR_READY_BIT | DATA_READY_BIT,
pdTRUE,
pdTRUE,
portMAX_DELAY
);

性能最適化戦略

// FreeRTOSConfig.h
#define configTOTAL_HEAP_SIZE (16 * 1024)
#define configMINIMAL_STACK_SIZE 128
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1

開発ロードマップ

  • 基礎段階:タスク生成・キュー操作・バイナリセマフォ
  • 中級段階:タスク通知・イベントグループ・ミューテックス
  • 高度段階:静的メモリ管理・性能計測・リアルタイム性検証

API選択チェックリスト

用途最適API
タスク生成xTaskCreate/xTaskCreateStatic
軽量同期xTaskNotifyGive/xTaskNotifyWait
データ転送xQueueCreate/xQueueSend
リソース保護xSemaphoreCreateMutex
複合イベントxEventGroupWaitBits
ISR処理xxxFromISR + portYIELD_FROM_ISR
タイマー処理xTimerCreate/xTimerStart
メモリ管理pvPortMalloc/vPortFree

実装ルール

  • 割り込みハンドラでは常にFromISR版APIを使用
  • 単純な同期にはタスク通知を優先
  • クリティカルセクションは静的メモリ割り当て
  • 優先度設定で優先度反転を防止
  • デバッグ用フック関数を積極的に活用

タグ: FreeRTOS タスク通知 キュー セマフォ イベントグループ

6月14日 18:02 投稿