
Queue Set은 하나의 Task가 여러 개의 Queue로부터 데이터를 받을 수 있게 해주는데, 이때 Task가 일일이 각 Queue을 확인(polling)하지 않아도 된다.
Queue Set에 속한 Queue 중 하나가 데이터를 받으면, 그 Queue의 handle이 Queue Set으로 전달된다. Task가 Queue Set을 읽으면, 해당 Queue의 Handle이 반환되고, 그 Handle을 통해 어떤 Queue에 데이터가 들어왔는지를 알 수 있다. 그러면 Task는 반환된 Handle이 가리키는 Queue에서 직접 데이터를 읽으면 된다.
여러 Producer Task가 각자 다른 Queue로 메시지를 보낼 때, Consumer Task가 Queue Set을 사용하면 폴링 없이 어느 Queue에 데이터가 도착했는지를 한번에 감지하고 처리할 수 있다. 본 블로그에서 다룰 코드는 두 개의 Sender Task와 하나의 Receiver Task가 Queue Set으로 협업하는 예제이다.
① 예제 개요
xQueue1에 100 ms 주기로 문자열 포인터 전송xQueue2에 200 ms 주기로 문자열 포인터 전송xQueueSet을 블록(대기)하여 감시 → 어느 Queue든, 데이터가 생기면 해당 Queue Handle을 받아 그 Queue에서 곧바로 xQueueReceive()로 읽고, Serial 출력② Queue와 Queue Set 만들기
xQueue1 = xQueueCreate(1, sizeof(char *));
xQueue2 = xQueueCreate(1, sizeof(char *));
xQueueSet = xQueueCreateSet(1 * 2); // 각 큐 길이(1) 합계만큼
xQueueAddToSet(xQueue1, xQueueSet);
xQueueAddToSet(xQueue2, xQueueSet);
Queue Set의 크기는 멤버 Queues의 길이 합 이상이어야 한다. 여기서는 1+1=2이다.
③ Senders
// Sender 1: 100ms 주기
vTaskDelay(pdMS_TO_TICKS(100));
xQueueSend(xQueue1, &messageToSend, 0);
// Sender 2: 200ms 주기
vTaskDelay(pdMS_TO_TICKS(200));
xQueueSend(xQueue2, &messageToSend, 0);
④ Receiver
QueueHandle_t xQueueThatContainsData =
(QueueHandle_t) xQueueSelectFromSet(xQueueSet, portMAX_DELAY);
xQueueReceive(xQueueThatContainsData, &pcReceivedString, 0);
Serial.println(pcReceivedString)
xQueueSelectFromSet()이 데이터가 있는 Queue의 Handle을 반환한다.xQueueReceive()를 호출해 메시지를 꺼내고, 시리얼로 출력⑤ 전체 코드
#include <Arduino_FreeRTOS.h>
#include "queue.h"
#define RED 6
#define YELLOW 7
#define BLUE 8
QueueHandle_t xQueue1;
QueueHandle_t xQueue2;
QueueSetHandle_t xQueueSet;
void setup()
{
pinMode(BLUE,OUTPUT);
Serial.begin(9600);
xQueue1 = xQueueCreate(1,sizeof(char *));
xQueue2 = xQueueCreate(1,sizeof(char *));
xQueueSet= xQueueCreateSet(1*2);
xQueueAddToSet(xQueue1,xQueueSet);
xQueueAddToSet(xQueue2,xQueueSet);
xTaskCreate(vSenderTask1,"Sender Task 1 ", 100,NULL,1,NULL );
xTaskCreate(vSenderTask2, "Sender Task 2 ",100,NULL,1,NULL);
xTaskCreate(vReceiverTask,"Receiver Task", 100,NULL,2,NULL);
}
void vSenderTask1 (void *pvParameters)
{
const TickType_t xBlockTime = pdMS_TO_TICKS(100);
const char * const messageToSend = " Message from Sender 1 ";
while(1)
{
vTaskDelay(xBlockTime);
xQueueSend(xQueue1,&messageToSend,0);
}
}
void vSenderTask2(void *pvParameters)
{
const TickType_t xBlockTime = pdMS_TO_TICKS(200);
const char * const messageToSend = "Hello from Sender 2 ";
while(1)
{
vTaskDelay(xBlockTime);
xQueueSend(xQueue2,&messageToSend,0);
}
}
void vReceiverTask(void *pvParameters)
{
QueueHandle_t xQueueThatContainsData;
char *pcReceivedString;
while(1)
{
xQueueThatContainsData = (QueueHandle_t)xQueueSelectFromSet(xQueueSet,portMAX_DELAY);
xQueueReceive(xQueueThatContainsData,&pcReceivedString,0);
Serial.println(pcReceivedString);
}
}
void loop(){}