Objective
- Understand how to use the queues with
FreeRTOS
. In this lab, the main focus will be using queues to send data among tasks. Students must create a queue to send and receive data between two tasks. Task 1 must send an integer i.e. (10
) and then modified to use a string i.e. ("Fall 2022"
). Task 2 should receive the data and print it.
Task | Description |
Task 1 | Send data to queue |
Task 2 | Receive queue data and print |
Bonus
- Undergrad Bonus:
- Modify the code to use the
structure
provided below on a queue. typedef struct {
char str[10];
int32_t val;
Undergraduate bonus.
Definition main.c:53
- Grad Bonus:
- Modify the code to use the
structure
provided below on a queue. Also, add an LED to change states based on isLedOn
. typedef struct {
char str[10];
int32_t val;
char studentName[15];
uint32_t studentID;
bool isLedOn;
Graduate bonus.
Definition main.c:63
ESP32 Pinout
+-----------------------+
| O | USB | O |
| ------- |
3V3 | [ ] [ ] | VIN
GND | [ ] [ ] | GND
Touch3 / HSPI_CS0 / ADC2_3 / GPIO15 | [ ] [ ] | GPIO13 / ADC2_4 / HSPI_ID / Touch4
CS / Touch2 / HSPI_WP / ADC2_2 / GPIO2 | [ ] [ ] | GPIO12 / ADC2_5 / HSPI_Q / Touch5
Touch0 / HSPI_HD / ADC2_0 / GPIO4 | [ ] [ ] | GPIO14 / ADC2_6 / HSPI_CLK / Touch6
U2_RXD / GPIO16 | [ ] [ ] | GPIO27 / ADC2_7 / Touch7
U2_TXD / GPIO17 | [ ] [ ] | GPIO26 / ADC2_9 / DAC2
V_SPI_CS0 / GPIO5 | [ ] ___________ [ ] | GPIO25 / ADC2_8 / DAC1
SCK / V_SPI_CLK / GPIO18 | [ ] | | [ ] | GPIO33 / ADC1_5 / Touch8 / XTAL32
U0_CTS / MSIO / V_SPI_Q / GPIO19 | [ ] | | [ ] | GPIO32 / ADC1_4 / Touch9 / XTAL32
SDA / V_SPI_HD / GPIO21 | [ ] | | [ ] | GPIO35 / ADC1_7
CLK2 / U0_RXD / GPIO3 | [ ] | | [ ] | GPIO34 / ADC1_6
CLK3 / U0_TXD / GPIO1 | [ ] | | [ ] | GPIO39 / ADC1_3 / SensVN
SCL / U0_RTS / V_SPI_WP / GPIO22 | [ ] | | [ ] | GPIO36 / ADC1_0 / SensVP
MOSI / V_SPI_WP / GPIO23 | [ ] |___________| [ ] | EN
| |
| | | ____ ____ | |
| | | | | | | | |
| |__|__| |__| |__| |
| O O |
+-----------------------+
Example 1
The following example is a quick demostration of how to use queues with FreeRTOS on the ESP32. First, a queue is created as a global variable to have the name myQueue
. Next, that variable must store an instance of a queue by xQueueCreate
function. Task 1
will send data
which stores a 10
to Task 2
every second. Task 2
will receive data through the queue and display it in the terminal.
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
QueueHandle_t myQueue;
void exampleTask1(void *pvParameters){
int data = 10;
while(1){
xQueueSendToBack(myQueue, &data, 0);
vTaskDelay(1000/portTICK_PERIOD_MS);
}
}
void exampleTask2(void *pvParameters){
int storeData;
while(1){
if(xQueueReceive(myQueue, &storeData, (TickType_t)100) == pdPASS){
printf("Data receive from task 1: %d\n", storeData);
vTaskDelay(100/portTICK_PERIOD_MS);
}
vTaskDelay(500/portTICK_PERIOD_MS);
}
}
myQueue = xQueueCreate(5, sizeof(int));
xTaskCreate(&exampleTask1, "example task 1", 2048, NULL, 4, NULL);
xTaskCreate(&exampleTask2, "example task 2", 2048, NULL, 4, NULL);
}
void app_main()
Definition main.c:261
Example 2
The following example shows how to pass an argument through a task. As mention in previous labs, xTaskCreate
has various parameters that we went briefly in detail. However, the 4th parameter is use to pass an argument to the task. In the bottom code, Task 1
receives an argument, this example may come handy when developing more advance tasks to reduce and create more abstract tasks.
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
int number = 69;
void task1(
void *pvParameters){
int data = (int)pvParameters;
while(1){
printf("Data recieved: %d\n",data);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
xTaskCreate(&
task1,
"Task 1", 2048, (
void*)number, 4, NULL);
}
void task1(void *pvParameters)
Definition main.c:43
Example 3
The following code is similar to the previous example, however, the major difference is using global
and static
variables. The static
keyword states that the variable that we create will store its data in the static memory.
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void task1(
void *pvParameters){
int data = (int)pvParameters;
while(1){
printf("Data recieved: %d\n",data);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
static int number = 420;
xTaskCreate(&
task1,
"Task 1", 2048, (
void*)number, 4, NULL);
}
Lab Template
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
typedef struct {
char str[10];
int32_t val;
typedef struct {
char str[10];
int32_t val;
char studentName[15];
uint32_t studentID;
bool isLedOn;
void task1(
void *pvParameters){
int32_t data;
while(1){
}
}
void task2(
void *pvParameters){
int32_t dataReceive;
while(1){
}
}
xQueue = xQueueCreate(5,
sizeof(int32_t));
}
}
void task2(void *pvParameters)
Definition main.c:53
QueueHandle_t xQueue
Definition main.c:72
C helpful functions
For this lab, there are few important function calls that are going to be used throughout the lab. Queues are created by using QueueHandle_t
data type. For instance, QueueHandle_t
myQueue is how you would create a queue.
First, xQueueCreate
is the function you must call if you want to create a queue. xQueueCreate
has two parameters, UBaseType_t
uxQueueLength, and UBaseType_t
uxItemSize. Therefore, if we wanted to create a queue of floats
we would do the following:
QueueHandle_t myQueue;
...
myQueue = xQueueCreate(10, sizeof(float));
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
Next, xQueueSendToBack
and xQueueSendToFront
are similar functions with the difference of how they send the data to the queue. As the name suggests, xQueueSendToBack
, sends the data to the back of the queue. Both function have three parameters, QueueHandle_t
xQueue, const void *
pvItemToQueue, TickType_t
xTicksToWait.
BaseType_t xQueueSendToBack(
const void * pvItemToQueue,
TickType_t xTicksToWait
);
BaseType_t xQueueSendToFront(
const void * pvItemToQueue,
TickType_t xTicksToWait
);
Lastly, xQueueReceive
is the opposite of xQueueSendToBack
and xQueueSendToFront
in the sense that it will store the data in void * const
pvBuffer.
BaseType_t xQueueReceive(
void *const pvBuffer,
TickType_t xTicksToWait
);
Additional Links
Authors
GitHub
Read Next: Lab 6