Wednesday, June 14, 2017

Arduino ESP32 FreeRTOS 3: How to use Message Queue

1. Introduction
- A queue is a First In First Out (FIFO) buffer.
- In FreeRTOS:
+ Queue is used to stored data/message that is exchanged among tasks.
+ Data will be copied (not reference) to queue.
+ Access by Multiple Tasks
+ Blocking on Queue Reads (a task moves to Blocked state to wait for data)
+ Blocking on Queue Writes (a task moves to Blocked state to wait until free space is available on the queue)
+ Blocking on Multiple Queues (a task moves to Blocked state to wait for data on a group of queues).
2. Demo
In this demo, we will create 3 tasks, 2 sending tasks and 1 receiving task. Sending task will send data that contains sender id and its counter.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
/* structure that hold data*/
typedef struct{
  int sender;
  int counter;
}Data;

/* this variable hold queue handle */
xQueueHandle xQueue;

void setup() {

  Serial.begin(112500);
  /* 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 )
{
  /* keep the status of sending data */
  BaseType_t xStatus;
  /* time to block the task until the queue has free space */
  const TickType_t xTicksToWait = pdMS_TO_TICKS(100);
  /* create data to send */
  Data data;
  /* sender 1 has id is 1 */
  data.sender = 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 1 */
      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 )
{
  /* keep the status of receiving data */
  BaseType_t xStatus;
  /* time to block the task until data is available */
  const TickType_t xTicksToWait = pdMS_TO_TICKS(100);
  Data data;
  for(;;){
    /* receive data from the queue */
    xStatus = xQueueReceive( xQueue, &data, xTicksToWait );
    /* check whether receiving is ok or not */
    if(xStatus == pdPASS){
      /* 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 );
}
3. Result
Figure: demo using Queue

3 comments:

Unknown said...
This comment has been removed by the author.
RudolfAtITD said...

I'm learning to use FreeRTOS on the ESP32. This is a good example of using queus. While a queue should normally be a FIFO, you should use "xQueueSendToBack (...)".

Mirnalini Sathya said...

Very useful information on Data Structures, definitely it helps us to protect our site from copied content, if you are Looking for software courses?


German Classes in Chennai
Big Data Training in Chennai
Android Training in Chennai
Selenium Training in Chennai
Digital Marketing Training in Chennai
Qtp training in Chennai
QTP Training in Porur