xEventGroupWaitBits の動作のメモ

xEventGroupWaitBits の動きを確認した。

最初は、xEventGroupWaitBits の第一引数に渡す EventGroup が xEventGroupWaitBits から返った後にイベントの値がクリアされて、それは該当のビットだけなのか、全ビットなのか？を確認したかった。
しかし、検証してみると返り値のほうも想定とすこし違った動きをしていたのでメモしておく。

----

テストプログラム

main_task 側
1. test_task を起動
1. BIT2 をセット
1. 3秒後、BIT1 をセット
1. 10秒後 BIT0 をセット を表示

test_task側
1. 最初は BIT0, BIT1 だけ待つ
1. BIT0 を受信時 wait_bit に BIT2 を追加
1. BIT1 を受信時 メッセージ表示のみ
1. BIT2 を受信時 break


```c
#include <FreeRTOS.h>
#include <task.h>
#include <event_groups.h>
#include <stdio.h> // printf

static EventGroupHandle_t events;

static void test_task(void *vpParameters)
{
    EventBits_t wait_bits;
    wait_bits = BIT0 | BIT1;

    vTaskDelay(pdMS_TO_TICKS(1000));

    for (;;)
    {
        printf("[test_task] waiting for bits %08x...\n", wait_bits);
        EventBits_t bits = xEventGroupWaitBits(events, wait_bits, pdTRUE, pdFALSE, portMAX_DELAY);

        printf("[test_task] returned bits = %08x.\n", bits);

        if (bits & BIT0)
        {
            printf("[test_task] bit0 received.\n");
            wait_bits |= BIT2;
            printf("[test_task] wait_bits updated.\n");
        }
        if (bits & BIT1)
        {
            printf("[test_task] bit1 received.\n");
        }
        if (bits & BIT2)
        {
            printf("[test_task] bit2 received.\n");
            printf("[test_task] break.\n");
            break;
        }
    }

    vTaskDelete(NULL);
}

static void main_task(void *pvParameters)
{
    printf("\n");
    events = xEventGroupCreate();
    if (!events)
    {
        printf("xEventGroupCreate failed");
        vTaskDelete(NULL);
    }

    if (xTaskCreate(test_task, "test_task", STACKSIZE, NULL, tskIDLE_PRIORITY + 8, NULL) != pdPASS)
    {
        printf("xTaskCreate(aircon_main) failed");
        vTaskDelete(NULL);
    }
    taskYIELD();

    printf("[main_task] set BIT2 of events.\n");
    xEventGroupSetBits(events, BIT2);

    vTaskDelay(pdMS_TO_TICKS(3 * 1000));

    printf("[main_task] set BIT1 of events.\n");
    xEventGroupSetBits(events, BIT1);

    vTaskDelay(pdMS_TO_TICKS(10 * 1000));

    printf("[main_task] set BIT0 of events.\n");
    xEventGroupSetBits(events, BIT0);

    vTaskDelete(NULL);
}

int main(void)
{
    if (xTaskCreate(main_task, "main_task", STACKSIZE, NULL, tskIDLE_PRIORITY + 8, NULL) != pdPASS)
    {
        printf("xTaskCreate(main_task) failed.\n");
    }

    vTaskStartScheduler();
    return 0;
}
```

結果

```
[main_task] set BIT2 of events.
[test_task] waiting for bits 00000003...
[main_task] set BIT1 of events.
[test_task] returned bits = 00000006.
[test_task] bit1 received.
[test_task] bit2 received.
[test_task] break.
[main_task] set BIT0 of events.
```

ちがうそうじゃない.

想定だと、以下の２つのどちらかの流れだった。そもそもこの２つのどっちになるのかを確認したかった。
・bit1 受信 → メッセージ表示 → bit0 受信 → wait_bits 更新 → bit2 受信 → ループ脱出
・bit1 受信 → メッセージ表示 → bit0 受信 → wait_bits 更新 → これまでの xEventGroupWaitBits の呼び出しで bit2 がクリアされていて受信できない

しかし実際には bit1 を受信した時点で bit2 を受信してしまい ループから脱出してしまっている。
bit1 受信時点の xEventGroupWaitBits の返り値を確認すると上記結果のとおり 6 だった。ぬぅ？

xEventGroupWaitBits の仕様ってどうなってるの？を確認すると、

>Returns:
The value of the event group at the time either the event bits being waited for became set, or the block time expired. 

訳：イベントビットがセットされた時点、またはタイムアウト時間が経過した時点の event group の値。

とある。なるほど、それならこの動きは納得。
セットされたビットだけが返ってくるのかと思っていた。

というわけで以下の通りに修正した。

```c
         printf("[test_task] waiting for bits %08x...\n", wait_bits);
+        printf("[test_task] current bits=%08x.\n", xEventGroupGetBits(events));
         EventBits_t bits = xEventGroupWaitBits(events, wait_bits, pdTRUE, pdFALSE, portMAX_DELAY);

         printf("[test_task] returned bits = %08x.\n", bits);
+        printf("[test_task] current bits=%08x.\n", xEventGroupGetBits(events));

+        bits &= wait_bits;    // ★★★★★★★★★★★★★★★★★ キモ！
+        printf("[test_task] bits = %08x.\n", bits);
```

printf が増えたのは置いといて、bits と wait_bits とで論理積を取得するようにした。キモ！の行。


修正結果→

```
[main_task] set BIT2 of events.
[test_task] waiting for bits 00000003...
[test_task] current bits=00000004.
[main_task] set BIT1 of events.
[test_task] returned bits = 00000006.
[test_task] current bits=00000004.
[test_task] bits = 00000002.
[test_task] bit1 received.
[test_task] waiting for bits 00000003...
[test_task] current bits=00000004.
[main_task] set BIT0 of events.
[test_task] returned bits = 00000005.
[test_task] current bits=00000004.
[test_task] bits = 00000001.
[test_task] bit0 received.
[test_task] wait_bits updated.
[test_task] waiting for bits 00000007...
[test_task] current bits=00000004.
[test_task] returned bits = 00000004.
[test_task] current bits=00000000.
[test_task] bits = 00000004.
[test_task] bit2 received.
[test_task] break.

```

想定通り！
確認したかった動きも確認できた。