Seeeduino XIAOでFreeRTOSの動作確認した時のメモです。

動作環境

Seeeduino XIAO (Arudino Framework + FreeRTOS)

タスク制御

#include <Seeed_Arduino_FreeRTOS.h>

TaskHandle_t main_task_handle = NULL;
TaskHandle_t sub_task_handle = NULL;

void main_task(void *p) 
{
  for (;;)
  {
    Serial.println("main");

    // タスクを1秒間ブロック状態にする。
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
  vTaskDelete(NULL);
}

void sub_task(void *p)
{
  for (;;)
  {
    Serial.println("sub");

    // タスクを1秒間ブロック状態にする。
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
  vTaskDelete(NULL);
}

void setup() 
{
  Serial.begin(9600);
  delay(1000);

  // タスクを作成する。  
  xTaskCreate(main_task, "main", 512, NULL, tskIDLE_PRIORITY+2, &main_task_handle);
  xTaskCreate(sub_task, "sub", 512, NULL, tskIDLE_PRIORITY+1, &sub_task_handle);

  // スケジューラーを起動する。
  vTaskStartScheduler();
}

void loop() 
{
}

セマフォ

#include <Seeed_Arduino_FreeRTOS.h>

TaskHandle_t main_task_handle = NULL;
TaskHandle_t sub_task_handle = NULL;
volatile SemaphoreHandle_t sem_handle = NULL;

void main_task(void *p)
{
  for (;;)
  {
    // イベントを待機
    Serial.println("wait for event");
    xSemaphoreTake(sem_handle, portMAX_DELAY);

    Serial.println("event received");
  }
  vTaskDelete(NULL);
}

void sub_task(void *p) 
{
  for (;;)
  {
    // イベント送信
    Serial.println("event send");
    xSemaphoreGive(sem_handle);

    // タスクを5秒間ブロック状態にする。
    vTaskDelay(pdMS_TO_TICKS(5000));
  }
  vTaskDelete(NULL);
}

void setup() 
{
  Serial.begin(9600);
  delay(1000);

  // セマフォを作成する。
  sem_handle = xSemaphoreCreateBinary();

  // メイン・タスクを作成する。  
  xTaskCreate(main_task, "main", 512, NULL, tskIDLE_PRIORITY+2, &main_task_handle);
  // サブ・タスクを作成する。  
  xTaskCreate(sub_task, "sub", 512, NULL, tskIDLE_PRIORITY+1, &sub_task_handle);

  // スケジューラーを起動する。
  vTaskStartScheduler();
}

void loop() 
{
}

ミューテック・セマフォ

#include <Seeed_Arduino_FreeRTOS.h>

TaskHandle_t main_task_handle = NULL;
TaskHandle_t sub_task_handle = NULL;
SemaphoreHandle_t mutex_handle = NULL;

int shared_resource = 0;

void main_task(void *p)
{
  for (;;)
  {
    xSemaphoreTake(mutex_handle, portMAX_DELAY);
    Serial.printf("main: %d\n", shared_resource);
    shared_resource = 1;
    xSemaphoreGive(mutex_handle);
    // タスクを1秒間ブロック状態にする。
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
  vTaskDelete(NULL);
}

void sub_task(void *p) 
{
  for (;;)
  {
    xSemaphoreTake(mutex_handle, portMAX_DELAY);
    Serial.printf("sub: %d\n", shared_resource);
    shared_resource = 2;
    xSemaphoreGive(mutex_handle);
    // タスクを1秒間ブロック状態にする。
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
  vTaskDelete(NULL);
}

void setup() 
{
  Serial.begin(9600);
  delay(1000);

  // セマフォを作成する。
  mutex_handle = xSemaphoreCreateMutex();

  // メイン・タスクを作成する。  
  xTaskCreate(main_task, "main", 512, NULL, tskIDLE_PRIORITY+2, &main_task_handle);
  // サブ・タスクを作成する。  
  xTaskCreate(sub_task, "sub", 512, NULL, tskIDLE_PRIORITY+1, &sub_task_handle);

  // スケジューラーを起動する。
  vTaskStartScheduler();
}

void loop() 
{
}

メッセージ・キュー

#include <Seeed_Arduino_FreeRTOS.h>

TaskHandle_t main_task_handle = NULL;
TaskHandle_t sub_task_handle = NULL;
QueueHandle_t msg_q_handle = NULL;

const char msg[] ="HELLO!";

static void main_task(void *p) 
{
  char data[100];

  for (;;)
  {
    Serial.println("wait for queue.");
    xQueueReceive(msg_q_handle, data, portMAX_DELAY);
    Serial.printf("receive: %s\n", data);
  }
  vTaskDelete(NULL);
}

static void sub_task(void *p)
{
  for (;;)
  {
    xQueueSend(msg_q_handle, msg, portMAX_DELAY);

    // タスクを5秒間ブロック状態にする。
    vTaskDelay(pdMS_TO_TICKS(5000));
  }
  vTaskDelete(NULL);
}

void setup() 
{
  Serial.begin(9600);
  delay(1000);

  // キューを作成する。
  msg_q_handle = xQueueCreate(5, 100);

  // メイン・タスクを作成する。  
  xTaskCreate(main_task, "main", 512, NULL, tskIDLE_PRIORITY+2, &main_task_handle);
  // サブ・タスクを作成する。  
  xTaskCreate(sub_task, "sub", 512, NULL, tskIDLE_PRIORITY+1, &sub_task_handle);

  // スケジューラーを起動する。
  vTaskStartScheduler();
}

void loop() 
{
}

イベント・グループ

#include <Seeed_Arduino_FreeRTOS.h>

EventGroupHandle_t event_handle = NULL;

TaskHandle_t main_task_handle = NULL;
TaskHandle_t sub1_task_handle = NULL;
TaskHandle_t sub2_task_handle = NULL;

#define EVENT1 (1<<0)
#define EVENT2 (1<<1)

void main_task(void *p) 
{
  for (;;)
  {
    // イベントを待機する。
    Serial.println("wait for events");
    EventBits_t  events = xEventGroupWaitBits(event_handle, (EVENT1|EVENT2), pdTRUE, pdFALSE, portMAX_DELAY);

    // イベント1が発生した?
    if (events & EVENT1)
    {
      Serial.println("event1 received");
    }

    // イベント2が発生した?
    if (events & EVENT2)
    {
      Serial.println("event2 received");
    }
  }
  vTaskDelete(NULL);
}

void sub1_task(void *p) 
{
  for (;;)
  {
    // イベントを設定
    Serial.println("event1 fired");
    xEventGroupSetBits(event_handle, EVENT1);

    // タスクを1秒間ブロック状態にする。
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
  vTaskDelete(NULL);
}

void sub2_task(void *p)
{
  for (;;)
  {
    // イベントを設定
    Serial.println("event2 fired");
    xEventGroupSetBits(event_handle, EVENT2);

    // タスクを3秒間ブロック状態にする。
    vTaskDelay(pdMS_TO_TICKS(3000));
  }
  vTaskDelete(NULL);
}

void setup() 
{
  Serial.begin(9600);
  delay(1000);

  // イベントグループを作成する。
  event_handle = xEventGroupCreate();

  // メイン・タスクを作成する。  
  xTaskCreate(main_task, "main", 512, NULL, tskIDLE_PRIORITY+2, &main_task_handle);
  // サブ1・タスクを作成する。  
  xTaskCreate(sub1_task, "s1", 512, NULL, tskIDLE_PRIORITY+1, &sub1_task_handle);
  // サブ2・タスクを作成する。  
  xTaskCreate(sub2_task, "s2", 512, NULL, tskIDLE_PRIORITY+1, &sub2_task_handle);

  // スケジューラーを起動する。
  vTaskStartScheduler();
}

void loop() 
{
}

タイマー

#include <Seeed_Arduino_FreeRTOS.h>

TimerHandle_t oneshot_timer_handle = NULL;
TimerHandle_t repeat_timer_handle = NULL;

void oneshot_timer_cb(TimerHandle_t timer_handle)
{
  Serial.println("oneshot timer expired");
}

void repeat_timer_cb(TimerHandle_t timer_handle)
{
  Serial.println("repeat timer expired");
}

void setup() 
{
  Serial.begin(9600);
  delay(1000);

  // 1回のみ実行されるタイマーを作成する。
  oneshot_timer_handle = xTimerCreate("oneshot", pdMS_TO_TICKS(10*1000), pdFALSE, (void *)0, oneshot_timer_cb);
  // 繰り返し実行されるタイマーを作成する。
  repeat_timer_handle =xTimerCreate("repeat", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, repeat_timer_cb);

  // タイマーを開始する。
  xTimerStart(oneshot_timer_handle, 0);
  xTimerStart(repeat_timer_handle, 0);

  // スケジューラーを起動する。
  vTaskStartScheduler();
}

void loop() 
{
}

参考資料

前の記事 次の記事