/*
** ver : 2.52
** file : os_mbox.c
** brief : 消息邮箱相关函数 C 文件
*/
#ifndef OS_MASTER_FILE
#include "includes.h" /* 包含头文件 */
#endif
#if OS_MBOX_EN > 0
/*
**************************************************************************************
* 无等待的请求消息邮箱
*
* brief : 该函数用于无等待的请求消息邮箱
*
* pevent : 指向事件控制块的指针
*
* returns : != (void *)0 邮箱内消息有效,返回后清空邮箱
* == (void *)0 未得到消息
*
* note : 该函数的另一个作用是清空消息邮箱
*****************************************************************************************
*/
#if OS_MBOX_ACCEPT_EN > 0
void *OSMboxAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
void *msg;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指 */
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*/
/*
*******************************************************************************************
* 创建消息邮箱
*
* brief : 该函数用于创建消息邮箱
*
* msg : 指向消息的指针
*
* Returns : != (OS_EVENT *)0 成功
* == (OS_EVENT *)0 失败
******************************************************************************************
*/
OS_EVENT *OSMboxCreate (void *msg)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
if (OSIntNesting > 0) { /* 不允许中断内创建邮箱 */
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) {
pevent->OSEventType = OS_EVENT_TYPE_MBOX;
pevent->OSEventCnt = 0;
pevent->OSEventPtr = msg; /* 消息 */
OS_EventWaitListInit(pevent);
}
return (pevent);
}
/*$PAGE*/
/*
*****************************************************************************************
* 删除消息邮箱
*
* brief : 该函数用于删除消息邮箱
*
* pevent : 指向事件控制块的指针
*
* opt : 删除选项:
* opt == OS_DEL_NO_PEND 无任务等待时删除
* opt == OS_DEL_ALWAYS 无条件删除
*
* err : 指向错误代码的指针:
* OS_NO_ERR 成功
* OS_ERR_DEL_ISR 不允许中断内删除消息邮箱
* OS_ERR_INVALID_OPT 无效的删除选项
* OS_ERR_TASK_WAITING 有任务正在等待消息邮箱
* OS_ERR_EVENT_TYPE 错误的事件类型
* OS_ERR_PEVENT_NULL 无效的事件控制块指针
*
* Returns : pevent 删除失败
* (OS_EVENT *)0 删除成功
*
****************************************************************************************
*/
#if OS_MBOX_DEL_EN > 0
OS_EVENT *OSMboxDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
BOOLEAN tasks_waiting;
if (OSIntNesting > 0) { /* 不能在中断中删除 */
*err = OS_ERR_DEL_ISR;
return (pevent);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */
*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; /* 返还事件控制块 */
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; /* 返还事件控制块 */
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*/
/*
************************************************************************************
* 请求消息邮箱
*
* brief : 该函数用来请求消息邮箱
*
* pevent : 指向事件控制块的指针
*
* timeout : 等待超时.
*
* err : 指向错误代码的指针,可能取值:
*
* OS_NO_ERR 成功
* OS_TIMEOUT 超时
* OS_ERR_EVENT_TYPE 错误的事件类型
* OS_ERR_PEND_ISR 不允许在中断中请求
* OS_ERR_PEVENT_NULL 无效的事件控制块指针
*
**************************************************************************************
*/
void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
void *msg;
if (OSIntNesting > 0) { /* 中断内不允许请求消息 */
*err = OS_ERR_PEND_ISR;
return ((void *)0);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */
*err = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* 错误的事件类型 */
*err = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
msg = pevent->OSEventPtr;
if (msg != (void *)0) { /* 邮箱有消息 */
pevent->OSEventPtr = (void *)0; /* 消息返回,清空邮箱 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (msg);
}
OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* 等待消息 */
OSTCBCur->OSTCBDly = timeout; /* 记录超时 */
OS_EventTaskWait(pevent); /* 是任务等待 */
OS_EXIT_CRITICAL();
OS_Sched(); /* 任务调度 */
OS_ENTER_CRITICAL();
msg = OSTCBCur->OSTCBMsg;
if (msg != (void *)0) { /* 获得消息 */
OSTCBCur->OSTCBMsg = (void *)0; /* 清空邮箱 */
OSTCBCur->OSTCBStat = OS_STAT_RDY;
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* 取消TCB ECB关联 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (msg);
}
OS_EventTO(pevent); /* 超时使任务就绪 */
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT;
return ((void *)0);
}
/*$PAGE*/
/*
*************************************************************************************
* 向邮箱发送一则消息
*
* brief : 该函数用于向消息邮箱发送一则消息
*
* pevent : 指向事件控制块的指针
*
* msg : 消息
*
* Returns : OS_NO_ERR 成功
* OS_MBOX_FULL 邮箱中已经存在消息
* OS_ERR_EVENT_TYPE 错误的事件类型
* OS_ERR_PEVENT_NULL 无效的事件控制块指针
* OS_ERR_POST_NULL_PTR 消息为空
**************************************************************************************
*/
#if OS_MBOX_POST_EN > 0
INT8U OSMboxPost (OS_EVENT *pevent, void *msg)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */
return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0) { /* 发送的消息不能为空 */
return (OS_ERR_POST_NULL_PTR);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* 错误的事件类型 */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { /* 是否有任务等待消息 */
OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX); /* 使最高优先级等待任务就绪 */
OS_EXIT_CRITICAL();
OS_Sched(); /* 任务调度 */
return (OS_NO_ERR);
}
if (pevent->OSEventPtr != (void *)0) { /* 邮箱中不应该已经存在消息 */
OS_EXIT_CRITICAL();
return (OS_MBOX_FULL);
}
pevent->OSEventPtr = msg; /* 将消息置邮箱内 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
**************************************************************************************
* 向邮箱发送一则消息
*
* brief : 该函数用于向邮箱发送一则消息
*
* pevent : 指向事件控制块的指针
*
* msg : 发送到邮箱的消息指针
*
* opt : 发送选项
* OS_POST_OPT_NONE 消息发送给最高优先级就绪任务
* OS_POST_OPT_BROADCAST 消息发送给所有等待任务
*
* Returns : OS_NO_ERR 成功
* OS_MBOX_FULL 邮箱满
* OS_ERR_EVENT_TYPE 错误的事件类型.
* OS_ERR_PEVENT_NULL 无效的事件控制块指针
* OS_ERR_POST_NULL_PTR 发送的消息不能为空
*
*****************************************************************************************
*/
#if OS_MBOX_POST_OPT_EN > 0
INT8U OSMboxPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */
return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0) { /* 发送的消息不能为空 */
return (OS_ERR_POST_NULL_PTR);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* 错误的事件类型 */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { /* 是否有任务等待消息 */
if ((opt & OS_POST_OPT_BROADCAST) != 0x00) { /* 是否广播消息 */
while (pevent->OSEventGrp != 0x00) { /* 就绪所有等待任务 */
OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);
}
} else {
OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);/* 就绪最高优先级等待任务 */
}
OS_EXIT_CRITICAL();
OS_Sched(); /* 任务调度 */
return (OS_NO_ERR);
}
if (pevent->OSEventPtr != (void *)0) { /* 确保邮箱为空 */
OS_EXIT_CRITICAL();
return (OS_MBOX_FULL);
}
pevent->OSEventPtr = msg; /* 消息置于邮箱内 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*****************************************************************************************
* 查询邮箱
*
* brief : 该函数用于查询消息邮箱
*
* pevent : 指向事件控制块的指针
*
* pdata : 保存邮箱信息的数据结构指针
*
* Returns : OS_NO_ERR 成功
* OS_ERR_EVENT_TYPE 错误的事件类型
* OS_ERR_PEVENT_NULL 无效的事件控制块指针
*****************************************************************************************
*/
#if OS_MBOX_QUERY_EN > 0
INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
INT8U *psrc;
INT8U *pdest;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* 错误的时间类型 */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pdata->OSEventGrp = pevent->OSEventGrp; /* 复制等待任务链表 */
psrc = &pevent->OSEventTbl[0];
pdest = &pdata->OSEventTbl[0];
#if OS_EVENT_TBL_SIZE > 0
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 1
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 2
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 3
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 4
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 5
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 6
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 7
*pdest = *psrc;
#endif
pdata->OSMsg = pevent->OSEventPtr; /* 复制邮箱内消息 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
#endif
uC/OS-II源码解析(os_mbox.c)
最新推荐文章于 2021-11-22 19:15:17 发布