📄 os_mbox.c
字号:
break;
case OS_DEL_ALWAYS: /* Always delete the mailbox */
while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mailbox */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_OK);
}
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent; /* 取得空闲的事件控制块ECB */
OS_EXIT_CRITICAL();
if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
OS_Sched(); /* Find highest priority task ready to run */
}
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */
break;
default:
OS_EXIT_CRITICAL();
*perr = OS_ERR_INVALID_OPT;
pevent_return = pevent;
break;
}
return (pevent_return);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* PEND ON MAILBOX FOR A MESSAGE
*
* Description: This function waits for a message to be sent to a mailbox
*
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for a message to arrive at the mailbox up to the amount of time
* specified by this argument. If you specify 0, however, your task will wait
* forever at the specified mailbox or, until a message arrives.
*
* 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 mailbox was aborted.
* OS_ERR_EVENT_TYPE Invalid event type
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
*
* Returns : != (void *)0 is a pointer to the message received
* == (void *)0 if no message was received or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass the proper pointer to the event control block.
*********************************************************************************************************
*/
/*$PAGE*/
void *OSMboxPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr)
{
void *pmsg;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /*事件控制块指针是否有效 */
*perr = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* 事件控制块类型是否有效 */
*perr = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
if (OSIntNesting > 0u) { /* 查看是否在中断服务程序ISR中调用本函数 */
*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return ((void *)0);
}
if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return ((void *)0);
}
OS_ENTER_CRITICAL();
pmsg = pevent->OSEventPtr;
if (pmsg != (void *)0) { /* See if there is already a message */
pevent->OSEventPtr = (void *)0; /* 清邮箱 */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (pmsg); /* 返回获得的消息(或空指针) */
}
OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready to run */
OS_ENTER_CRITICAL();
switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
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; /* Indicate that we aborted */
break;
case OS_STAT_PEND_TO:
default:
OS_EventTaskRemove(OSTCBCur, pevent);
pmsg = (void *)0;
*perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
break;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
#if (OS_EVENT_MULTI_EN > 0u)
OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
OSTCBCur->OSTCBMsg = (void *)0; /* 清除获得的消息 */
OS_EXIT_CRITICAL();
return (pmsg); /* 返回获得的消息 */
}
/*$PAGE*/
/*
*********************************************************************************************************
* ABORT WAITING ON A MESSAGE MAILBOX
*
* Description: This function aborts & readies any tasks currently waiting on a mailbox. This function
* should be used to fault-abort the wait on the mailbox, rather than to normally signal
* the mailbox via OSMboxPost() or OSMboxPostOpt().
*
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox.
*
* opt determines the type of ABORT performed:
* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
* mailbox
* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
* mailbox
*
* 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 mailbox.
* OS_ERR_PEND_ABORT At least one task waiting on the mailbox was readied
* and informed of the aborted wait; check return value
* for the number of tasks whose wait on the mailbox
* was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : == 0 if no tasks were waiting on the mailbox, or upon error.
* > 0 if one or more tasks waiting on the mailbox are now readied and informed.
*********************************************************************************************************
*/
#if OS_MBOX_PEND_ABORT_EN > 0u
INT8U OSMboxPendAbort (OS_EVENT *pevent,
INT8U opt,
INT8U *perr)
{
INT8U nbr_tasks;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /*事件控制块指针是否有效 */
*perr = OS_ERR_PEVENT_NULL;
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* 事件控制块类型是否有效*/
*perr = OS_ERR_EVENT_TYPE;
return (0u);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task waiting on mailbox? */
nbr_tasks = 0u;
switch (opt) {
case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */
while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on mailbox */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
nbr_tasks++;
}
break;
case OS_PEND_OPT_NONE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -