OS_Q.C(全)
- 從隊列中接收消息*OSQAccept (OS_EVENT ?*pevent,INT8U *perr)
- 建立一個消息隊列OS_EVENT ?*OSQCreate (void ?**start,INT16U size)
- 刪除消息隊列OS_EVENT *OSQDel (OS_EVENT *pevent,INT8U opt,INT8U ?perr)
- 清空消息隊列OSQFlush (OS_EVENT *pevent)
- 任務等待消息隊列中的消息*OSQPend (OS_EVENT ?*pevent,INT32U timeout,INT8U ?*perr)
- 取消等待消息的任務OSQPendAbort (OS_EVENT *pevent,INT8U opt,INT8U ? ? *perr)
- 給隊列發送消息INT8U OSQPost (OS_EVENT *pevent,void *pmsg)
- 通過消息隊列向任務發送消息INT8U ?OSQPostFront (OS_EVENT ?*pevent,void *pmsg)
- 消息隊列向任務發消息(允許廣播消息)INT8U ?OSQPostOpt (OS_EVENT ?*pevent,?void *pmsg,INT8U opt)
- 獲得消息隊列的信息INT8U ?OSQQuery (OS_EVENT ?*pevent,OS_Q_DATA *p_q_data)
- 隊列單元初始化?OS_QInit (void)
從隊列中接收消息*OSQAccept (OS_EVENT ?*pevent,INT8U *perr):
建立一個消息隊列OS_EVENT ?*OSQCreate (void ?**start,INT16U ?size):
/*$PAGE*/ /*2018/2/22 ********************************************************************************************************* * 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] *參數: --start:指向消息隊列存儲區域底部的指針。該存儲區域必須被聲明為void型指針數組。形式如下;void *MessageStorage[size] * size is the number of elements in the storage area * --size:該存儲區的成員數量。 * 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返回值:!= (OS_EVENT *)0:指向事件控制塊的指針。== (OS_EVENT *)0:如果事件控制塊不可獲得或者有其他錯誤信息,返回空。 ********************************************************************************************************* */OS_EVENT *OSQCreate (void **start,INT16U size) {OS_EVENT *pevent;/*指向隊列對應的事件控制塊*/OS_Q *pq;/*指向隊列控制塊的指針*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE) {OS_SAFETY_CRITICAL_EXCEPTION();}#endifif (OSIntNesting > 0u) { return ((OS_EVENT *)0); }OS_ENTER_CRITICAL();/*進入中斷*/pevent = OSEventFreeList;/* 得到空閑的事件控制塊*/if (OSEventFreeList != (OS_EVENT *)0) /*如果有可獲得事件控制塊*/{ OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;/*更新空閑事件列表*/}OS_EXIT_CRITICAL();/*退出中斷*/if (pevent != (OS_EVENT *)0) /*如果獲得了事件控制塊*/{ OS_ENTER_CRITICAL();/*進入中斷*/pq = OSQFreeList; /*獲得空閑的隊列控制塊 */if (pq != (OS_Q *)0) /*如果獲得了空閑的隊列控制塊*/{ OSQFreeList = OSQFreeList->OSQPtr; /*調整空閑列表指針到下一個*/OS_EXIT_CRITICAL();/*退出中斷*/pq->OSQStart = start;/*初始化隊列 頭指針*/pq->OSQEnd = &start[size];/*尾指針*/pq->OSQIn = start;/*進入的指針*/pq->OSQOut = start;/*出去的指針*/pq->OSQSize = size;/*隊列大小*/pq->OSQEntries = 0u;/*隊列內的成員數初始化為0*/pevent->OSEventType = OS_EVENT_TYPE_Q;/*將事件控制塊類型設置為隊列類型*/pevent->OSEventCnt = 0u;pevent->OSEventPtr = pq;/*事件控制塊指針指向隊列*/#if OS_EVENT_NAME_EN > 0upevent->OSEventName = (INT8U *)(void *)"?";/*名字初始化為未命名*/#endifOS_EventWaitListInit(pevent);/*初始化等待列表 */} else/*如果沒有獲得空閑的隊列控制塊*/{pevent->OSEventPtr = (void *)OSEventFreeList; /*將事件控制塊還給事件空閑列表*/OSEventFreeList = pevent;OS_EXIT_CRITICAL();/*退出中斷*/pevent = (OS_EVENT *)0;}}return (pevent); }刪除消息隊列OS_EVENT ?*OSQDel (OS_EVENT ?*pevent,INT8U opt,INT8U *perr):
/*$PAGE*/ /*2018/2/22 ********************************************************************************************************* * 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. *參數: --pevent:指向與隊列對應的事件控制塊的指針 * 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. * --opt:選擇刪除方式:opt == OS_DEL_NO_PEND:沒有任務掛起時才能刪除。opt == OS_DEL_ALWAYS:即使有任務正在等待也將隊列刪除。在這種情況下,所有掛起的任務都轉為就緒態。 * perr is a pointer to an error code that can contain one of the following values: * OS_ERR_NONE 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. * --perr:指向錯誤碼的指針:OS_ERR_NONE:調用成功,隊列被刪除;OS_ERR_DEL_ISR:從中斷服務子程序中刪除隊列;OS_ERR_INVALID_OPT:選擇無效;OS_ERR_TASK_WAITING:一個或者多個任務正在等待該隊列OS_ERR_EVENT_TYPE:沒有指向隊列的指針OS_ERR_PEVENT_NULL:pevent為空指針 * Returns : pevent upon error * (OS_EVENT *)0 if the queue was successfully deleted. *返回值:如果成功刪除隊列,返回值為空,如果沒有成功刪除,返回pevent。 * 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. 注釋:1)該函數一定要小心使用。等待隊列的任務要檢查OSQPend()的返回值。2)調用OSQAccept()的任務無法得知隊列是否被刪除,除非檢測pevent是否為空指針。3)該函數調用會中斷很長時間,中斷的時間長短與等待任務的數量成正比。4)因為在刪除后所有的任務都會從等待狀態轉為就緒態。所以如果隊列中的消息為互斥量,調用需要小心。因為此時資源是開放的。5)如果消息隊列內存是動態分配的,你的應用程序一定要通過對應的程序釋放存儲空間。如果空間是靜態的,該空間可以被重新使用。 ********************************************************************************************************* */#if OS_Q_DEL_EN > 0u OS_EVENT *OSQDel (OS_EVENT *pevent,INT8U opt,INT8U *perr) {BOOLEAN tasks_waiting;/*布爾型變量標志是否有任務正在等待*/OS_EVENT *pevent_return;/*返回值*/OS_Q *pq;/*指向隊列的指針*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { *perr = OS_ERR_PEVENT_NULL;return (pevent);}#endifif (pevent->OSEventType != OS_EVENT_TYPE_Q) { *perr = OS_ERR_EVENT_TYPE;return (pevent);}if (OSIntNesting > 0u) { *perr = OS_ERR_DEL_ISR; return (pevent);}OS_ENTER_CRITICAL();/*進入中斷*/if (pevent->OSEventGrp != 0u)/*有任務正在等待隊列*/{ tasks_waiting = OS_TRUE; /* 將等待標志設置為true */}else/*沒有任務等待隊列*/{tasks_waiting = OS_FALSE;/* 將等待標志設置為false*/}switch (opt) /*選擇刪除方式并進行對應操作*/{case OS_DEL_NO_PEND: /* 無掛起才刪除*/if (tasks_waiting == OS_FALSE)/*無任務等待*/{#if OS_EVENT_NAME_EN > 0upevent->OSEventName = (INT8U *)(void *)"?";/*名字初始化為未命名*/#endif/*將隊列控制塊還給空閑隊列列表*/pq = (OS_Q *)pevent->OSEventPtr; pq->OSQPtr = OSQFreeList;OSQFreeList = pq;pevent->OSEventType = OS_EVENT_TYPE_UNUSED;/*將事件類型設置為未使用類型*/pevent->OSEventPtr = OSEventFreeList; /*將事件控制塊還給事件空閑列表*/pevent->OSEventCnt = 0u;OSEventFreeList = pevent; /*更新空閑事件列表*/ OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_NONE;pevent_return = (OS_EVENT *)0; /* 隊列已經被刪除,返回空*/}else/*有任務正在等待*/{OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_TASK_WAITING;/*設置錯誤類型*/pevent_return = pevent;}break;case OS_DEL_ALWAYS: /*有掛起也刪除*/while (pevent->OSEventGrp != 0u)/*將所有等待的任務轉為就緒態*/{ (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_OK);}#if OS_EVENT_NAME_EN > 0upevent->OSEventName = (INT8U *)(void *)"?";#endifpq = (OS_Q *)pevent->OSEventPtr; /*同上*/pq->OSQPtr = OSQFreeList;OSQFreeList = pq;pevent->OSEventType = OS_EVENT_TYPE_UNUSED;pevent->OSEventPtr = OSEventFreeList; pevent->OSEventCnt = 0u;OSEventFreeList = pevent; OS_EXIT_CRITICAL();if (tasks_waiting == OS_TRUE) /*有任務等待時才可能調度*/{ OS_Sched(); /*找到最高優先級任務并進行調度 */}*perr = OS_ERR_NONE;pevent_return = (OS_EVENT *)0; /*隊列被刪除,返回值為空 */break;default:/*兩種選擇都不是*/OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_INVALID_OPT;/*設置錯誤類型*/pevent_return = pevent;break;}return (pevent_return); } #endif清空消息隊列并且忽略發送往隊列的所有消息OSQFlush (OS_EVENT *pevent):
/*$PAGE*/ /*2018/2/22 ********************************************************************************************************* * FLUSH QUEUE * 清空消息隊列并且忽略發送往隊列的所有消息 * Description : This function is used to flush the contents of the message queue. *描述:該功能用來清空消息隊列的內容。 * Arguments : none *參數:無 * Returns : OS_ERR_NONE 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 *返回值:OS_ERR_NONE;成功調用。OS_ERR_EVENT_TYPE:沒有指向隊列的指針。OS_ERR_PEVENT_NULL:pevent為空指針。 * WARNING : You should use this function with great care because, when to flush the queue, you LOOSE * the references to what the queue entries are pointing to and thus, you could cause * 'memory leaks'. In other words, the data you are pointing to that's being referenced * by the queue entries should, most likely, need to be de-allocated (i.e. freed).警告:需要特別小心使用該函數,因為當清空隊列的時候,會釋放隊列中成員指向的一些內容,容易造成內存泄漏。換句話說,在使用完隊列后應該動態釋放空間。 ********************************************************************************************************* */#if OS_Q_FLUSH_EN > 0u INT8U OSQFlush (OS_EVENT *pevent) {OS_Q *pq;/*指向隊列的指針*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { return (OS_ERR_PEVENT_NULL);}if (pevent->OSEventType != OS_EVENT_TYPE_Q) { return (OS_ERR_EVENT_TYPE);}#endifOS_ENTER_CRITICAL();/*進入中斷*/pq = (OS_Q *)pevent->OSEventPtr; /* pq指向隊列存儲結構 */pq->OSQIn = pq->OSQStart;/*進入隊列指針*/pq->OSQOut = pq->OSQStart;/*出隊列指針,首尾指向該隊列的開始*/pq->OSQEntries = 0u;OS_EXIT_CRITICAL();/*退出中斷*/return (OS_ERR_NONE); } #endif任務等待消息隊列中的消息*OSQPend (OS_EVENT ?*pevent,INT32U timeout,INT8U *perr):
/*$PAGE*/ /*2018/2/22 ********************************************************************************************************* * 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 *參數: --pevent:指向事件控制塊的指針 * 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. * --timeout:可選擇的時間片。如果不為0,任務將會等待消息,到時間到達了設定的時間后不再等待。如果是0,任務就會一直等待,知道有消息到來。 * perr is a pointer to where an error message will be deposited. Possible error * messages are: * OS_ERR_NONE The call was successful and your task received a message. * OS_ERR_TIMEOUT A message was not received within the specified 'timeout'. * OS_ERR_PEND_ABORT The wait on the queue was aborted. * 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. * OS_ERR_PEND_LOCKED If you called this function with the scheduler is locked * --perr:指向錯誤碼的指針:‘OS_ERR_NONE:成功調用,任務收到消息。OS_ERR_TIMEOUT:超時錯。OS_ERR_PEND_ABORT:任務被取消。OS_ERR_EVENT_TYPE:沒有指向隊列的指針。OS_ERR_PEVENT_NULL:pevent為空指針。OS_ERR_PEND_ISR:從中斷服務子程序中調用該功能。OS_ERR_PEND_LOCKED:調度程序被鎖 * Returns : != (void *)0 is a pointer to the message received * == (void *)0 if you received a NULL pointer message or, * if no message was received or, * if 'pevent' is a NULL pointer or, * if you didn't pass a pointer to a queue. *返回值:!= (void *)0:指向收到的消息== (void *)0:以下幾種情況返回值為空:指向消息的指針為空;沒有收到消息;pevent為空指針;沒有指向隊列的指針。 * Note(s) : As of V2.60, this function allows you to receive NULL pointer messages. 注釋:對于V2.60版本,該功能允許收到空指針消息。 ********************************************************************************************************* */void *OSQPend (OS_EVENT *pevent,INT32U timeout,INT8U *perr) {void *pmsg;/*指向消息的指針*/OS_Q *pq;/*指向隊列控制塊的指針*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { *perr = OS_ERR_PEVENT_NULL;return ((void *)0);}#endifif (pevent->OSEventType != OS_EVENT_TYPE_Q) {*perr = OS_ERR_EVENT_TYPE;return ((void *)0);}if (OSIntNesting > 0u) { *perr = OS_ERR_PEND_ISR; return ((void *)0);}if (OSLockNesting > 0u) { *perr = OS_ERR_PEND_LOCKED; return ((void *)0);}OS_ENTER_CRITICAL();/*進入中斷*/pq = (OS_Q *)pevent->OSEventPtr;/*指向隊列控制塊的指針*/if (pq->OSQEntries > 0u)/*在隊列中有消息*/{ pmsg = *pq->OSQOut++; /*從隊列中取出最早進入的消息 */pq->OSQEntries--; /*更新隊列的數量*/if (pq->OSQOut == pq->OSQEnd) /*隊列中沒有消息了*/{ pq->OSQOut = pq->OSQStart;/*將出隊列的指針指向隊列首*/}OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_NONE;return (pmsg);/* 返回收到的消息*/}/*隊列中沒有消息*/OSTCBCur->OSTCBStat |= OS_STAT_Q;/*將事件進入睡眠狀態,由消息隊列喚醒*/OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;OSTCBCur->OSTCBDly = timeout; /*等待時間置入任務控制中*/OS_EventTaskWait(pevent);/*使任務進入等待消息隊列狀態*/OS_EXIT_CRITICAL();/*退出中斷*/OS_Sched(); /* 找到最高優先級任務并調度 */OS_ENTER_CRITICAL();/*進入中斷*/switch (OSTCBCur->OSTCBStatPend) /*看掛起狀態是超時還是被取消*/{ case OS_STAT_PEND_OK:/*得到消息*/pmsg = OSTCBCur->OSTCBMsg;*perr = OS_ERR_NONE;break;case OS_STAT_PEND_ABORT:/*任務被取消*/pmsg = (void *)0;*perr = OS_ERR_PEND_ABORT; break;case OS_STAT_PEND_TO:/*超時*/default:OS_EventTaskRemove(OSTCBCur, pevent);pmsg = (void *)0;*perr = OS_ERR_TIMEOUT; break;}OSTCBCur->OSTCBStat = OS_STAT_RDY;/*將任務狀態設置為就緒態*/OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* 清除掛起狀態*/OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;/* 清除事件指針 */#if (OS_EVENT_MULTI_EN > 0u)OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;#endifOSTCBCur->OSTCBMsg = (void *)0; /*清除收到的消息*/OS_EXIT_CRITICAL();/*退出中斷*/return (pmsg); /* 返回收到的消息*/ }取消等待的任務INT8U ?OSQPendAbort (OS_EVENT ?*pevent,INT8U ?opt,INT8U ?*perr):
/*$PAGE*/ /*2018/2/22 ********************************************************************************************************* * ABORT WAITING ON A MESSAGE QUEUE * 取消等待消息的任務 * Description: This function aborts & readies any tasks currently waiting on a queue. This function * should be used to fault-abort the wait on the queue, rather than to normally signal * the queue via OSQPost(), OSQPostFront() or OSQPostOpt(). *描述:該功能是將所有等待隊列消息的任務取消并轉為就緒態。該功能是默認取消等待,而不是通過OSQPost(),OSQPostFront()或者OSQPostOpt()通知隊列。 * Arguments : pevent is a pointer to the event control block associated with the desired queue. *參數: --pevent:指向隊列對應的事件控制塊的指針。 * opt determines the type of ABORT performed: * OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the * queue * OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the * queue * --opt:取消的方式:OS_PEND_OPT_NONE:只取消最高優先級任務;OS_PEND_OPT_BROADCAST:取消所有任務。 * perr is a pointer to where an error message will be deposited. Possible error * messages are: * OS_ERR_NONE No tasks were waiting on the queue. * OS_ERR_PEND_ABORT At least one task waiting on the queue was readied * and informed of the aborted wait; check return value * for the number of tasks whose wait on the queue * was aborted. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.--perr:指向錯誤碼的指針:OS_ERR_NONE:沒有任務等待隊列消息。OS_ERR_PEND_ABORT:至少一個等待隊列消息的任務是就緒的并且被取消等待;檢查任務數的返回值。OS_ERR_EVENT_TYPE:沒有指向隊列的指針;OS_ERR_PEVENT_NULL:pevent為空指針。 * Returns : == 0 if no tasks were waiting on the queue, or upon error. * > 0 if one or more tasks waiting on the queue are now readied and informed.返回值:== 0:沒有任務等待隊列。> 0:一個或多個等待隊列的任務為就緒態并且被取消。 ********************************************************************************************************* */#if OS_Q_PEND_ABORT_EN > 0u INT8U OSQPendAbort (OS_EVENT *pevent,INT8U opt,INT8U *perr) {INT8U nbr_tasks;/*等待的任務數目*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { *perr = OS_ERR_PEVENT_NULL;return (0u);}#endifif (pevent->OSEventType != OS_EVENT_TYPE_Q) { *perr = OS_ERR_EVENT_TYPE;return (0u);}OS_ENTER_CRITICAL();/*進入中斷*/if (pevent->OSEventGrp != 0u) /*有任務正在等待*/{ nbr_tasks = 0u;/*數量先初始化為0*/switch (opt) /*選擇取消的類型*/{case OS_PEND_OPT_BROADCAST: /*取消所有的任務*/while (pevent->OSEventGrp != 0u){ (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);nbr_tasks++;}break;case OS_PEND_OPT_NONE:/*只取消優先級最高的那個任務*/default: /*取消任務就是不讓該任務處于等待狀態,轉為就緒態*/(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);nbr_tasks++;break;}OS_EXIT_CRITICAL();/*退出中斷*/OS_Sched(); /*找到最高優先級任務并調度*/*perr = OS_ERR_PEND_ABORT;return (nbr_tasks);/*返回任務的數目*/}OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_NONE;return (0u); /*如果沒有任務等待的話,返回0*/ } #endif該函數最后是返回取消的任務數目。如果有任務正在等待隊列消息,取消后返回任務數量。如果沒有任務等待,返回0。取消等待的任務實際上就是將任務從等待狀態轉為就緒態。
給隊列發送消息INT8U ?OSQPost (OS_EVENT ?*pevent,void ? *pmsg):
通過消息隊列向任務發送消息INT8U ?OSQPostFront (OS_EVENT ?*pevent,?void *pmsg):
/*$PAGE*/ /*2018/2/22 ********************************************************************************************************* * 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. *描述:該功能是給隊列發送消息,但是與OSQPost()不同,這個消息是發送給隊列的開始,而不是結尾。OSQPostFront()允許你發送優先級高的消息。(消息隊列按照后入先出(LIFO)的方式工作, 而不是先入先出(FIFO)) * Arguments : pevent is a pointer to the event control block associated with the desired queue *參數: --pevent:指向事件控制塊的指針。 * pmsg is a pointer to the message to send. * --pmsg:指向要發送的消息的指針。 * Returns : OS_ERR_NONE The call was successful and the message was sent * OS_ERR_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_NONE:調用成功,消息被發出。OS_ERR_Q_FULL:隊列已滿,不能接收消息。OS_ERR_EVENT_TYPE:沒有指向隊列的指針。OS_ERR_PEVENT_NULL:pevent為空指針。 * Note(s) : As of V2.60, this function allows you to send NULL pointer messages.注釋:在V2.60版本中,該功能允許發送空指針消息。 ********************************************************************************************************* */#if OS_Q_POST_FRONT_EN > 0u INT8U OSQPostFront (OS_EVENT *pevent,void *pmsg) {OS_Q *pq;/*指向消息隊列的指針*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { return (OS_ERR_PEVENT_NULL);}#endifif (pevent->OSEventType != OS_EVENT_TYPE_Q) { return (OS_ERR_EVENT_TYPE);}OS_ENTER_CRITICAL();/*進入中斷*/if (pevent->OSEventGrp != 0u)/*有任務正在等待隊列消息*/{ /*將最高優先級任務轉為就緒態*/(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);OS_EXIT_CRITICAL();/*退出中斷*/OS_Sched(); /* 找到最高優先級任務并調度 */return (OS_ERR_NONE);}/*沒有任務等待消息*/pq = (OS_Q *)pevent->OSEventPtr; /* 指向隊列控制塊的指針*/if (pq->OSQEntries >= pq->OSQSize)/*隊列已滿*/{ OS_EXIT_CRITICAL();/*退出中斷*/return (OS_ERR_Q_FULL);}if (pq->OSQOut == pq->OSQStart) /*當插入指針=指針的起始地址(指針)*/{ pq->OSQOut = pq->OSQEnd;/*插入指針跳轉到最后地址(指針)*/}pq->OSQOut--;/*插入指針減1*/*pq->OSQOut = pmsg; /*插入當前消息(內容) */pq->OSQEntries++;/* 消息數加1 */OS_EXIT_CRITICAL();/*退出中斷*/return (OS_ERR_NONE); } #endif該函數與上一個函數十分相似,不同點在于這個函數是將消息插入到隊列的最前端。這樣就讓隊列的進出方式從FIFO(先進先出)變成了LIFO(后進先出)。
消息隊列向任務發消息(允許廣播消息)INT8U ?OSQPostOpt (OS_EVENT ?*pevent,void *pmsg,INT8U ?opt):
獲得消息隊列的信息INT8U ?OSQQuery (OS_EVENT ?*pevent,OS_Q_DATA *p_q_data):
/*$PAGE*/ /*2018/2/22 ********************************************************************************************************* * 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 *參數: --pevent:指向事件控制塊的指針。 * p_q_data is a pointer to a structure that will contain information about the message queue. * --p_q_data:指向結構體的指針,該指針包含消息隊列的信息。 * Returns : OS_ERR_NONE 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 * OS_ERR_PDATA_NULL If 'p_q_data' is a NULL pointer返回值:OS_ERR_NONE:調用成功,消息被發出。OS_ERR_EVENT_TYPE:對象不是隊列。OS_ERR_PEVENT_NULL:pevent為空指針。OS_ERR_PDATA_NULL:p_q_data為空指針。 ********************************************************************************************************* */#if OS_Q_QUERY_EN > 0u INT8U OSQQuery (OS_EVENT *pevent,OS_Q_DATA *p_q_data) {OS_Q *pq;/*指向隊列的指針*/INT8U i;OS_PRIO *psrc;/*指向源*/OS_PRIO *pdest;/*指向目的*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { return (OS_ERR_PEVENT_NULL);}if (p_q_data == (OS_Q_DATA *)0) { return (OS_ERR_PDATA_NULL);}#endifif (pevent->OSEventType != OS_EVENT_TYPE_Q) { return (OS_ERR_EVENT_TYPE);}OS_ENTER_CRITICAL();/*進入中斷*//*將事件(消息隊列)結構中的等待任務列表復制到pdata數據結構中*/p_q_data->OSEventGrp = pevent->OSEventGrp; /* 等待事件的任務組中的內容傳送到狀態數據結構中*/psrc = &pevent->OSEventTbl[0];/*保存pevent->OSEventTbl[0]對應的地址*/pdest = &p_q_data->OSEventTbl[0];/*保存pdata->OSEventTbl[0]對應的地址*/for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {*pdest++ = *psrc++;/*地址指針下移一個類型地址,獲取信號量的值*/}pq = (OS_Q *)pevent->OSEventPtr;/*將隊列事件指針保存到pq 中*/if (pq->OSQEntries > 0u)/*如果消息隊列指針中有消息*/{p_q_data->OSMsg = *pq->OSQOut; /* 將最早進入隊列得消息復制到數據結構的OSMsg中 */} else{p_q_data->OSMsg = (void *)0;/*如果隊列中沒有消息(包含一個空指針)*/}p_q_data->OSNMsgs = pq->OSQEntries;/*消息隊列中的消息數放置在數據結構的(OSNMsgs)中*/p_q_data->OSQSize = pq->OSQSize;/*消息隊列中的消息隊列容量放置在數據結構得(OSQSize)中*/OS_EXIT_CRITICAL();/*退出中斷*/return (OS_ERR_NONE); } #endif獲得消息隊列的信息實際上就是將隊列中的消息復制到隊列對應的結構體中(p_q_data)。
隊列單元初始化void ?OS_QInit (void):
總結
- 上一篇: os_mbox.c(全)
- 下一篇: os_mem.c(全)