📄 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 + -