A Bare-Metal Implementation of a Queue Module for Microcontrollers

Follow Us for More UpdatesStar Our Public Account to Not Miss Exciting Content from GitHub

Source | GitHub

When it comes to queues, many might first think of “queues” in RTOS. In fact, similar queue functionality can also be implemented in a bare-metal state. Today, I will share a module for implementing queue functionality in a bare-metal microcontroller environment: QueueForMcu

About QueueForMcu

A queue functionality module implemented based on microcontrollers, primarily used for 8-bit, 16-bit, and 32-bit microcontroller applications that do not run RTOS, compatible with most microcontroller platforms.

Open-source code: https://github.com/xiaoxinpro/QueueForMcu

1. Features

  • Dynamic creation of queue objects
  • Dynamic setting of queue data buffer
  • Static specification of queue element data length
  • Value passing method to store queue data

2. Quick Start

#include "queue.h"

#define Q_UART_BUFFER_SIZE  1024

QUEUE_HandleTypeDef qUartTx;
QUEUE_DATA_T BufferUartTx[Q_UART_BUFFER_SIZE];

int main(void)
{
  QUEUE_DATA_T temp;

  // Initialize queue
  Queue_Init(&qUartTx, BufferUartTx, Q_UART_BUFFER_SIZE);

while(1)
  {
    // Enqueue
    Queue_Push(&qUartTx, 'Q');
    Queue_Push(&qUartTx, 'u');
    Queue_Push(&qUartTx, 'e');
    Queue_Push(&qUartTx, 'u');
    Queue_Push(&qUartTx, 'e');
    
    // Dequeue
    Queue_Pop(&qUartTx, &temp);
    Queue_Pop(&qUartTx, &temp);
    Queue_Pop(&qUartTx, &temp);
    Queue_Pop(&qUartTx, &temp);
    Queue_Pop(&qUartTx, &temp);
  }
}

3. Configuration Instructions

Currently, QueueForMcu has only one static configuration item, as follows:

In the file <span>queue.h</span>, there is a macro definition <span>QUEUE_DATA_T</span> used to specify the data length of queue elements, which defaults to <span>unsigned char</span>, and can be changed to other data types as needed.

4. Data Structure

The data structure of the queue is <span>QUEUE_HandleTypeDef</span>, which is used to save the state of the queue. The source code is as follows:

typedef struct QUEUE_HandleTypeDef{
    unsigned int head;                      // Queue head pointer
    unsigned int tail;                      // Queue tail pointer
    unsigned int buffer_length;             // Queue buffer length (assigned during initialization)
    QUEUE_DATA_T * buffer;                  // Queue buffer array (assigned during initialization)
}QUEUE_HandleTypeDef;

Where <span>QUEUE_DATA_T</span> is the custom data type defined in the configuration item.

5. Creating a Queue

1. Create Queue Buffer

Since we use a value-passing method to store queue data, we need to manually create a queue buffer before creating the queue to store the queue data.

QUEUE_DATA_T BufferUartTx[1024];

The above code creates a queue buffer of size <span>1024</span>.

2. Create Queue Structure

Next, use <span>QUEUE_HandleTypeDef</span> to create a queue structure to save the state of the queue:

QUEUE_HandleTypeDef qUartTx;

3. Initialize Queue

After preparing the queue buffer and queue structure, call the <span>Queue_Init</span> function to create the queue. The function prototype is as follows:

void Queue_Init(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T * buffer, unsigned int len)

Parameter Description:

Parameter Name Description
hqueue The queue structure to be initialized. If re-initialized, the original queue content will be cleared.
buffer The pointer to the starting address of the queue buffer
len The queue length, which cannot exceed the queue buffer length.

Reference Code:

Queue_Init(&qUartTx, BufferUartTx, Q_UART_BUFFER_SIZE);

6. Enqueue

1. Single Data Enqueue

To enqueue data at the tail of the queue, use the <span>Queue_Push</span> function. The function prototype is as follows:

QUEUE_StatusTypeDef Queue_Push(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T data)

Parameter Description:

Parameter Name Description
hqueue The queue structure to which data needs to be pushed.
data The data to be pushed into the queue.

Return Value Description:

This function will return a <span>QUEUE_StatusTypeDef</span> enumeration data type, and the return value will indicate the following based on the queue status:

Return Value Description
QUEUE_OK Data successfully pushed into the queue.
QUEUE_OVERLOAD Data not pushed into the queue, reason: queue is full.

Reference Code:

Queue_Push(&qUartTx, 'Q');
Queue_Push(&qUartTx, 0x51);
Queue_Push(&qUartTx, 81);

2. Multiple Data Enqueue

If you need to push multiple data (array) into the queue, you can use the <span>Queue_Push_Array</span> function, which essentially calls the <span>Queue_Push</span> function in a loop. The function prototype is as follows:

unsigned int Queue_Push_Array(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T * pdatas, unsigned int len)

Parameter Description:

Parameter Name Description
hqueue The queue structure to which data needs to be pushed.
pdatas The starting address of the array to be pushed into the queue.
len The length of the array to be pushed into the queue.

If the array length exceeds the remaining length of the queue, the excess data will be ignored.

Return Value Description:

  • This function will return the actual length of data pushed into the queue.

  • When the remaining length in the queue is sufficient, the return value will equal the parameter <span>len</span>.

  • When the remaining length in the queue is insufficient, the return value will be the actual length of data pushed into the queue.

7. Dequeue

1. Single Data Dequeue

To dequeue data from the head of the queue, use the <span>Queue_Pop</span> function. Note that the dequeued data will be removed from the queue. The function prototype is as follows:

QUEUE_StatusTypeDef Queue_Pop(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T * pdata)

Parameter Description:

Parameter Name Description
hqueue The queue structure from which data needs to be popped.
pdata A pointer to save the popped data variable.

Return Value Description:

This function will return a <span>QUEUE_StatusTypeDef</span> enumeration data type, and the return value will indicate the following based on the queue status:

Return Value Description
QUEUE_OK Data successfully popped from the queue.
QUEUE_VOID No data popped from the queue, reason: queue is empty.

Reference Code:

QUEUE_DATA_T temp;
if(QUEUE_OK == Queue_Pop(&qUartTx, &temp))
{
    // temp contains the data popped from the queue
}
else
{
    // Failed to pop data
}

2. Multiple Data Dequeue

If you need to pop multiple data from the queue, you can use the <span>Queue_Pop_Array</span> function, which essentially calls the <span>Queue_Pop</span> function in a loop. Note that successfully popped data will be removed from the queue. The function prototype is as follows:

unsigned int Queue_Pop_Array(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T * pdatas, unsigned int len)

Parameter Description:

Parameter Name Description
hqueue The queue structure from which data needs to be popped.
pdatas The starting address of the array to save popped data.
len The length of the array for popping data.

If the length of data to be popped exceeds the data length in the queue, the excess space in the array will not be assigned.

Return Value Description:

  • This function will return the actual length of data popped from the queue.

  • When the data length in the queue is sufficient, the return value will equal the parameter <span>len</span>.

  • When the data length in the queue is insufficient, the return value will be the actual length of data popped from the queue.

3. Single Data Peek

If you need to get data from the head of the queue without removing it, you can use the <span>Queue_Peek</span> function, which has the same parameters and return values as <span>Queue_Pop</span>.

The difference between using <span>Queue_Peek</span> and <span>Queue_Pop</span> is:

  • <span>Queue_Pop</span> removes the data from the queue after retrieving it.
  • <span>Queue_Peek</span> retains the data in the queue after retrieving it.

4. Multiple Data Peek

If you need to get multiple data from the head of the queue without removing them, you can use the <span>Queue_Peek_Array</span> function, which has the same parameters and return values as <span>Queue_Pop_Array</span>.

The difference between using <span>Queue_Peek_Array</span> and <span>Queue_Pop_Array</span> is:

  • <span>Queue_Pop_Array</span> removes the data from the queue after retrieving it.
  • <span>Queue_Peek_Array</span> retains the data in the queue after retrieving it.

8. Other Functions

1. Clear Queue

When you need to clear the queue data, there is no need to pop all data; just call <span>Queue_Clear</span> to quickly clear the specified queue. This function is called during queue creation to initialize the queue, so there is no need to call the clear queue function for a newly created queue.

Function Prototype:

void Queue_Clear(QUEUE_HandleTypeDef * hqueue)

Parameter Description:

Parameter Name Description
hqueue The queue structure to be cleared.

2. Get Queue Data Count

When you need to get the data length in the queue, call the <span>Queue_Count</span> function. The function prototype is as follows:

unsigned int Queue_Count(QUEUE_HandleTypeDef * hqueue)

Parameter Description:

Parameter Name Description
hqueue The queue structure from which to get the data length.

Return Value Description:

  • This function will return the data length in the queue.
  • The return value range is between 0 and the length at which the queue was created.

License

Copyright © 2020 QueueForMcu Released under the GPL-3.0 License.

Disclaimer: The materials in this article are sourced from the internet, and the copyright belongs to the original author. If there are any copyright issues, please contact me for removal.———— END ————A Bare-Metal Implementation of a Queue Module for Microcontrollers● Column “Embedded Tools”● Column “Embedded Development”● Column “Keil Tutorials”● Selected Tutorials in Embedded ColumnFollow our public accountReply “Add Group” to join the technical exchange group according to the rules, reply “1024” to see more content.Click “Read Original” to see more shares.

Leave a Comment