uC/OS-II队列(OS_q)块
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* MESSAGE QUEUE MANAGEMENT
*
* (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
* All Rights Reserved
*
* File : OS_Q.C
* By : Jean J. Labrosse
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include "includes.h"
#endif
#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
/*
*********************************************************************************************************
* ACCEPT MESSAGE FROM QUEUE
*
* Description: This function checks the queue to see if a message is available. Unlike OSQPend(),
* OSQAccept() does not suspend the calling task if a message is not available.
*
* Arguments : pevent is a pointer to the event control block
*
* Returns : != (void *)0 is the message in the queue if one is available. The message is removed
* from the so the next time OSQAccept() is called, the queue will contain
* one less entry.
* == (void *)0 if the queue is empty or,
* if 'pevent' is a NULL pointer or,
* if you passed an invalid event type
*********************************************************************************************************
*/
#if OS_Q_ACCEPT_EN > 0
//无等待的去请求一个信息队列
void *OSQAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
void *msg;
OS_Q *pq;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return ((void *)0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */
//OSQEntries--表示已经存放信息指针的元素数目 OSQOut指向被取消消息的位置 OSQStart指向信息指针数组的起始地址
if (pq->OSQEntries > 0) { /* See if any messages in the queue */
//Yes, extract/提取 oldest message from 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
/*$PAGE*/
/*
*********************************************************************************************************
* CREATE A MESSAGE QUEUE
*
* Description: This function creates a message queue if free event control blocks are available.
*
* Arguments : start is a pointer to the base address of the message queue storage area. The
* storage area MUST be declared as an array of pointers to 'void' as follows
*
* void *MessageStorage[size]
*
* size is the number of elements in the storage area
*
* Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the
* created queue
* == (OS_EVENT *)0 if no event control blocks were available or an error was detected
*********************************************************************************************************
*/
//This function creates a message queue if free event control blocks are available.
OS_EVENT *OSQCreate (void **start, INT16U size)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
OS_Q *pq;
if (OSIntNesting > 0) { /* See if called from ISR ... */
return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
}
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();
//See if we have an event control block
if (pevent != (OS_EVENT *)0) { /* See if we have an event control block */
OS_ENTER_CRITICAL();
pq = OSQFreeList; /* Get a free queue control block */
//OS_Q--queue control block struct
if (pq != (OS_Q *)0) { /* Were we able to get a queue control block ? */
OSQFreeList = OSQFreeList->OSQPtr; /* Yes, Adjust free list pointer to next free*/
OS_EXIT_CRITICAL();
pq->OSQStart = start; /* 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->OSEventCnt = 0;
pevent->OSEventPtr = pq;
//Initalize the wait list
OS_EventWaitListInit(pevent); /* Initalize the wait list */
} else {
//free 还回去
pevent->OSEventPtr = (void *)OSEventFreeList; /* No, Return event control block on error */
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
pevent = (OS_EVENT *)0;
}
}
return (pevent);
}
/*$PAGE*/
/*
*********************************************************************************************************
* DELETE A MESSAGE QUEUE
*
* Description: This function deletes a message queue and readies all tasks pending on the queue.
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* queue.
*
* opt determines delete options as follows:
* opt == OS_DEL_NO_PEND Delete the queue ONLY if no task pending
* opt == OS_DEL_ALWAYS Deletes the queue even if tasks are waiting.
* In this case, all the tasks pending will be readied.
*
* err is a pointer to an error code that can contain one of the following values:
* OS_NO_ERR The call was successful and the queue was deleted
* OS_ERR_DEL_ISR If you tried to delete the queue from an ISR
* OS_ERR_INVALID_OPT An invalid option was specified
* OS_ERR_TASK_WAITING One or more tasks were waiting on the queue
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : pevent upon error
* (OS_EVENT *)0 if the queue was successfully deleted.
*
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
* the queue MUST check the return code of OSQPend().
* 2) OSQAccept() callers will not know that the intended queue has been deleted unless
* they check 'pevent' to see that it's a NULL pointer.
* 3) This call can potentially disable interrupts for a long time. The interrupt disable
* time is directly proportional to the number of tasks waiting on the queue.
* 4) Because ALL tasks pending on the queue will be readied, you MUST be careful in
* applications where the queue is used for mutual exclusion because the resource(s)
* will no longer be guarded by the queue.
* 5) If the storage for the message queue was allocated dynamically (i.e. using a malloc()
* type call) then your application MUST release the memory storage by call the counterpart
* call of the dynamic allocation scheme used. If the queue storage was created statically
* then, the storage can be reused.
*********************************************************************************************************
*/
#if OS_Q_DEL_EN > 0
//This function deletes a message queue and readies all tasks pending on the queue.
OS_EVENT *OSQDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN tasks_waiting;
OS_Q *pq;
//各种判断
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
return ((OS_EVENT *)0);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return (pevent);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return (pevent);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { /* See if any tasks waiting on queue */
tasks_waiting = TRUE; /* Yes */
} else {
tasks_waiting = FALSE; /* No */
}
switch (opt) {
case OS_DEL_NO_PEND: /* Delete queue only if no task waiting */
if (tasks_waiting == FALSE) {
//Return OS_Q to free list
pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */
pq->OSQPtr = OSQFreeList;
OSQFreeList = pq;
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return ((OS_EVENT *)0); /* Queue has been deleted */
} else {
OS_EXIT_CRITICAL();
*err = OS_ERR_TASK_WAITING;
return (pevent);
}
case OS_DEL_ALWAYS: /* Always delete the queue */
while (pevent->OSEventGrp != 0x00) { /* Ready ALL tasks waiting for queue */
OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q);
}
pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */
pq->OSQPtr = OSQFreeList;
OSQFreeList = pq;
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
//若当前是在等待
if (tasks_waiting == TRUE) { /* Reschedule only if task(s) were waiting */
OS_Sched(); /* Find highest priority task ready to run */
}
*err = OS_NO_ERR;
return ((OS_EVENT *)0); /* Queue has been deleted */
default:
OS_EXIT_CRITICAL();
*err = OS_ERR_INVALID_OPT;
return (pevent);
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* FLUSH QUEUE
*
* Description : This function is used to flush the contents of the message queue.
*
* Arguments : none
*
* Returns : OS_NO_ERR upon success
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
*********************************************************************************************************
*/
#if OS_Q_FLUSH_EN > 0
//This function is used to flush the contents/内容 of the message queue. 清空信息队列
INT8U OSQFlush (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pq = (OS_Q *)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
/*$PAGE*/
/*
*********************************************************************************************************
* PEND ON A QUEUE FOR A MESSAGE
*
* Description: This function waits for a message to be sent to a queue
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for a message to arrive at the queue up to the amount of time
* specified by this argument. If you specify 0, however, your task will wait
* forever at the specified queue or, until a message arrives.
*
* err is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_NO_ERR The call was successful and your task received a
* message.
* OS_TIMEOUT A message was not received within the specified timeout
* OS_ERR_EVENT_TYPE You didn't pass a pointer to a queue
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.
*
* Returns : != (void *)0 is a pointer to the message received
* == (void *)0 if no message was received or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass a pointer to a queue.
*********************************************************************************************************
*/
//请求信息队列
void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
void *msg;
OS_Q *pq;
//各种判断
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return ((void *)0);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
pq = (OS_Q *)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 */
//Update the number of entries in 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;
return (msg); /* Return message received */
}
//设置当前状态
OSTCBCur->OSTCBStat |= OS_STAT_Q; /* Task will have to pend for a message to be posted */
OSTCBCur->OSTCBDly = timeout; /* Load timeout into TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
//查找优先级
OS_Sched(); /* Find next highest priority task ready to run */
OS_ENTER_CRITICAL();
msg = OSTCBCur->OSTCBMsg;
if (msg != (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;
return (msg); /* Return message received */
}
//时间超时
OS_EventTO(pevent); /* Timed out */
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; /* Indicate a timeout occured */
return ((void *)0); /* No message received */
}
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO A QUEUE
*
* Description: This function sends a message to a queue
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* msg is a pointer to the message to send. You MUST NOT send a NULL pointer.
*
* Returns : OS_NO_ERR The call was successful and the message was sent
* OS_Q_FULL If the queue cannot accept any more messages because it is full.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
*********************************************************************************************************
*/
//This function sends a message to a queue
#if OS_Q_POST_EN > 0
INT8U OSQPost (OS_EVENT *pevent, void *msg)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0) { /* Make sure we are not posting a NULL pointer */
return (OS_ERR_POST_NULL_PTR);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { /* See if any task pending on queue */
OS_EventTaskRdy(pevent, msg, OS_STAT_Q); /* Ready highest priority task waiting on event */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return (OS_NO_ERR);
}
pq = (OS_Q *)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);
}
//OSQIn指向一条插入信息 的位置
*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
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO THE FRONT OF A QUEUE
*
* Description: This function sends a message to a queue but unlike OSQPost(), the message is posted at
* the front instead of the end of the queue. Using OSQPostFront() allows you to send
* 'priority' messages.
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* msg is a pointer to the message to send. You MUST NOT send a NULL pointer.
*
* Returns : OS_NO_ERR The call was successful and the message was sent
* OS_Q_FULL If the queue cannot accept any more messages because it is full.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_POST_NULL_PTR If you are attempting to post to a non queue.
*********************************************************************************************************
*/
//OSQPost()---实现先进先出 OSQPostFront()----后进先出 都是向信息队列发送信息
#if OS_Q_POST_FRONT_EN > 0
INT8U OSQPostFront (OS_EVENT *pevent, void *msg)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0) { /* Make sure we are not posting a NULL pointer */
return (OS_ERR_POST_NULL_PTR);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { /* See if any task pending on queue */
//Ready highest priority task waiting on event
OS_EventTaskRdy(pevent, msg, OS_STAT_Q); /* Ready highest priority task waiting on event */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return (OS_NO_ERR);
}
pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */
if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */
// queue is full
OS_EXIT_CRITICAL();
return (OS_Q_FULL);
}
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
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO A QUEUE
*
* Description: This function sends a message to a queue. This call has been added to reduce code size
* since it can replace both OSQPost() and OSQPostFront(). Also, this function adds the
* capability to broadcast a message to ALL tasks waiting on the message queue.
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* msg is a pointer to the message to send. You MUST NOT send a NULL pointer.
*
* opt determines the type of POST performed:
* OS_POST_OPT_NONE POST to a single waiting task
* (Identical to OSQPost())
* OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the queue
* OS_POST_OPT_FRONT POST as LIFO (Simulates OSQPostFront())
*
* Below is a list of ALL the possible combination of these flags:
*
* 1) OS_POST_OPT_NONE
* identical to OSQPost()
*
* 2) OS_POST_OPT_FRONT
* identical to OSQPostFront()
*
* 3) OS_POST_OPT_BROADCAST
* identical to OSQPost() but will broadcast 'msg' to ALL waiting tasks
*
* 4) OS_POST_OPT_FRONT + OS_POST_OPT_BROADCAST is identical to
* OSQPostFront() except that will broadcast 'msg' to ALL waiting tasks
*
* Returns : OS_NO_ERR The call was successful and the message was sent
* OS_Q_FULL If the queue cannot accept any more messages because it is full.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
*
* Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the
* interrupt disable time is proportional to the number of tasks waiting on the queue.
*********************************************************************************************************
*/
#if OS_Q_POST_OPT_EN > 0
// this function adds the capability to broadcast a message to ALL tasks waiting on the message queue.
// This function sends a message to a queue.
INT8U OSQPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
//各种判断
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0) { /* Make sure we are not posting a NULL pointer */
return (OS_ERR_POST_NULL_PTR);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { /* See if any task pending on queue */
if ((opt & OS_POST_OPT_BROADCAST) != 0x00) { /* Do we need to post msg to ALL waiting tasks ? */
//Do we need to post msg to ALL waiting tasks
while (pevent->OSEventGrp != 0x00) { /* Yes, Post to ALL tasks waiting on queue */
OS_EventTaskRdy(pevent, msg, OS_STAT_Q);
}
} else {
//发送高优先级任务
OS_EventTaskRdy(pevent, msg, OS_STAT_Q); /* No, Post to HPT waiting on queue */
}
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return (OS_NO_ERR);
}
pq = (OS_Q *)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);
}
if ((opt & OS_POST_OPT_FRONT) != 0x00) { /* Do we post to the FRONT of the queue? */
if (pq->OSQOut == pq->OSQStart) { /* Yes, Post as LIFO, Wrap OUT pointer if we ... */
pq->OSQOut = pq->OSQEnd; /* ... are at the 1st queue entry */
}
pq->OSQOut--;
*pq->OSQOut = msg; /* Insert message into queue */
} else { /* No, Post as FIFO */
*pq->OSQIn++ = msg; /* Insert message into queue */
if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we are at end of queue */
pq->OSQIn = pq->OSQStart;
}
}
pq->OSQEntries++; /* Update the nbr of entries in the queue */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* QUERY A MESSAGE QUEUE
*
* Description: This function obtains information about a message queue.
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* pdata is a pointer to a structure that will contain information about the message
* queue.
*
* Returns : OS_NO_ERR The call was successful and the message was sent
* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
*********************************************************************************************************
*/
#if OS_Q_QUERY_EN > 0
INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
INT8U *psrc;
INT8U *pdest;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pdata->OSEventGrp = pevent->OSEventGrp; /* Copy message queue wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &pdata->OSEventTbl[0];
#if OS_EVENT_TBL_SIZE > 0
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 1
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 2
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 3
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 4
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 5
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 6
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 7
*pdest = *psrc;
#endif
pq = (OS_Q *)pevent->OSEventPtr;
if (pq->OSQEntries > 0) {
pdata->OSMsg = *pq->OSQOut; /* Get next message to return if available */
} else {
pdata->OSMsg = (void *)0;
}
pdata->OSNMsgs = pq->OSQEntries;
pdata->OSQSize = pq->OSQSize;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif /* OS_Q_QUERY_EN */
/*$PAGE*/
/*
*********************************************************************************************************
* QUEUE MODULE INITIALIZATION
*
* Description : This function is called by uC/OS-II to initialize the message queue module. Your
* application MUST NOT call this function.
*
* Arguments : none
*
* Returns : none
*
* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************************************
*/
void OS_QInit (void)
{
#if OS_MAX_QS == 1
OSQFreeList = &OSQTbl[0]; /* Only ONE queue! */
OSQFreeList->OSQPtr = (OS_Q *)0;
#endif
#if OS_MAX_QS >= 2
INT16U i;
OS_Q *pq1;
OS_Q *pq2;
pq1 = &OSQTbl[0];
pq2 = &OSQTbl[1];
for (i = 0; i < (OS_MAX_QS - 1); i++) { /* Init. list of free QUEUE control blocks */
pq1->OSQPtr = pq2;
pq1++;
pq2++;
}
pq1->OSQPtr = (OS_Q *)0;
OSQFreeList = &OSQTbl[0];
#endif
}
#endif /* OS_Q_EN */
uC/OS-II队列(OS_q)块的更多相关文章
- uC/OS II原理分析及源码阅读(一)
uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的.可裁减的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和 ...
- 【原创】uC/OS II 任务切换原理
今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS.IP寄存器没有出栈和入栈指令,所以只能引 ...
- 【小梅哥SOPC学习笔记】NIOS II处理器运行UC/OS II
SOPC开发流程之NIOS II 处理器运行 UC/OS II 这里以在芯航线FPGA学习套件的核心板上搭建 NIOS II 软核并运行 UCOS II操作系统为例介绍SOPC的开发流程. 第一步:建 ...
- uC/OS II 函数说明 之–OSTaskCreate()与OSTaskCreateExt()
1. OSTaskCreate() OSTaskCreate()建立一个新任务,能够在多任务环境启动之前,或者执行任务中建立任务.注意,ISR中禁止建立任务,一个任务必须为无限循环结构. ...
- uc/os iii移植到STM32F4---IAR开发环境
也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...
- uc/os 任务删除
问题描述: uc/os 任务删除 问题解决: uc/os任务删除流程图 具体代码 注: 如上是关中断,以及取消优先级对应的就绪标志 关中断代码为: 取消就绪标志,实际上是将就绪表中指定 ...
- uc/os任务创建
问题描述: uc/os中任务创建 问题解决: 创建一个任务,任务从无到有.任务创建函数分两种, 一种是基本的创建函数OSTaskCreate, 另一种是扩展的任务创建函数OSTaskCrea ...
- uC/OS 的任务调度解析 (转)
uC/OS 的任务调度解析 1.任务调度器启动之后(初始化,主要是TCB的初始化),就可以创建任务,开始任务调度了,实际上第一个任务准确的说不是进行任务切换,而是进行启动当前最高优先级任务.uC/OS ...
- 关于uC/OS的简单学习(转)
1.微内核 与Linux的首要区别是,它是一个微内核,内核所实现的功能非常简单,主要包括: 一些通用函数,如TaskCreate(),OSMutexPend(),OSQPost()等. 中断处理函数, ...
随机推荐
- DataGridView 绑定List集合后实现自定义排序
这里只贴主要代码,dataList是已添加数据的全局变量,绑定数据源 datagridview1.DataSource = dataList,以下是核心代码. 实现点击列表头实现自定义排序 priva ...
- JS 问题集锦
[1]js页面跳转 和 js打开新窗口方法 第一种: <script language="javascript" type="text/javascript&quo ...
- android服务之录音功能
该服务的作用是当打电话时自动录音. 布局文件 布局文件中开启录音服务 <?xml version="1.0" encoding="utf-8"?> ...
- BroadcastReceiver之(手动代码注册广播)屏幕锁屏、解锁监听、开机自启
对于解锁和锁屏这种用的比较频繁action,谷歌做了限制,必须手动用代码注册 直接上代码:这是注册广播(手动代码注册广播接收者) public class MainActivity extends A ...
- Android自定义PopupWindow显示在控件上方或者下方
记录学习之用 View view = mInflater.inflate(R.layout.layout_popupwindow, null); PopUpwindowLayout popUpwind ...
- Json-遍历
1.js遍历 var data=[{name:"a",age:12},{name:"b",age:11},{name:"c",age:13} ...
- C# String.Format格式说明
C#格式化数值结果表 字符 说明 示例 输出 C 货币 string.Format("{0:C3}", 2) $2.000 D 十进制 string.Format("{0 ...
- 事件冒泡是什么如何用jquery阻止事件冒泡
(1)什么是事件起泡 首先你要明白一点,当一个事件发生的时候,该事件总是有一个事件源,即引发这个事件的对象,一个事件不能凭空产生,这就是事件的发生. 当事件发生后,这个事件就要开始传播.为什么要传播呢 ...
- Python字符串基础一
下一篇:Python 序列通用操作介绍 写在前面 下学期开始上计算机网络的课程,现在已经在看相关书籍,希望结合python写出一个网络爬虫程序.利用学习C++后的空余时间来看看Python并在这里总结 ...
- C++强制类型转换操作符 static_cast
static_cast是一个强制类型转换操作符.强制类型转换,也称为显式转换,C++中强制类型转换操作符有static_cast.dynamic_cast.const_cast.reinterpert ...