?? os_q.c
字號(hào):
/*
*********************************************************************************************************
* uC/OS-II 實(shí)時(shí)內(nèi)核
* 消息隊(duì)列管理
*
* (c) 版權(quán) 1992-2002, 所有版權(quán)歸Jean J. Labrosse, Weston, FL 所有
*
*
* 文件名稱 : OS_Q.C
* 程序作者 : Jean J. Labrosse
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include "includes.h"
#endif
#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
/*
*********************************************************************************************************
* 從隊(duì)列中獲取消息
*
* 函數(shù)描述: 該函數(shù)檢查隊(duì)列看消息是否有效。不象 OSMboxPend(),如果消息無效,函數(shù)OSMboxAccept()不會(huì)掛起
* 調(diào)用的函數(shù)。
*
* 輸入?yún)?shù) : pevent 指向ECB的指針
*
* 返回值 : != (void *)0 如果有效是在隊(duì)列中的消息。OSQAccept() 再次被調(diào)用則隊(duì)列清零隊(duì)列為空。
* == (void *)0 隊(duì)列為空,
* 'pevent' 是空指針,
* 沒有傳遞適當(dāng)?shù)氖录羔?*********************************************************************************************************
*/
#if OS_Q_ACCEPT_EN > 0
void *OSQAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3 /* 為CPU狀態(tài)寄存器分配存儲(chǔ)變量 */
OS_CPU_SR cpu_sr;
#endif
void *msg;
OS_Q *pq;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0)
{ /* 無效的 'pevent' */
return ((void *)0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q)
{ /* 無效的事件塊類型 */
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
pq = (OS_Q *)pevent->OSEventPtr; /* 指向QCB */
if (pq->OSQEntries > 0) /* 看隊(duì)列中是否有消息? */
{
msg = *pq->OSQOut++; /* 是,提取最先進(jìn)入的消息 */
pq->OSQEntries--; /* 更新隊(duì)列中的消息數(shù) */
if (pq->OSQOut == pq->OSQEnd) /* 進(jìn)行邊界檢查 */
{
pq->OSQOut = pq->OSQStart;
}
}
else
{
msg = (void *)0; /* 隊(duì)列中的消息為空 */
}
OS_EXIT_CRITICAL();
return (msg); /* 返回接收的消息 (或空指針) */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 建立一個(gè)消息隊(duì)列
*
* 函數(shù)描述: 如果空余ECB有效,該函數(shù)創(chuàng)建消息隊(duì)列。
*
* 輸入?yún)?shù): start 指向消息隊(duì)列存儲(chǔ)區(qū)基址的指針。存儲(chǔ)區(qū)必須聲明指向空的指針陣列,如下:
*
* void *MessageStorage[size]
*
* size 存儲(chǔ)區(qū)的單元數(shù)
*
* 返回值: != (OS_EVENT *)0 指向帶有已創(chuàng)建的隊(duì)列的ECB的指針
* == (OS_EVENT *)0 ECB無效或出錯(cuò)
*********************************************************************************************************
*/
OS_EVENT *OSQCreate (void **start, INT16U size)
{
#if OS_CRITICAL_METHOD == 3 /* 為CPU狀態(tài)寄存器分配存儲(chǔ)變量 */
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
OS_Q *pq;
if (OSIntNesting > 0)
{ /* 看調(diào)用是否來自ISR ... */
return ((OS_EVENT *)0); /* ... 從 ISR中不能創(chuàng)建 */
}
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; /* 得到空余的ECB */
if (OSEventFreeList != (OS_EVENT *)0) /* 看空余ECB池是否為空? */
{
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0)
{ /* 看是否有一個(gè)ECB? */
OS_ENTER_CRITICAL();
pq = OSQFreeList; /* 得到一個(gè)隊(duì)列控制塊 */
if (pq != (OS_Q *)0) /* 隊(duì)列控制塊是否為空 ? */
{
OSQFreeList = OSQFreeList->OSQPtr; /* 不為空, 得到QCB */
OS_EXIT_CRITICAL();
pq->OSQStart = start; /* 初始化隊(duì)列 */
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;
OS_EventWaitListInit(pevent); /* 初始化任務(wù)等待列表 */
}
else
{
pevent->OSEventPtr = (void *)OSEventFreeList; /* 空, 返回ECB出錯(cuò) */
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
pevent = (OS_EVENT *)0;
}
}
return (pevent);
}
/*$PAGE*/
/*
*********************************************************************************************************
* 刪除一個(gè)消息隊(duì)列
*
* 函數(shù)描述: 該函數(shù)刪除一個(gè)消息隊(duì)列和就緒等待消息隊(duì)列的所有任務(wù)。
*
* 輸入?yún)?shù) : pevent 指向帶有期望消息隊(duì)列的ECB的指針
*
* opt 決定刪除的選項(xiàng)如下:
* opt == OS_DEL_NO_PEND 只在無任務(wù)等待時(shí),才刪除隊(duì)列
* opt == OS_DEL_ALWAYS 即使有任務(wù)等待,也要?jiǎng)h除隊(duì)列
* 該種情況下,所有等待任務(wù)將就緒.
*
* err 指向下列值之一的出錯(cuò)代碼的指針:
* OS_NO_ERR 調(diào)用成功,隊(duì)列被刪除
* OS_ERR_DEL_ISR 從 ISR中刪除隊(duì)列
* OS_ERR_INVALID_OPT 指定選項(xiàng)無效
* OS_ERR_TASK_WAITING 一個(gè)或更多的任務(wù)正等待隊(duì)列
* OS_ERR_EVENT_TYPE 沒有傳遞一個(gè)指向隊(duì)列的指針
* OS_ERR_PEVENT_NULL 'pevent' 是一個(gè)空指針
*
* 返回值 : pevent upon error
* (OS_EVENT *)0 隊(duì)列成功刪除.
*
* 注釋 : 1) 該函數(shù)使用時(shí)要小心。期望消息隊(duì)列的任務(wù)一定要檢查OSQPend()的返回值。
* 2) OSQAccept() 的調(diào)用函數(shù)將不會(huì)知道消息郵箱已被刪除,除非檢查'pevent'是一個(gè)空指針。
* 3) 這種調(diào)用潛在的關(guān)閉中斷很長(zhǎng)時(shí)間。中斷關(guān)閉時(shí)間直接正比于等待消息隊(duì)列的任務(wù)的數(shù)量。
* 4) 由于所有等待消息隊(duì)列的任務(wù)將被就緒。所以,必須小心處理隊(duì)列用在互斥上,因?yàn)橘Y源不再受隊(duì)列保護(hù)。
* 5) 如果消息隊(duì)列的存儲(chǔ)動(dòng)態(tài)分配(如使用 malloc() 調(diào)用),那么,應(yīng)用程序必須使用相配的動(dòng)態(tài)釋放存儲(chǔ)區(qū)。
* 如果存儲(chǔ)區(qū)靜態(tài)創(chuàng)建,存儲(chǔ)能重用。
*********************************************************************************************************
*/
#if OS_Q_DEL_EN > 0
OS_EVENT *OSQDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 為CPU狀態(tài)寄存器分配存儲(chǔ)變量 */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN tasks_waiting;
OS_Q *pq;
if (OSIntNesting > 0)
{ /* 如果調(diào)用來自 ISR ... */
*err = OS_ERR_DEL_ISR; /* ... 從ISR中不能刪除 */
return ((OS_EVENT *)0);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0)
{ /* 無效的 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return (pevent);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q)
{ /* 無效的事件塊類型 */
*err = OS_ERR_EVENT_TYPE;
return (pevent);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00)
{ /* 看是否有任務(wù)在等待消息隊(duì)列? */
tasks_waiting = TRUE; /* 是 */
}
else
{
tasks_waiting = FALSE; /* 否 */
}
switch (opt)
{
case OS_DEL_NO_PEND: /* 只在無任務(wù)等待時(shí),才刪除隊(duì)列 */
if (tasks_waiting == FALSE)
{
pq = (OS_Q *)pevent->OSEventPtr; /* 返回 OS_Q 空余列表 */
pq->OSQPtr = OSQFreeList;
OSQFreeList = pq;
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* 返回ECB到空余鏈表中 */
OSEventFreeList = pevent; /* 加入空余鏈表中 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return ((OS_EVENT *)0); /* 消息隊(duì)列被刪除 */
}
else
{
OS_EXIT_CRITICAL();
*err = OS_ERR_TASK_WAITING;
return (pevent);
}
case OS_DEL_ALWAYS: /* 即使有任務(wù)等待,也要?jiǎng)h除隊(duì)列 */
while (pevent->OSEventGrp != 0x00)
{
OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q); /* 就緒所有等待消息隊(duì)列的任務(wù) */
}
pq = (OS_Q *)pevent->OSEventPtr; /* 返回 OS_Q 空余列表 */
pq->OSQPtr = OSQFreeList;
OSQFreeList = pq;
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* 返回ECB到空余鏈表中 */
OSEventFreeList = pevent; /* 加入空余鏈表中 */
OS_EXIT_CRITICAL();
if (tasks_waiting == TRUE)
{ /* 如果任務(wù)等待重新調(diào)度 */
OS_Sched(); /* 尋找最高優(yōu)先級(jí)任務(wù)就緒運(yùn)行 */
}
*err = OS_NO_ERR;
return ((OS_EVENT *)0); /* 消息隊(duì)列被刪除 */
default:
OS_EXIT_CRITICAL();
*err = OS_ERR_INVALID_OPT;
return (pevent);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -