📄 os_q.c
字号:
/*********************************************************************************************************** uC/OS-II* The Real-Time Kernel* MESSAGE QUEUE MANAGEMENT** (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL* All Rights Reserved** V2.00** File : OS_Q.C* By : Jean J. Labrosse**********************************************************************************************************/#ifndef OS_MASTER_FILE#include "includes.h"#endif#if OS_Q_EN && (OS_MAX_QS >= 2)/*********************************************************************************************************** LOCAL DATA TYPES **********************************************************************************************************/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;/*********************************************************************************************************** LOCAL GLOBAL VARIABLES**********************************************************************************************************/static OS_Q *OSQFreeList; /* Pointer to list of free QUEUE control blocks */static OS_Q OSQTbl[OS_MAX_QS]; /* Table of QUEUE control blocks *//*$PAGE*//*********************************************************************************************************** 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* if you passed an invalid event type**********************************************************************************************************/void *OSQAccept (OS_EVENT *pevent){ 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 = (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 */ 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) */}/*$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 : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the* created queue* == (void *)0 if no event control blocks were available**********************************************************************************************************/OS_EVENT *OSQCreate (void **start, INT16U size){ 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);}/*$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**********************************************************************************************************/INT8U OSQFlush (OS_EVENT *pevent){ 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 = (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);}/*$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**********************************************************************************************************/void OSQInit (void){ 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];}/*$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_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 you didn't pass a pointer to a queue.**********************************************************************************************************/void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err){ void *msg; OS_Q *pq; OS_ENTER_CRITICAL();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -