📄 os_q.c
字号:
#ifndef OS_MASTER_FILE
#include "includes.h"
#endif
//队列结构
#if OS_Q_EN && (OS_MAX_QS >= 2)
typedef struct os_q { /* QUEUE CONTROL BLOCK */
struct os_q *OSQPtr; /* Link to next queue control block in list of free blocks */
void **OSQStart; /* Pointer to start of queue data */
void **OSQEnd; /* Pointer to end of queue data */
void **OSQIn; /* Pointer to where next message will be inserted in the Q */
void **OSQOut; /* Pointer to where next message will be extracted from the Q */
INT16U OSQSize; /* Size of queue (maximum number of entries) */
INT16U OSQEntries; /* Current number of entries in the queue */
} OS_Q;
static OS_Q *OSQFreeList; /* Pointer to list of free QUEUE control blocks */
static OS_Q OSQTbl[OS_MAX_QS]; /* Table of QUEUE control blocks */
//无等待地从一个消息队列中取得消息
#if OS_Q_Accept_EN
void *OSQAccept (OS_EVENT *pevent)reentrant
{
void *msg;
OS_Q *pq;
OS_ENTER_CRITICAL();
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
OS_EXIT_CRITICAL();
return ((void *)0);
}
pq = pevent->OSEventPtr; /* Point at queue control block */
if (pq->OSQEntries != 0) { /* See if any messages in the queue */
msg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */
pq->OSQEntries--; /* Update the number of entries in the queue */
if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */
pq->OSQOut = pq->OSQStart;
}
} else {
msg = (void *)0; /* Queue is empty */
}
OS_EXIT_CRITICAL();
return (msg); /* Return message received (or NULL) */
}
#endif
//建立一个消息队列
#if OS_Q_Create_EN
OS_EVENT *OSQCreate (void **start, INT16U size)reentrant
{
OS_EVENT *pevent;
OS_Q *pq;
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; /* Get next free event control block */
if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0) { /* See if we have an event control block */
OS_ENTER_CRITICAL(); /* Get a free queue control block */
pq = OSQFreeList;
if (OSQFreeList != (OS_Q *)0) {
OSQFreeList = OSQFreeList->OSQPtr;
}
OS_EXIT_CRITICAL();
if (pq != (OS_Q *)0) { /* See if we were able to get a queue control block */
pq->OSQStart = start; /* Yes, initialize the queue */
pq->OSQEnd = &start[size];
pq->OSQIn = start;
pq->OSQOut = start;
pq->OSQSize = size;
pq->OSQEntries = 0;
pevent->OSEventType = OS_EVENT_TYPE_Q;
pevent->OSEventPtr = pq;
OSEventWaitListInit(pevent);
} else { /* No, since we couldn't get a queue control block */
OS_ENTER_CRITICAL(); /* Return event control block on error */
pevent->OSEventPtr = (void *)OSEventFreeList;
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
pevent = (OS_EVENT *)0;
}
}
return (pevent);
}
#endif
//清空一个消息队列
#if OS_Q_Flush_EN
INT8U OSQFlush (OS_EVENT *pevent)reentrant
{
OS_Q *pq;
OS_ENTER_CRITICAL();
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
OS_EXIT_CRITICAL();
return (OS_ERR_EVENT_TYPE);
}
pq = pevent->OSEventPtr; /* Point to queue storage structure */
pq->OSQIn = pq->OSQStart;
pq->OSQOut = pq->OSQStart;
pq->OSQEntries = 0;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
//队列初始化
void OSQInit (void)reentrant
{
INT16U i;
for (i = 0; i < (OS_MAX_QS - 1); i++) { /* Init. list of free QUEUE control blocks */
OSQTbl[i].OSQPtr = &OSQTbl[i+1];
}
OSQTbl[OS_MAX_QS - 1].OSQPtr = (OS_Q *)0;
OSQFreeList = &OSQTbl[0];
}
//等待一个消息队列中的消息
#if OS_Q_Pend_EN
void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)reentrant
{
void *msg=NULL;
OS_Q *pq;
OS_ENTER_CRITICAL();
if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */
OS_EXIT_CRITICAL();
*err = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
pq = pevent->OSEventPtr; /* Point at queue control block */
if (pq->OSQEntries != 0) { /* See if any messages in the queue */
msg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */
pq->OSQEntries--; /* Update the number of entries in the queue */
if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */
pq->OSQOut = pq->OSQStart;
}
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
} else if (OSIntNesting > 0) { /* See if called from ISR ... */
OS_EXIT_CRITICAL(); /* ... can't PEND from an ISR */
*err = OS_ERR_PEND_ISR;
} else {
OSTCBCur->OSTCBStat |= OS_STAT_Q; /* Task will have to pend for a message to be posted */
OSTCBCur->OSTCBDly = timeout; /* Load timeout into TCB */
OSEventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
OSSched(); /* Find next highest priority task ready to run */
OS_ENTER_CRITICAL();
if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) {/* Did we get a message? */
OSTCBCur->OSTCBMsg = (void *)0; /* Extract message from TCB (Put there by QPost) */
OSTCBCur->OSTCBStat = OS_STAT_RDY;
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* No longer waiting for event */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
} else if (OSTCBCur->OSTCBStat & OS_STAT_Q) { /* Timed out if status indicates pending on Q */
OSEventTO(pevent);
OS_EXIT_CRITICAL();
msg = (void *)0; /* No message received */
*err = OS_TIMEOUT; /* Indicate a timeout occured */
} else {
msg = *pq->OSQOut++; /* Extract message from queue */
pq->OSQEntries--; /* Update the number of entries in the queue */
if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of Q */
pq->OSQOut = pq->OSQStart;
}
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
}
return (msg); /* Return message received (or NULL) */
}
#endif
//向消息队列中发送一个消息(FIFO)
#if OS_Q_Post_EN
INT8U OSQPost (OS_EVENT *pevent, void *msg)reentrant
{
OS_Q *pq;
OS_ENTER_CRITICAL();
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
OS_EXIT_CRITICAL();
return (OS_ERR_EVENT_TYPE);
}
if (pevent->OSEventGrp) { /* See if any task pending on queue */
OSEventTaskRdy(pevent, msg, OS_STAT_Q); /* Ready highest priority task waiting on event */
OS_EXIT_CRITICAL();
OSSched(); /* Find highest priority task ready to run */
return (OS_NO_ERR);
} else {
pq = pevent->OSEventPtr; /* Point to queue control block */
if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */
OS_EXIT_CRITICAL();
return (OS_Q_FULL);
} else {
*pq->OSQIn++ = msg; /* Insert message into queue */
pq->OSQEntries++; /* Update the nbr of entries in the queue */
if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we are at end of queue */
pq->OSQIn = pq->OSQStart;
}
OS_EXIT_CRITICAL();
}
return (OS_NO_ERR);
}
}
#endif
//向消息队列中发送一个消息(LIFO)
#if OS_Q_PostFront_EN
INT8U OSQPostFront (OS_EVENT *pevent, void *msg)reentrant
{
OS_Q *pq;
OS_ENTER_CRITICAL();
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
OS_EXIT_CRITICAL();
return (OS_ERR_EVENT_TYPE);
}
if (pevent->OSEventGrp) { /* See if any task pending on queue */
OSEventTaskRdy(pevent, msg, OS_STAT_Q); /* Ready highest priority task waiting on event */
OS_EXIT_CRITICAL();
OSSched(); /* Find highest priority task ready to run */
return (OS_NO_ERR);
} else {
pq = pevent->OSEventPtr; /* Point to queue control block */
if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */
OS_EXIT_CRITICAL();
return (OS_Q_FULL);
} else {
if (pq->OSQOut == pq->OSQStart) { /* Wrap OUT ptr if we are at the 1st queue entry */
pq->OSQOut = pq->OSQEnd;
}
pq->OSQOut--;
*pq->OSQOut = msg; /* Insert message into queue */
pq->OSQEntries++; /* Update the nbr of entries in the queue */
OS_EXIT_CRITICAL();
}
return (OS_NO_ERR);
}
}
#endif
//查询一个消息队列状态
#if OS_Q_Query_EN
INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *dataptr)reentrant
{
OS_Q *pq;
INT8U i;
INT8U *psrc;
INT8U *pdest;
OS_ENTER_CRITICAL();
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
OS_EXIT_CRITICAL();
return (OS_ERR_EVENT_TYPE);
}
dataptr->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &dataptr->OSEventTbl[0];
for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
*pdest++ = *psrc++;
}
pq = (OS_Q *)pevent->OSEventPtr;
if (pq->OSQEntries > 0) {
dataptr->OSMsg = pq->OSQOut; /* Get next message to return if available */
} else {
dataptr->OSMsg = (void *)0;
}
dataptr->OSNMsgs = pq->OSQEntries;
dataptr->OSQSize = pq->OSQSize;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -