|

楼主 |
发表于 2024-10-24 23:18:54
|
显示全部楼层
本帖最后由 LY_Bear 于 2024-10-26 12:30 编辑
今天把完善后的代码公布出来,以供审阅与使用。
---------------------------------------------------------------更新---------------------------------------------------------------
1、增加在3个注释标记为 (DMA use) 的接口,用于DMA对队列的连续写入和空闲中断回调函数中对于头尾索引的维护。
2、移除Pop和Push接口,增加PopN和PushN接口,减少函数调用次数,并优化了入口错误判断。
-----------------------------------------------------以下分别为.h与.c文件-----------------------------------------------------
.H文件
#ifndef __RING_QUEUE_H__
#define __RING_QUEUE_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*---------------------------------Inc----------------------------------*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
/*---------------------------------Define--------------------------------*/
/*---------------------------------Typedef--------------------------------*/
typedef uint16_t rqcType_t; // ring queue control member type
typedef void *ringQueue_t; // ring queue type, private data type
/* ring queue interface */
typedef struct _RING_QUEUE_INTERFACE
{
void *(*init)(rqcType_t n); // initialize the ring queue
rqcType_t (*pushN)(void *rqueue, uint8_t *buffer, rqcType_t n); // push an element into the queue
rqcType_t (*popN)(void *rqueue, uint8_t *buffer, rqcType_t n); // pop an element from the queue
bool (*updateHead)(void *rqueue, rqcType_t num); // (DMA use) update the head index
bool (*updateTail)(void *rqueue, rqcType_t num); // (DMA use) update the tail index
uint8_t *(*getHeadPointer)(const void *rqueue); // (DMA use) get the head pointer
bool (*isEmpty)(const void *rqueue); // check if the queue is empty
bool (*isFull)(const void *rqueue); // check if the queue is full
bool (*peekHead)(const void *rqueue, uint8_t *value); // peek the head element
bool (*peekTail)(const void *rqueue, uint8_t *value); // peek the tail element
rqcType_t (*getSize)(const void *rqueue); // get the size of the queue
rqcType_t (*getCount)(const void *rqueue); // gets the number of existing members of the queue.
void (*clear)(void *rqueue); // clear the queue
void (*deInit)(void *rqueue); // de-initialize the ring queue
} ringQueueInterface_ts;
/*---------------------------------Interface--------------------------------*/
/* 向外提供接口组件,.c文件中已全部实现 */
extern const ringQueueInterface_ts rqInterface;
/*-----------------------------------Macro----------------------------------*/
/* 安全释放宏 */
#define rqSafeDeInit(rqueue) \
do \
{ \
rqInterface.deInit(rqueue); \
rqueue = NULL; \
} while (0)
/*-----------------------------------Test----------------------------------*/
/* 测试用例 */
// void testringQueue(void) {
// ringQueue_t uart1_rq = rqInterface.init(128);
// for (int i = 0; i < 127; i++) {
// rqInterface.pushN(uart1_rq, &i, 1);
// }
// rqcType_t temp = rqInterface.getSize(uart1_rq);
// temp = rqInterface.getCount(uart1_rq);
// uint8_t *rq_ptr = rqInterface.getHeadPointer(uart1_rq);
// uint8_t value = 0;
// value = rq_ptr[2];
// rq_ptr = NULL;
// rqInterface.peekHead(uart1_rq, &value);
// rqInterface.peekTail(uart1_rq, &value);
// for (int i = 0; i < 127; i++) {
// rqInterface.popN(uart1_rq, &value, 1);
// }
// rqInterface.clear(uart1_rq);
// rqSafeDeInit(uart1_rq);
// }
#ifdef __cplusplus
}
#endif
#endif // !__ring_QUEUE_H__
C文件
/*---------------------------------Inc----------------------------------*/
#include "ringqueue.h"
/*---------------------------------Define--------------------------------*/
/*---------------------------------Typedef--------------------------------*/
typedef struct _RING_QUEUE_DATA
{
uint8_t *queue; // data pointer
rqcType_t head; // head index
rqcType_t tail; // tail index
rqcType_t size; // queue size
rqcType_t count; // queue counter
} ringQueueData_ts;
/*---------------------------------Declaration--------------------------------*/
void *rqInit(rqcType_t n);
rqcType_t rqPushN(void *rqueue, uint8_t *buffer, rqcType_t n);
rqcType_t rqPopN(void *rqueue, uint8_t *buffer, rqcType_t n);
bool rqUpdateHead(void *rqueue, rqcType_t num);
bool rqUpdateTail(void *rqueue, rqcType_t num);
uint8_t *rqGetHeadPointer(const void *rqueue); // get the head pointer
bool rqIsEmpty(const void *rqueue);
bool rqIsFull(const void *rqueue);
bool rqPeekHead(const void *rqueue, uint8_t *value);
bool rqPeekTail(const void *rqueue, uint8_t *value);
rqcType_t rqGetSize(const void *rqueue);
rqcType_t rqGetCount(const void *rqueue);
void rqClear(void *rqueue);
void rqDeInit(void *rqueue);
/*---------------------------------Global--------------------------------*/
const ringQueueInterface_ts rqInterface = {.init = rqInit,
.pushN = rqPushN,
.popN = rqPopN,
.getHeadPointer = rqGetHeadPointer,
.updateHead = rqUpdateHead,
.updateTail = rqUpdateTail,
.isEmpty = rqIsEmpty,
.isFull = rqIsFull,
.peekHead = rqPeekHead,
.peekTail = rqPeekTail,
.getSize = rqGetSize,
.getCount = rqGetCount,
.clear = rqClear,
.deInit = rqDeInit};
/*---------------------------------Static--------------------------------*/
/*---------------------------------Function--------------------------------*/
/**
* @brief initialize the ring queue
*
* @param n the size of the queue
* @return void* the pointer to the ring queue
*/
void *rqInit(rqcType_t n)
{
if (n == 0)
{
return NULL;
}
ringQueueData_ts *rq = (ringQueueData_ts *)malloc(
sizeof(ringQueueData_ts));
if (!rq)
{
return NULL;
}
rq->queue = (uint8_t *)malloc(n * sizeof(uint8_t));
if (!rq->queue)
{
free(rq);
rq = NULL;
return NULL;
}
rq->head = 0;
rq->tail = 0;
rq->size = n;
rq->count = 0;
return rq;
}
/**
* @brief Push N elements into the queue
*
* @param rqueue Pointer to the queue
* @param buffer Pointer to the buffer
* @param n Number of elements to push
* @return rqcType_t Number of elements pushed
*/
rqcType_t rqPushN(void *rqueue, uint8_t *buffer, rqcType_t n)
{
static rqcType_t i = 0;
if (NULL == rqueue || 0 == n)
{
return 0; // Queue is invalid parameters
}
ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
if (rq->size == rq->count)
{
return 0; // Queue is full
}
// to push n elements into the queue
for (i = 0; i < n; i++)
{
rq->queue[rq->tail] = buffer[i];
rq->tail = (rq->tail + 1) % rq->size;
rq->count++;
if (rq->size == rq->count)
{
break;
}
}
return i; // Number of elements pushed
}
/**
* @brief Pop N elements from the queue
*
* @param rqueue Pointer to the queue
* @param buffer Pointer to the buffer
* @param n Number of elements to pop
* @return rqcType_t Number of elements popped
*/
rqcType_t rqPopN(void *rqueue, uint8_t *buffer, rqcType_t n)
{
static rqcType_t i = 0;
if (NULL == rqueue || 0 == n)
{
return 0; // Queue is empty or invalid parameters
}
ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
if (0 == rq->count)
{
return 0; // Queue is empty
}
// to pop n elements from the queue
for (i = 0; i < n; i++)
{
buffer[i] = rq->queue[rq->head];
rq->head = (rq->head + 1) % rq->size;
rq->count--;
if (0 == rq->count)
{
break; // Queue is empty
}
}
return i; // Number of elements popped
}
/**
* @brief This is a function used to get the first address pointer of the data part in the ring queue structure.
*
* @param rqueue Pointer to the ring queue structure.
* @return uint8_t* The first address pointer of the data part in the ring queue structure
* @return NULL If the ring queue pointer is NULL
*/
uint8_t *rqGetHeadPointer(const void *rqueue)
{
if (NULL == rqueue)
{
return NULL;
}
const ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
return rq->queue;
}
/**
* @brief This is a function used to update the Head index in the ring queue structure.
* It has two parameters, the ring queue pointer rqueue and the number of bytes that have been dequeued num.
*
* @param rqueue Pointer to the ring queue structure.
* @param num Number of bytes that have been dequeued.
* @return true If the head index is updated successfully.
* @return false If the head index is not updated.
*/
bool rqUpdateHead(void *rqueue, rqcType_t num)
{
if (NULL == rqueue)
{
return false;
}
ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
if (rq->count < num)
{
return false;
}
// to update the head index
if (0 == num)
{
return true;
}
rq->head = (rq->head + num) % rq->size;
rq->count -= num;
return true;
}
/**
* @brief This is a function used to update the Tail index in the ring queue structure.
* It has two parameters, the ring queue pointer rqueue and the number of bytes written to the queue num.
*
* @param rqueue Pointer to the ring queue structure.
* @param num Number of bytes written to the queue.
* @return true If the tail index is updated successfully.
* @return false If the tail index is not updated.
*/
bool rqUpdateTail(void *rqueue, rqcType_t num)
{
if (NULL == rqueue)
{
return false;
}
ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
if ((rq->count + num) > rq->size)
{
return false;
}
// to update the tail index
if (0 == num)
{
return true;
}
rq->tail = (rq->tail + num) % rq->size;
rq->count += num;
return true;
}
/**
* @brief This is a function used to check if the ring queue is empty.
*
* @param rqueue Pointer to the ring queue structure.
* @return true If the ring queue is empty.
* @return false If the ring queue is not empty.
*/
bool rqIsEmpty(const void *rqueue)
{
if (NULL == rqueue)
{
return false;
}
const ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
return ((0 == rq->count) ? true : false);
}
/**
* @brief This is a function used to check if the ring queue is full.
*
* @param rqueue Pointer to the ring queue structure.
* @return true If the ring queue is full.
* @return false If the ring queue is not full.
*/
bool rqIsFull(const void *rqueue)
{
if (NULL == rqueue)
{
return false;
}
const ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
return ((rq->size == rq->count) ? true : false);
}
/**
* @brief This is a function used to peek the element at the head of the ring queue.
*
* @param rqueue Pointer to the ring queue structure.
* @param value Pointer to the variable where the value will be stored.
* @return true If the element was peeked successfully.
* @return false If the ring queue is empty or the pointer to the ring queue is NULL.
*/
bool rqPeekHead(const void *rqueue, uint8_t *value)
{
if (NULL == rqueue)
{
return false; // rqueue is NULL
}
const ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
if (0 == rq->count)
{
return false; // Queue is empty
}
*value = rq->queue[rq->head];
return true;
}
/**
* @brief This is a function used to peek the element at the tail of the ring queue.
*
* @param rqueue Pointer to the ring queue structure.
* @param value Pointer to the variable where the value will be stored.
* @return true If the element was peeked successfully.
* @return false If the ring queue is empty or the pointer to the ring queue is NULL.
*/
bool rqPeekTail(const void *rqueue, uint8_t *value)
{
if (NULL == rqueue)
{
return false; // rqueue is NULL
}
const ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
if (0 == rq->count)
{
return false; // Queue is empty
}
*value = rq->queue[(rq->tail - 1 + rq->size) % rq->size];
return true;
}
/**
* @brief This is a function used to get the size of the ring queue.
*
* @param rqueue Pointer to the ring queue structure.
* @return rqcType_t The size of the ring queue.
*/
rqcType_t rqGetSize(const void *rqueue)
{
if (NULL == rqueue)
{
return 0;
}
const ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
return rq->size;
}
/**
* @brief This is a function used to get the number of elements in the ring queue.
*
* @param rqueue Pointer to the ring queue structure.
* @return rqcType_t The number of elements in the ring queue.
*/
rqcType_t rqGetCount(const void *rqueue)
{
if (NULL == rqueue)
{
return 0;
}
const ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
return rq->count;
}
/**
* @brief This is a function used to clear the ring queue.
*
* @param rqueue Pointer to the ring queue structure.
*/
void rqClear(void *rqueue)
{
if (NULL == rqueue)
{
return;
}
ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
rq->head = 0;
rq->tail = 0;
rq->count = 0;
memset(rq->queue, 0, (rq->size * sizeof(uint8_t)));
}
/**
* @brief This is a function used to deinitialize the ring queue.
*
* @param rqueue Pointer to the ring queue structure.
* @attention This function will free the memory allocated for the ring queue.
*/
void rqDeInit(void *rqueue)
{
if (NULL == rqueue)
{
return;
}
ringQueueData_ts *rq = (ringQueueData_ts *)rqueue;
rq->count = 0;
rq->head = 0;
rq->tail = 0;
rq->size = 0;
free(rq->queue);
rq->queue = NULL;
free(rq);
rq = NULL;
}
|
|