2018년 7월 2일 월요일

ESP32에서 FreeRTOS 사용 - Message Queue 사용하기

FreeRTOS에서

- Queue는 태스크 간 교환되는 데이터/메시지를저장하는데 사용
- 데이터는 queue에 카피됨 (포인터로 참조되는게 아님)
- 여러 태스크가 억세스 할 수 있음
- Queue Read는 blocking 동작 (큐에 데이터가 없으면 데이터를 기다리기 위해 태스크는 blocked 상태가 됨)
- Queue Write는 blocking 동작 (큐에 빈 공간이 없으면 빈 공간이 생기는걸 기디리기 위해 태스크는 blocked 상태가 됨)
- mulitple queue에 대해 blocking 동작 (큐 그룹에 데이터가 들어오는걸 기다리기 위해 태스크는 blocked 상태가 됨)

* 데모
이 데모에서는 3개의 태스크를 만드는데, 2개의 태스크는 sending 태스크이고 1개는 receiving 태스크이다. sending 태스크는 sender id와 태스크의 카운트 값을 가지고 있는 데이터를 보낸다.

// structure that hold data
typedef struct{
  int sender;
  int counter;
}Data;

// this variable hold queue handle 
xQueueHandle xQueue;

void setup() {
  Serial.begin(115200);
  // create the queue which size can contains 5 elements of Data
  xQueue = xQueueCreate(5, sizeof(Data));
  xTaskCreate(
      sendTask1,     // Task function. 
      "sendTask1",   // name of task. 
      10000,         // Stack size of task 
      NULL,          // parameter of the task 
      2,             // priority of the task 
      NULL);         // Task handle to keep track of created task 
  xTaskCreate(
      sendTask2,     // Task function. 
      "sendTask2",   // name of task. 
      10000,         // Stack size of task 
      NULL,          // parameter of the task 
      2,             // priority of the task 
      NULL);         // Task handle to keep track of created task 
  xTaskCreate(
      receiveTask,   // Task function. 
      "receiveTask", // name of task. 
      10000,         // Stack size of task 
      NULL,          // parameter of the task 
      1,             // priority of the task 
      NULL);         // Task handle to keep track of created task 
}

void loop() {
}

void sendTask1( void * parameter )
{ 
  BaseType_t xStatus;   // keep the status of sending data 
  // time to block the task until the queue has free space 
  const TickType_t xTicksToWait = pdMS_TO_TICKS(100);
  Data data;    // create data to send 
  data.sender = 1;   // sender 1 has id is 1
  data.counter = 1;
  for(;;){
    Serial.println("sendTask1 is sending data");
    // send data to front of the queue 
    xStatus = xQueueSendToFront( xQueue, &data, xTicksToWait );
    // check whether sending is ok or not 
    if( xStatus == pdPASS ) {   // increase counter of sender
      data.counter = data.counter + 1;
    }
    // we delay here so that receiveTask has chance to receive data
    delay(1000);
  }
  vTaskDelete( NULL );
}
 
// this task is similar to sendTask1 
void sendTask2( void * parameter )
{
  BaseType_t xStatus;
  const TickType_t xTicksToWait = pdMS_TO_TICKS(100);
  Data data;
  data.sender = 2;
  data.counter = 1;
  for(;;){
    Serial.println("sendTask2 is sending data");
    xStatus = xQueueSendToFront( xQueue, &data, xTicksToWait );
    if( xStatus == pdPASS ) {
      data.counter = data.counter + 1;
    }
    delay(1000);
  }
  vTaskDelete( NULL );
}
 
void receiveTask( void * parameter )
{
  BaseType_t xStatus;   // keep the status of receiving data 
  // time to block the task until data is available 
  const TickType_t xTicksToWait = pdMS_TO_TICKS(100);
  Data data;
  while (1) {        // receive data from the queue
    xStatus = xQueueReceive( xQueue, &data, xTicksToWait );
    if(xStatus == pdPASS){     // check whether receiving is ok or not 
      // print the data to terminal 
      Serial.print("receiveTask got data: ");
      Serial.print("sender = ");
      Serial.print(data.sender);
      Serial.print(" counter = ");
      Serial.println(data.counter);
    }
  }
  vTaskDelete( NULL );
} 
 
 
 
 
 

댓글 없음:

댓글 쓰기