FreeRTOS Queue Tutorial Using LPC2148

This article is a continuation of the  Series on FreeRTOS and carries the discussion on FreeRTOS and its usage. The aim of this series is to provide easy and practical examples that anyone can understand. In this tutorial, we are going to discuss about the FreeRTOS Queue Tutorial Using LPC2148.

You can also read the task creation, semaphore, and mutex tutorials.

Suggestion to read

FreeRTOS Queue Tutorial Using LPC2148

Introduction – FreeRTOS Queue

Queues are the primary form of intertask communications. They can be used to send messages between tasks, and between interrupts and tasks. In most cases, they have used thread-safe FIFO (First In First Out) buffers with new data being sent to the back of the queue, as well as the data can also be sent to the front.

Writing to and reading from a queue. In this example, the queue was created to hold 5 items, and the queue never becomes full.

When a task attempts to read from an empty queue, the task will be placed into the Blocked state (so it is not consuming any CPU time and other tasks can run) until either data becomes available on the queue, or the block time expires.

When a task attempts to write to a full queue, the task will be placed into the Blocked state (so it is not consuming any CPU time and other tasks can run) until either space becomes available in the queue, or the block time expires.

in the FreeRTOS queue, if more than one task has been blocked on the same queue, then the task with the highest priority will be unblocked first.

APIs Used

  • xQueueCreate()
  • vQueueDelete()
  • xQueuePeek()
  • xQueuePeekFromISR()
  • xQueueReceive()
  • xQueueReceiveFromISR()
  • xQueueSend()
  • xQueueSendToFront()
  • xQueueSendToBack()
  • xQueueSendFromISR()
  • xQueueSendToBackFromISR()
  • xQueueSendToFrontFromISR()

Now we will see one by one APIs.

xQueueCreate()

This API is used to create the queue.

#include “FreeRTOS.h”
#include “queue.h”

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength,UBaseType_t uxItemSize );

This API creates a new queue and returns a handle. The handle can be used to reference the queue.

Each queue requires RAM that is used to hold the queue state, and to hold the items that are contained in the queue (the queue storage area). If a queue is created using xQueueCreate(), then the required RAM is automatically allocated from the FreeRTOS heap.

Parameters

  • uxQueueLength: The maximum number of items that the queue being created can hold at any one time.
  • uxItemSize : The size, in bytes, of each data item that can be stored in the queue.

Return Values

  • NULL The queue cannot be created because there is insufficient heap memory available for FreeRTOS to allocate the queue data structures and storage area.
  • Any other value, the queue was created successfully. The returned value is a handle by which the created queue can be referenced.

Queues can be created before or after the scheduler has been started.

vQueueDelete()

This API is used to delete a queue that was previously created using a call to xQueueCreate()vQueueDelete() can also be used to delete a semaphore.

#include “FreeRTOS.h”
#include “queue.h”

void vQueueDelete( TaskHandle_t pxQueueToDelete );

Parameters

  • pxQueueToDelete: The handle of the queue has to be deleted. Semaphore handles can also be used.

Return Values

  • None

Note:

A queue/semaphore must not be deleted if there are any tasks currently blocked on it.

xQueuePeek()

This API reads an item from a queue without removing it from the queue.

#include “FreeRTOS.h”
#include “queue.h”

BaseType_t xQueuePeek( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );

Parameters

  • xQueue : The handle of the queue from which data is to be read.
  • pvBuffer : A pointer to the memory into which the data read from the queue will be copied. The length of the buffer must be at least equal to the queue item size. The item size will have been set by the uxItemSize parameter of the call to xQueueCreate() used to create the queue.
  • xTicksToWait : The maximum amount of time the task should remain in the Blocked state to wait for data to become available on the queue, should the queue already be empty. If xTicksToWait is zero, then xQueuePeek() will return immediately if the queue is already empty.

Return Values

  • pdPASS : Returned if data was successfully read from the queue. If a block time was specified (xTicksToWait was not zero), then it is possible that the calling task was placed into the Blocked state, to wait for data to become available on the queue, but data was successfully read from the queue before the block time expired.
  • errQUEUE_EMPTY : Returned if data cannot be read from the queue because the queue is already empty. If a block time was specified (xTicksToWait was not zero) then the calling task will have been placed into the Blocked state to wait for another task or interrupt to send data to the queue, but the block time expired before this happened.

xQueuePeekFromISR()

This is another version of xQueuePeek() that can be used from an interrupt service routine (ISR).

This API reads an item (in ISR) from a queue without removing it from the queue.

#include “FreeRTOS.h”
#include “queue.h”

BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void *pvBuffer );

Parameters

  • xQueue : The handle of the queue from which data is to be read.
  • pvBuffer : A pointer to the memory into which the data read from the queue will be copied. The length of the buffer must be at least equal to the queue item size. The item size will have been set by the uxItemSize parameter of the call to xQueueCreate() used to create the queue.

Return Values

  • pdPASS : Returned if data was successfully read from the queue.
  • errQUEUE_EMPTY : Returned if data cannot be read from the queue because the queue is already empty.

xQueueReceive()

This API used to receive (read) an item from a queue.

#include “FreeRTOS.h”
#include “queue.h”

BaseType_t xQueueReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );

Parameters

  • xQueue : The handle of the queue from which the data is being received (read).
  • pvBuffer : A pointer to the memory into which the received data will be copied. The length of the buffer must be at least equal to the queue item size. The item size will have been set by the uxItemSize parameter of the call to xQueueCreate() used to create the queue.
  • xTicksToWait: The maximum amount of time the task should remain in the Blocked state to wait for data to become available on the queue, should the queue already be empty. If xTicksToWait is zero, then xQueueReceive() will return immediately if the queue is already empty. If INCLUDE_vTaskSuspend is set to ‘1’ then specifying the block time as portMAX_DELAY will cause the task to block indefinitely (without a timeout).

Return Values

  • pdPASS : Returned if data was successfully read from the queue. If a block time was specified (xTicksToWait was not zero), then it is possible that the calling task was placed into the Blocked state, to wait for data to become available on the queue, but data was successfully read from the queue before the block time expired.
  • errQUEUE_EMPTY : Returned if data cannot be read from the queue because the queue is already empty.

xQueueReceiveFromISR()

This is another version of xQueueReceive() that can be called from an ISR. Unlike xQueueReceive(), xQueueReceiveFromISR() does not permit a block time to be specified.

#include “FreeRTOS.h”
#include “queue.h”

BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken );

Parameters

  • xQueue : The handle of the queue from which the data is being received (read).
  • pvBuffer: A pointer to the memory into which the received data will be copied. The length of the buffer must be at least equal to the queue item size. The item size will have been set by the uxItemSize parameter of the call to xQueueCreate() used to create the queue.
  • pxHigherPriorityTaskWoken: A task may be blocked waiting for space to become available on the queue. If xQueueReceiveFromISR causes such a task to unblock *pxHigherPriorityTaskWoken will get set to pdTRUE, otherwise *pxHigherPriorityTaskWoken will remain unchanged. From FreeRTOS V7.3.0 pxHigherPriorityTaskWoken is an optional parameter and can be set to NULL.

Return Values

  • pdPASS: Data was successfully received from the queue.
  • pdFAIL: Data was not received from the queue because the queue was already empty.

Notes

Calling xQueueReceiveFromISR() within an interrupt service routine can potentially cause a task that was blocked on a queue to leave the Blocked state. A context switch should be performed if such an unblocked task has a priority higher than or equal to the currently executing task (the task that was interrupted). The context switch will ensure that the interrupt returns directly to the highest priority Ready state task. Unlike the xQueueReceive() API function, xQueueReceiveFromISR() will not itself perform a context switch. It will instead just indicate whether or not a context switch is required. xQueueReceiveFromISR() must not be called prior to the scheduler being started. Therefore an interrupt that calls xQueueReceiveFromISR() must not be allowed to execute prior to the scheduler being started.

xQueueSend(), xQueueSendToFront(), xQueueSendToBack()

It is used to send (writes) an item to the front or the back of a queue.

xQueueSend() and xQueueSendToBack() perform the same operation so are equivalent. Both send data to the back of a queue.

xQueueSend() was the original version, and it is now recommended to use xQueueSendToBack() in its place.

#include “FreeRTOS.h”
#include “queue.h”

BaseType_t xQueueSend( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );

BaseType_t xQueueSendToFront( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );

BaseType_t xQueueSendToBack( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );

Parameters

  • xQueue: The handle of the queue to which the data is being sent (written).
  • pvItemToQueue : A pointer to the data to be copied into the queue. The size of each item the queue can hold is set when the queue is created, and that many bytes will be copied from pvItemToQueue into the queue storage area.
  • xTicksToWait : The maximum amount of time the task should remain in the Blocked state to wait for space to become available on the queue, should the queue already be full. xQueueSend(), xQueueSendToFront() and xQueueSendToBack() will return immediately if xTicksToWait is zero and the queue is already full. If INCLUDE_vTaskSuspend is set to ‘1’ then specifying the block time as portMAX_DELAY will cause the task to block indefinitely (without a timeout).

Return Values

  • pdPASS : Returned if data was successfully sent to the queue. If a block time was specified (xTicksToWait was not zero), then it is possible that the calling task was placed into the Blocked state, to wait for space to become available in the queue before the function returned, but data was successfully written to the queue before the block time expired.
  • errQUEUE_FULL : Returned if data could not be written to the queue because the queue was already full. If a block time was specified (xTicksToWait was not zero) then the calling task will have been placed into the Blocked state to wait for another task or interrupt to make room in the queue, but the specified block time expired before that happened.

xQueueSendFromISR(), xQueueSendToBackFromISR(), xQueueSendToFrontFromISR()

This is another versions of the xQueueSend(), xQueueSendToFront() and xQueueSendToBack() API functions that can be called from an ISR. Unlike xQueueSend(), xQueueSendToFront() and xQueueSendToBack(), the ISR safe versions do not permit a block time to be specified. xQueueSendFromISR() and xQueueSendToBackFromISR() perform the same operation so are equivalent. Both send data to the back of a queue. xQueueSendFromISR() was the original version and it is now recommended to use xQueueSendToBackFromISR() in its place.

#include “FreeRTOS.h”
#include “queue.h”

BaseType_t xQueueSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue,
BaseType_t *pxHigherPriorityTaskWoken );

BaseType_t xQueueSendToBackFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken );

BaseType_t xQueueSendToFrontFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken );

Parameters

xQueue: The handle of the queue to which the data is being sent (written). The queue handle will have been returned from the call to xQueueCreate()  used to create the queue.

pvItemToQueue : A pointer to the data to be copied into the queue. The size of each item the queue can hold is set when the queue is created, and that many bytes will be copied from pvItemToQueue into the queue storage area.

pxHigherPriorityTaskWoken : xQueueSendFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task to unblock, and the unblocked task has a priority higher than the currently running task. If xQueueSendFromISR() sets this value to pdTRUE then a context switch should be requested before the interrupt is exited.

From FreeRTOS V7.3.0 pxHigherPriorityTaskWoken is an optional parameter and can be set to NULL.

Return Values

  • pdTRUE : Data was successfully sent to the queue.
  • errQUEUE_FULL: Data could not be sent to the queue because the queue was already full.

FreeRTOS Queue Tutorial Using LPC2148 – Code

Here I’ve created two tasks.

  1. Sender
  2. Receiver

The sender task will be sending data continuously to the queue. The receiver task always waiting for a queue. If that queue contains any data, the receiver task reads that data and prints it in the serial terminal. Go through the below code. Then you will understand easily. This is only the main code. If you want to download the full project please visit here.

#include<stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#include "uart0.h"
#include "queue.h"
#include "semphr.h"

void sender(void *u);
void readqueue(void *p);

xQueueHandle myqueue;

int main()
{
	initserial();
	
	myqueue=xQueueCreate(11,sizeof(char));
	
	if(myqueue!=NULL) {
		xTaskCreate(sender,"sender",128,NULL,1,NULL);
		xTaskCreate(readqueue,"read",128,NULL,1,NULL);
		vTaskStartScheduler();
	}
}

void sender(void *u)
{
	portBASE_TYPE qstatus;
	unsigned char dat[]="EmbeTronicX",i;
	while(1) {
			for(i=0;i<11;i++)   
				qstatus=xQueueSendToBack(myqueue,&dat[i],0);
		
			if(qstatus!=pdPASS) {
				sendsserial("\r\n");
				vTaskDelay(10);
			}
  }
}

void readqueue(void *p)
{
	unsigned char receivedValue;
	portBASE_TYPE xStatus;
	
	while(1) {
		xStatus = xQueueReceive(myqueue,&receivedValue,100);
    if( xStatus == pdPASS ) {
			 sendserial(receivedValue);
		 }
	}
}

FreeRTOS Queue – Output

[Download the FreeRTOS Queue project Here]

You can also read the task creation, semaphore, and mutex tutorials. In our next tutorial, we will interface both LED and LCD with LPC2148 using the FreeRTOS.

You can also read the below tutorials.

Linux Device Driver TutorialsC Programming Tutorials
FreeRTOS TutorialsNuttX RTOS Tutorials
RTX RTOS TutorialsInterrupts Basics
I2C Protocol – Part 1 (Basics)I2C Protocol – Part 2 (Advanced Topics)
STM32 TutorialsLPC2148 (ARM7) Tutorials
PIC16F877A Tutorials8051 Tutorials
Unit Testing in C TutorialsESP32-IDF Tutorials
Raspberry Pi TutorialsEmbedded Interview Topics
Reset Sequence in ARM Cortex-M4BLE Basics
VIC and NVIC in ARMSPI – Serial Peripheral Interface Protocol
STM32F7 Bootloader TutorialsRaspberry PI Pico Tutorials
STM32F103 Bootloader TutorialsRT-Thread RTOS Tutorials
Zephyr RTOS Tutorials - STM32Zephyr RTOS Tutorials - ESP32
AUTOSAR TutorialsUDS Protocol Tutorials
Product ReviewsSTM32 MikroC Bootloader Tutorial
VHDL Tutorials
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Table of Contents