Queue Sets

hyeony·2025년 8월 31일

RTOS

목록 보기
7/8

1. Introduction to Queue Sets

Queue Set은 하나의 Task가 여러 개의 Queue로부터 데이터를 받을 수 있게 해주는데, 이때 Task가 일일이 각 Queue을 확인(polling)하지 않아도 된다.

Queue Set에 속한 Queue 중 하나가 데이터를 받으면, 그 Queue의 handle이 Queue Set으로 전달된다. Task가 Queue Set을 읽으면, 해당 Queue의 Handle이 반환되고, 그 Handle을 통해 어떤 Queue에 데이터가 들어왔는지를 알 수 있다. 그러면 Task는 반환된 Handle이 가리키는 Queue에서 직접 데이터를 읽으면 된다.

2. Code Implementation

여러 Producer Task가 각자 다른 Queue로 메시지를 보낼 때, Consumer TaskQueue Set을 사용하면 폴링 없이 어느 Queue에 데이터가 도착했는지를 한번에 감지하고 처리할 수 있다. 본 블로그에서 다룰 코드는 두 개의 Sender Task와 하나의 Receiver TaskQueue Set으로 협업하는 예제이다.

① 예제 개요

  • Sender 1xQueue1에 100 ms 주기로 문자열 포인터 전송
  • Sender 2xQueue2에 200 ms 주기로 문자열 포인터 전송
  • ReceiverxQueueSet을 블록(대기)하여 감시 → 어느 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을 반환한다.
  • 반환된 Queue에서 곧바로 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(){}

<참고 자료>
https://www.udemy.com/course/arduino-freertos/

profile
Chung-Ang Univ. EEE.

0개의 댓글