0
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?

More than 5 years have passed since last update.

FRDM-K64FでAmazonFreeRTOSを動かす

Posted at

FRDM-K64FのSDKに付属のamazon FreeRTOS のサンプルをいじって、わかったことを書き留めます。
開発環境はMCUXpressoを使用します。

frdm_k64f_freertos_hello

  • タスクからHelloWorldするサンプル
  • ROM/RAM は -O0 でそれぞれ 22872 Byte / 19120 Byte
  • main() では最初にBOARD_xxx というAPI群を呼ぶ
    • クロック、ペリフェラル初期化など
    • BOARD_xxx APIは board/board.c にあるBSPのAPI
  • xTaskCreate()Hello_task のタスク登録
    • 引数はタスクメイン関数ポインタ、タスク名、スタックサイズ、起動引数、プライオリティ、ハンドラ格納用変数
    • このAPIを呼ぶには source/FreeRTOSConfig.hconfigSUPPORT_DYNAMIC_ALLOCATION が 1 でないといけない
    • タスク登録に成功すると pdPASS が返る
  • hello_task() は無限ループ
    • "Hello world." を出力してサスペンドする
    • vTaskSupend()vTaskResume() 待ちとなりディスパッチされなくなる
    • 引数はタスクのハンドラだが、NULLで呼ぶと自身をサスペンドする
  • タスク登録後 vTaskStartScheduler() でタスクスケジューラを起動して、メイン関数は無限ループに入る
  • ここで起動しているタスクは3つ
    • Hello_task
    • IDLE : アイドルタスク
    • Tmr svc : タイマーデーモンタスク
  • アイドルタスクとタイマーデーモンタスクは vTaskStartScheduler() 呼び出し時に自動的に作成される
source/freertos_hello.c抜粋
int main(void)
{
    /* Init board hardware. */
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();
    if (xTaskCreate(hello_task, "Hello_task", configMINIMAL_STACK_SIZE + 100, NULL, hello_task_PRIORITY, NULL) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }
    vTaskStartScheduler();
    for (;;)
        ;
}

static void hello_task(void *pvParameters)
{
    for (;;)
    {
        PRINTF("Hello world.\r\n");
        vTaskSuspend(NULL);
    }
}

frdm_k64f_freertos_event

  • ROM/RAM は -O0 でそれぞれ 21736 Byte / 19096 Byte
  • イベントフラグを使うサンプル
  • FreeRTOSではイベントフラグをイベントグループという
  • グローバルでイベントグループハンドラを宣言
  • main() ではhelloworldと同様の初期化
  • xEventGroupCreate() でイベントグループを作成、ヒープに確保される
  • イベントのビット数は source/FreeRTOSConfig.hconfigUSE_16_BIT_TICKS が 0 であるため 24 ビット
  • イベント書き込みタスク WRITE_TASK_1, WRITE_TASK_2, イベント読み出しタスク READ_TASK を作成
    • プライオリティは大きい方が高く READ_TASKWRITE_TASK_1, WRITE_TASK_2 より高くしている
  • 2つのイベント書き込みタスクはひたすら xEventGroupSetBits() で、それぞれビット0, ビット1を立てる
  • 読み出しタスクは xEventGroupWaitBits() でイベントを待っている
    • この関数はブロックし、戻り値でイベントビットをとれる
    • 引数はイベントグループハンドル、待受けビットマスク、ビットクリア指定、ビットマスクでしたビットのAND待ち、タイムアウトチック
    • 待受けビットマスクは B0 | B1 = 0x03 で待受け
    • ビットクリア指定は true なので、イベントが起きた後ビットはクリアされる
    • 第4引数は false なので、ビット0, 1, タイムアウトのいずれかが起きると関数は返る
    • タイムアウトは portMaxDelay = 0xffffffffUL となっているが詳細不明
  • 読み出しタスクは起きたイベントに応じてログ出力する
  • 起動するタスクは同じく、作成した3つとアイドルタスク、タイマーデーモンタスク
source/freertos_event.c抜粋
static EventGroupHandle_t event_group = NULL;

int main(void)
{
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();
    event_group = xEventGroupCreate();
    if (xTaskCreate(write_task_1, "WRITE_TASK_1", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, NULL) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }
    if (xTaskCreate(write_task_2, "WRITE_TASK_2", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, NULL) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }
    if (xTaskCreate(read_task, "READ_TASK", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 2, NULL) != pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }
    /* Start scheduling. */
    vTaskStartScheduler();
    for (;;)
        ;
}

static void write_task_1(void *pvParameters)
{
    while (1)
    {
        xEventGroupSetBits(event_group, B0);
    }
}

static void write_task_2(void *pvParameters)
{
    while (1)
    {
        xEventGroupSetBits(event_group, B1);
    }
}

static void read_task(void *pvParameters)
{
    EventBits_t event_bits;
    while (1)
    {
        event_bits = xEventGroupWaitBits(event_group,    /* The event group handle. */
                                         B0 | B1,        /* The bit pattern the event group is waiting for. */
                                         pdTRUE,         /* BIT_0 and BIT_4 will be cleared automatically. */
                                         pdFALSE,        /* Don't wait for both bits, either bit unblock task. */
                                         portMAX_DELAY); /* Block indefinitely to wait for the condition to be met. */

        if ((event_bits & (B0 | B1)) == (B0 | B1))
        {
            PRINTF("Both bits are set.");
        }
        else if ((event_bits & B0) == B0)
        {
            PRINTF("Bit B0 is set.\r\n");
        }
        else if ((event_bits & B1) == B1)
        {
            PRINTF("Bit B1 is set.\r\n");
        }
    }
}

実行ログはこのようになる

Bit B0 is set.
Bit B1 is set.
Bit B0 is set.
Bit B1 is set.
Bit B0 is set.
Bit B1 is set.
Bit B0 is set.
Bit B1 is set.
Bit B0 is set.
.
.

試しにタスクプライオリティを READ > WRITE2 > WRITE1 にしてみる。
WRITE1 はディスパッチされなくなり READWRITE2 だけで回る。

Bit B1 is set.
Bit B1 is set.
Bit B1 is set.
Bit B1 is set.
Bit B1 is set.
Bit B1 is set.
Bit B1 is set.
Bit B1 is set.
.
.

今回はここまで。

0
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
0
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?