RTOS (Real Time Operating System) is a computer program that supports basic functions, services or applications that runs on real time environment. RTOS is not a big data size of operating system and it is not design to runs on a desktop computer / laptops class processor. The main part of the RTOS is called the scheduler this scheduler is responsible for deciding which program to run, and provides the illusion of simultaneous execution by rapidly switching between each program.
RTOS is designed to provide a predictable normally described as deterministic (NDD) execution pattern. This is mainly if interest to embedded system as embedded systems often have real time requirements. Real time requirements is one of the requirements of embedded system must respond to a certain event within a strictly defined time (deadline) an assurance to meet real time requirements can only be made if the behavior of the operating system scheduler can be predicted. Traditional real time schedulers such as scheduler used in FreeRTOS accomplish by allowing the user to assign a priority to each thread of execution. The scheduler uses the priority to know the thread of execution that runs next. In RTOS a thread of execution is named task.
FreeRTOS is a class of RTOS that designed to be small enough to runs on many microcontrollers. For more readings please refer to this link. As demonstration we will going to used FreeRTOS Queues with ESP32 Arduino Core.
RTOS Queues are mainly useful for inter-task communication, allowing you to send message from on task to another safely typically used as FIFO First In / First Out if the data is injected at the previous queue and feed at the first queue. FreeRTOS is an advance queue API, which provide more functionality. See the QUEUE API here.
Note: the more important part which is the data is inserted at the queue is copied rather than reference being stored. It means that if you send an integer value to the queue, the value will be copied and if we change the original value there will be no error should occur. However you can still insert a pointers to data as elements to the queue which is useful especially if the data to exchange are quite big. In this case the pointer will be sync and copy to the queue not the data itself, in this case we can guarantee that there is not changes.
One more important to keep in mind that the insertion in a full queue and consumption of an empty queue can be mark as made blocking calls for a specified amount of time this amount of time is parameter at the API. As an example we will insert and get the elements at the queue on the Arduino main loop function as basic API calls.
For this demonstration we will going to used ESP822 & ESP32 with Arduino Core Firmware.
Requirements
List of required module and boards |
if your using a ESP8266 or ESP32 / ESP32s / module kindly refer to the link provided
- Open source FreeRTOS-based ESP8266 Software Framework | Link
- ESP32 IDF FreeRTOS | link
- Optional (ESP32 FreeRTOS SDK) | Link
The Source Code
For this example we need additional libraries starts on global variable <QueueHandle_t> which is required for FreeRTOS queue, set as <QueueHandle_t> library and variable set as <myqueue>, then crate a queue call to the <xQueueCreate> function. The xQueueCreate function will be the first input maximum number of elements, keep in mind that each element of the queue should be the same size. The created queue can hold maximum 10 elements integer , getting the size of the integer in bytes using sizeof functions. See the sizeof function reference here.
The xQueueCreate will return as handler for the queue which is the type of <QueueHandler_t> the same variable we declared globally. if error will occur to the allocation of the queue it will return to NULL and print ERROR > Cannot create a queue.
Next is we need to start inserting the values at the queue for later use, to insert a value into the myqueue we need to call the <xQueueSend> function, which is an elements at the end of myqueue, this function will receives as first input value to the queue handle which is the global variable declared and assigned with the result of the function. For the argument the value is specified, then we will pass the value <portMAX_DELAY> it means that we will wait in case the myqueue is full. Since the queue can hold maximum of 10 elements we need to place a forloop and each iteration we insert the current value.
<xQueueReceive> follow the same loop to get the items of the queue by using <xQueueReceive> function. Then it will receive the first input of the queue. keep in mind that getting of the item it will be removed from the queue if don’t want queue will be remove you can use the xQueuePeek function. Below are the full source code.
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 |
QueueHandle_t myqueue; //a call to xQueueCreate() returns an QueueHandle_t variable that can then be used as a parameter to xQueueSend(), xQueueReceive(), etc. void setup() { Serial.begin(115200); Serial.println("14CORE | FreeRTOS Test Code"); delay(1000); Serial.println("Initializing.............."); Delay(4000); myqueue = xQueueCreate( 10, sizeof( int ) ); //See the xQueueCreate Docs if(myqueue == NULL){ Serial.println("ERROR >Cannot create a queue"); } } void loop() { if(myqueue == NULL)return; for(int i = 0; i<10; i++){ xQueueSend(myqueue, &i, portMAX_DELAY); //See the xQueueSend Docs } int myelement; for(int i = 0; i<10; i++){ xQueueReceive(myqueue, &element, portMAX_DELAY); //See the xQueueReceive Docs Serial.print(myelement); Serial.print("/"); } Serial.println(); delay(1000); } |
As you can see the at the serial communication terminal shows that the queue is inserted items being placed in each repetition of the main loop function.
The code had two errors. One Delay and the other &element. Corrected the errors with delay and &myelement.
QueueHandle_t myqueue; //a call to xQueueCreate() returns an QueueHandle_t variable that can then be used as a parameter to xQueueSend(), xQueueReceive(), etc.
void setup() {
Serial.begin(115200);
Serial.println(“14CORE | FreeRTOS Test Code”);
delay(1000);
Serial.println(“Initializing…………..”);
delay(4000);
myqueue = xQueueCreate( 10, sizeof( int ) ); //See the xQueueCreate Docs
if(myqueue == NULL){
Serial.println(“ERROR >Cannot create a queue”);
}
}
void loop() {
if(myqueue == NULL)return;
for(int i = 0; i<10; i++){
xQueueSend(myqueue, &i, portMAX_DELAY); //See the xQueueSend Docs
}
int myelement;
for(int i = 0; i<10; i++){
xQueueReceive(myqueue, &myelement, portMAX_DELAY); //See the xQueueReceive Docs
Serial.print(myelement);
Serial.print("/");
}
Serial.println();
delay(1000);
}
See the xQueueReceive Docs https://www.freertos.org/a00118.html