1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【FreeRTOS × ESP32】MessageBufferとは?Queueとの違いと最小サンプル

Last updated at Posted at 2025-12-27

この記事でわかること

  • MessageBufferの機能内容(何ができるか)
  • Queueとの違い(固定長 vs 可変長)
  • 最小構成のサンプル(ESP32 ESP-IDFで動く)

今までArduinoのフレームワークを使用していましたが、今後はESP-IDFを使用したコードで実装例を示します。
ESP-IDFの環境構築について知りたい方がいれば、まとめますのでコメントよろしくお願いいたします。

1. MessageBufferの機能内容(何ができる?)

FreeRTOS の MessageBuffer(メッセージバッファ) は、
タスク間で 可変長のデータ(バイト列) を送受信できる仕組みです。

Queueは「固定サイズのデータ(例:uint32_tや構造体)」を渡すのが得意ですが、
MessageBufferは 文字列・JSON・可変長フレーム のように、長さが毎回変わるデータを扱うのに向いています。

できることをざっくり言うと:

  • 送信:可変長データ(バイト列)をバッファに入れる
  • 受信:1件(1メッセージ)ずつ取り出す(境界がある)

ができます。

2. Queueとの違い(初心者向けに一言で)

違いを一言でまとめるとこうです。

  • Queue:固定長の“箱”を順番に渡す
  • MessageBuffer:可変長の“メッセージ”を1件ずつ渡す

Queueだと困りやすいケース

  • 文字列(ログ)を渡したい
  • JSONを渡したい
  • 通信フレーム(長さ可変)を渡したい

Queueでやろうとすると、
「最大長のバッファ構造体を作る」「無駄なコピーが増える」などで面倒になります。

MessageBufferなら、メッセージ長を意識せず送って、受信側でまとめて受け取れるので実装がシンプルになります。

3. MessageBufferのイメージ(1件ずつ受け取れる)

MessageBufferは、単なるバイトの流れではなく “メッセージ境界” があるのが特徴です。

[ "HELLO" ][ "JSON:{...}" ][ "OK" ]

受信側は1件ずつ取り出せます。

4. 【実装】最小サンプル(ESP32 + ESP-IDFで動く)

やること

  • SenderTask:可変長メッセージ(文字列)を送信
  • ReceiverTask:受信して printf() で出力

MessageBuffer自体は '\0' を必要としません(長さ付きバイト列として扱うため)。
ただ今回は printf("%s") で出力したいので、送信側で '\0' まで含めて送っています

#include <cstdio>
#include <cstring>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/message_buffer.h"

// MessageBuffer全体の容量(この中に複数メッセージが格納される)
static MessageBufferHandle_t mbuf;

void SenderTask(void *pvParameters) {
    const char *msg1 = "HELLO";
    const char *msg2 = "JSON:{\"temp\":25.3}";
    for (;;) {
        // 文字列末尾の '\0' も含めて送る(受信側でprintfしやすい)
        xMessageBufferSend(mbuf, msg1, strlen(msg1) + 1, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(500));

        xMessageBufferSend(mbuf, msg2, strlen(msg2) + 1, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(1500));
    }
}

void ReceiverTask(void *pvParameters) {
  char rx[64];

    for (;;) {
        // 受信バッファサイズを超えるメッセージは受け取れないので注意
        size_t n = xMessageBufferReceive(mbuf, rx, sizeof(rx), portMAX_DELAY);

        if (n > 0) {
            printf("[RX] %s (len=%u)\n", rx, (unsigned)n);
        }
        else {
            printf("MessageBufferReceiveError\n");
            vTaskDelay(pdMS_TO_TICKS(100)); // ログ連打防止
        }
    }
}

extern "C" void app_main(void)
{
    // MessageBuffer全体のバッファサイズ(この中に可変長メッセージが詰まる)
    mbuf = xMessageBufferCreate(128);
    if(mbuf == NULL){
        printf("MessageBufferCreateError\n");
        return;
    }

    xTaskCreate(SenderTask, "SenderTask", 2048, NULL, 1, NULL);
    xTaskCreate(ReceiverTask, "ReceiverTask", 2048, NULL, 1, NULL);
}

5. 主要関数(役割だけ押さえる)

xMessageBufferCreate(作る)

mbuf = xMessageBufferCreate(128);
//MessageBufferを作る(128バイト分の領域を確保)

xMessageBufferSend(送る)

xMessageBufferSend(mbuf, data, len, portMAX_DELAY);
// data(バイト列)を len バイト送る
// 送れたら len が返り、満杯などで送れなければ 0 が返る

xMessageBufferReceive(受け取る)

n = xMessageBufferReceive(mbuf, rx, sizeof(rx), portMAX_DELAY);
//1件のメッセージを受け取る(rxにコピーされる)

6. 使いどころ

ログ文字列を別タスクに渡してまとめて出力
JSONやHTTPの一部など可変長データの受け渡し
通信フレーム(長さが決まっていないデータ)の受け渡し

7. 注意点(初心者が詰まりやすい)

受信バッファが小さい → xMessageBufferReceive() が 0 を返す
※そのメッセージはバッファに残るので、次の受信も同じメッセージで失敗し続ける
→ rx を十分大きくする(または最大長を設計で決める)

MessageBufferの容量が小さいとすぐ満杯になる
→ xMessageBufferCreate() のサイズは余裕を持たせる

可変長は便利だが、最大サイズの設計は必要
→ “無限に長いデータ”は扱わない(必ず上限を決める)

原則は 1 writer / 1 reader 前提
→ MessageBuffer(StreamBuffer含む)は、基本的に 送信者1・受信者1 を想定しています。

8. まとめ

  • MessageBufferは 可変長メッセージ をタスク間で渡せる仕組み
  • Queueが苦手な 文字列/JSON/可変長フレーム に強い
  • 原則は 1 writer / 1 reader 前提

次は、バイト列を“流す”用途に強い StreamBuffer を紹介します(UART受信などで便利です)。


FreeRTOS × ESP32 記事シリーズ

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?