?? os_mbox.c
字號:
/*
*********************************************************************************************************
* uC/OS-II 實時內核
* 消息郵箱管理
*
* (c) 版權 1992-2002, 所有版權歸Jean J. Labrosse, Weston, FL 所有
*
*
* 文件名稱 : OS_MBOX.C
* 程序作者 : Jean J. Labrosse
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include "includes.h"
#endif
#if OS_MBOX_EN > 0
/*
*********************************************************************************************************
* 從郵箱中獲取消息
*
* 函數描述: 該函數檢查郵箱看消息是否有效。不象 OSMboxPend(),如果消息無效,函數OSMboxAccept()不會掛起
* 調用的函數
*
* 輸入參數 : pevent 指向ECB的指針
*
* 返回值 : != (void *)0 如果有效是郵箱中的消息。 OSMboxAccept()再次被調用則郵箱清零,郵箱為空。
* == (void *)0 郵箱為空,
* 'pevent' 是空指針,
* 沒有傳遞適當的事件類型指針
*********************************************************************************************************
*/
#if OS_MBOX_ACCEPT_EN > 0
void *OSMboxAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3 /* 為CPU狀態寄存器分配存儲變量 */
OS_CPU_SR cpu_sr;
#endif
void *msg;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0)
{ /* 無效的 'pevent' */
return ((void *)0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX)
{ /* 無效的事件塊類型 */
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
msg = pevent->OSEventPtr;
pevent->OSEventPtr = (void *)0; /* 清除消息郵箱 */
OS_EXIT_CRITICAL();
return (msg); /* 返回接收的消息 (或空指針) */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 創建一個消息郵箱
*
* 函數描述: 如果空余ECB有效,該函數創建一個消息郵箱。
*
* 輸入參數 : msg 指向存放在郵箱中消息的指針。 如果設定該值為空指針,那么郵箱將為空。
*
* 返回值 : != (OS_EVENT *)0 指向帶有創建消息郵箱的ECB。
* == (OS_EVENT *)0 無有效的ECB。
*********************************************************************************************************
*/
OS_EVENT *OSMboxCreate (void *msg)
{
#if OS_CRITICAL_METHOD == 3 /* 為CPU狀態寄存器分配存儲變量 */
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
if (OSIntNesting > 0)
{ /* 如果調用來自 ISR ... */
return ((OS_EVENT *)0); /* ... 從ISR中不能創建 */
}
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)
{
pevent->OSEventType = OS_EVENT_TYPE_MBOX;
pevent->OSEventCnt = 0;
pevent->OSEventPtr = msg; /* 在ECB 中存儲消息指針 */
OS_EventWaitListInit(pevent);
}
return (pevent); /* 返回ECB 的指針 */
}
/*$PAGE*/
/*
*********************************************************************************************************
* 刪除一個郵箱
*
* 函數描述: 該函數刪除一個郵箱和就緒等待消息郵箱的所有任務。
*
* 輸入參數 : pevent 指向帶有期望郵箱的ECB的指針。
*
* opt 決定刪除的選項:
* opt == OS_DEL_NO_PEND 只在無任務等待時,才刪除郵箱
* opt == OS_DEL_ALWAYS 即使有任務等待,也要刪除郵箱。
* 該種情況下,所有等待任務將就緒。
*
* err 指向下列值之一的出錯代碼的指針:
* OS_NO_ERR 調用成功,郵箱被刪除
* OS_ERR_DEL_ISR 從 ISR中刪除郵箱
* OS_ERR_INVALID_OPT 指定選項無效
* OS_ERR_TASK_WAITING 一個或更多的任務正等待郵箱
* OS_ERR_EVENT_TYPE 沒有傳遞一個指向郵箱類型的指針
* OS_ERR_PEVENT_NULL 'pevent' 是一個空指針
*
* 返回值 : pevent upon error
* (OS_EVENT *)0 郵箱成功刪除
*
* Note(s) : 1) 該函數使用時要小心。期望消息郵箱的任務一定要檢查OSMboxPend()的返回值。
* 2) OSMboxAccept()的調用函數將不會知道消息郵箱已被刪除。
* 3) 這種調用潛在的關閉中斷很長時間。中斷關閉時間直接正比于等待消息郵箱的任務的數量。
* 4) 由于所有等待郵箱的任務將被就緒。所以,必須小心處理郵箱用在互斥上,因為資源不再受郵箱保護。
*************************************************************************************************************
*/
#if OS_MBOX_DEL_EN > 0
OS_EVENT *OSMboxDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 為CPU狀態寄存器分配存儲變量 */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN tasks_waiting;
if (OSIntNesting > 0)
{ /* 如果調用來自 ISR ... */
*err = OS_ERR_DEL_ISR; /* ... 從ISR中不能刪除 */
return (pevent);
}
#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_MBOX)
{ /* 無效的事件塊類型 */
*err = OS_ERR_EVENT_TYPE;
return (pevent);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00)
{ /* 看是否有任務在等待消息郵箱? */
tasks_waiting = TRUE; /* 是 */
}
else
{
tasks_waiting = FALSE; /* 否 */
}
switch (opt)
{
case OS_DEL_NO_PEND: /* 只在無任務等待時,刪除郵箱 */
if (tasks_waiting == FALSE)
{
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* 返回ECB到空余鏈表中 */
OSEventFreeList = pevent; /* 加入空余鏈表中 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return ((OS_EVENT *)0); /* 消息郵箱被刪除 */
}
else
{
OS_EXIT_CRITICAL();
*err = OS_ERR_TASK_WAITING;
return (pevent);
}
case OS_DEL_ALWAYS: /* 即使有任務等待,也要刪除郵箱 */
while (pevent->OSEventGrp != 0x00)
{ /* 就緒所有等待消息郵箱的任務 */
OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX);
}
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* 返回ECB到空余鏈表中 */
OSEventFreeList = pevent; /* 加入空余鏈表中 */
OS_EXIT_CRITICAL();
if (tasks_waiting == TRUE)
{ /* 如果任務等待重新調度 */
OS_Sched(); /* 尋找最高優先級任務就緒運行 */
}
*err = OS_NO_ERR;
return ((OS_EVENT *)0); /* 消息郵箱被刪除 */
default:
OS_EXIT_CRITICAL();
*err = OS_ERR_INVALID_OPT;
return (pevent);
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 等待郵箱中的消息
*
* 函數描述: 該函數等待發送到郵箱中的消息
*
* 輸入參數 : pevent 指向帶有期望郵箱的ECB的指針
*
* timeout 選擇延時時間。如果非0,則任務將在指定的延時時間內等待到達郵箱中的消息。如果為0,
* 則任務將一直等待郵箱中消息的到來。
* err 指向出錯代碼的指針。其值為:
*
* OS_NO_ERR 調用成功,任務收到消息。
* OS_TIMEOUT 在指定的延時時間內,沒有收到消息
* OS_ERR_EVENT_TYPE 無效的事件類型
* OS_ERR_PEND_ISR 從ISR中調用該函數,將導致掛起
* OS_ERR_PEVENT_NULL 'pevent' 是一個空指針
*
* 返回值 : != (void *)0 指向接收到消息的指針
* == (void *)0 沒有消息接收,
* 'pevent' 是一個空指針,
* 沒有傳遞給ECB一個恰當的指針.
*********************************************************************************************************
*/
void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 為CPU狀態寄存器分配存儲變量 */
OS_CPU_SR cpu_sr;
#endif
void *msg;
if (OSIntNesting > 0)
{ /* 如果調用來自 ISR ... */
*err = OS_ERR_PEND_ISR; /* ... 從ISR中不能掛起 */
return ((void *)0);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0)
{ /* 無效的 'pevent' */
*err = OS_ERR_PEVENT_NULL;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -