📄 os_flag.c
字号:
OS_FLAGS OSFlagPend (OS_FLAG_GRP *p_grp,
OS_FLAGS flags,
OS_TICK timeout,
OS_OPT opt,
CPU_TS *p_ts,
OS_ERR *p_err)
{
CPU_BOOLEAN consume;
OS_FLAGS flags_rdy;
OS_OPT mode;
OS_PEND_DATA pend_data;
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return ((OS_FLAGS)0);
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from ISR ... */
*p_err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return ((OS_FLAGS)0);
}
#endif
#if OS_CFG_ARG_CHK_EN > 0u
if (p_grp == (OS_FLAG_GRP *)0) { /* Validate arguments */
*p_err = OS_ERR_OBJ_PTR_NULL;
return ((OS_FLAGS)0);
}
#endif
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
if (p_grp->Type != OS_OBJ_TYPE_FLAG) { /* Validate that we are pointing at an event flag */
*p_err = OS_ERR_OBJ_TYPE;
return ((OS_FLAGS)0);
}
#endif
if ((opt & OS_OPT_PEND_FLAG_CONSUME) != (OS_OPT)0) { /* See if we need to consume the flags */
consume = DEF_TRUE;
} else {
consume = DEF_FALSE;
}
if (p_ts != (CPU_TS *)0) {
*p_ts = (CPU_TS)0; /* Initialize the returned timestamp */
}
mode = opt & OS_OPT_PEND_FLAG_MASK;
CPU_CRITICAL_ENTER();
switch (mode) {
case OS_OPT_PEND_FLAG_SET_ALL: /* See if all required flags are set */
flags_rdy = (OS_FLAGS)(p_grp->Flags & flags); /* Extract only the bits we want */
if (flags_rdy == flags) { /* Must match ALL the bits that we want */
if (consume == DEF_TRUE) { /* See if we need to consume the flags */
p_grp->Flags &= ~flags_rdy; /* Clear ONLY the flags that we wanted */
}
OSTCBCurPtr->FlagsRdy = flags_rdy; /* Save flags that were ready */
if (p_ts != (CPU_TS *)0) {
*p_ts = p_grp->TS;
}
CPU_CRITICAL_EXIT(); /* Yes, condition met, return to caller */
*p_err = OS_ERR_NONE;
return (flags_rdy);
} else { /* Block task until events occur or timeout */
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* Specified non-blocking so task would block */
return ((OS_FLAGS)0);
} else { /* Specified blocking so check is scheduler is locked */
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* See if called with scheduler locked ... */
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_SCHED_LOCKED; /* ... can't PEND when locked */
return ((OS_FLAGS)0);
}
}
OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
OS_FlagBlock(&pend_data,
p_grp,
flags,
opt,
timeout);
OS_CRITICAL_EXIT_NO_SCHED();
}
break;
case OS_OPT_PEND_FLAG_SET_ANY:
flags_rdy = (OS_FLAGS)(p_grp->Flags & flags); /* Extract only the bits we want */
if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */
if (consume == DEF_TRUE) { /* See if we need to consume the flags */
p_grp->Flags &= ~flags_rdy; /* Clear ONLY the flags that we got */
}
OSTCBCurPtr->FlagsRdy = flags_rdy; /* Save flags that were ready */
if (p_ts != (CPU_TS *)0) {
*p_ts = p_grp->TS;
}
CPU_CRITICAL_EXIT(); /* Yes, condition met, return to caller */
*p_err = OS_ERR_NONE;
return (flags_rdy);
} else { /* Block task until events occur or timeout */
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* Specified non-blocking so task would block */
return ((OS_FLAGS)0);
} else { /* Specified blocking so check is scheduler is locked */
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* See if called with scheduler locked ... */
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_SCHED_LOCKED; /* ... can't PEND when locked */
return ((OS_FLAGS)0);
}
}
OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
OS_FlagBlock(&pend_data,
p_grp,
flags,
opt,
timeout);
OS_CRITICAL_EXIT_NO_SCHED();
}
break;
#if OS_CFG_FLAG_MODE_CLR_EN > 0u
case OS_OPT_PEND_FLAG_CLR_ALL: /* See if all required flags are cleared */
flags_rdy = (OS_FLAGS)(~p_grp->Flags & flags); /* Extract only the bits we want */
if (flags_rdy == flags) { /* Must match ALL the bits that we want */
if (consume == DEF_TRUE) { /* See if we need to consume the flags */
p_grp->Flags |= flags_rdy; /* Set ONLY the flags that we wanted */
}
OSTCBCurPtr->FlagsRdy = flags_rdy; /* Save flags that were ready */
if (p_ts != (CPU_TS *)0) {
*p_ts = p_grp->TS;
}
CPU_CRITICAL_EXIT(); /* Yes, condition met, return to caller */
*p_err = OS_ERR_NONE;
return (flags_rdy);
} else { /* Block task until events occur or timeout */
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* Specified non-blocking so task would block */
return ((OS_FLAGS)0);
} else { /* Specified blocking so check is scheduler is locked */
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* See if called with scheduler locked ... */
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_SCHED_LOCKED; /* ... can't PEND when locked */
return ((OS_FLAGS)0);
}
}
OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
OS_FlagBlock(&pend_data,
p_grp,
flags,
opt,
timeout);
OS_CRITICAL_EXIT_NO_SCHED();
}
break;
case OS_OPT_PEND_FLAG_CLR_ANY:
flags_rdy = (OS_FLAGS)(~p_grp->Flags & flags); /* Extract only the bits we want */
if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */
if (consume == DEF_TRUE) { /* See if we need to consume the flags */
p_grp->Flags |= flags_rdy; /* Set ONLY the flags that we got */
}
OSTCBCurPtr->FlagsRdy = flags_rdy; /* Save flags that were ready */
if (p_ts != (CPU_TS *)0) {
*p_ts = p_grp->TS;
}
CPU_CRITICAL_EXIT(); /* Yes, condition met, return to caller */
*p_err = OS_ERR_NONE;
return (flags_rdy);
} else { /* Block task until events occur or timeout */
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* Specified non-blocking so task would block */
return ((OS_FLAGS)0);
} else { /* Specified blocking so check is scheduler is locked */
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* See if called with scheduler locked ... */
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_SCHED_LOCKED; /* ... can't PEND when locked */
return ((OS_FLAGS)0);
}
}
OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
OS_FlagBlock(&pend_data,
p_grp,
flags,
opt,
timeout);
OS_CRITICAL_EXIT_NO_SCHED();
}
break;
#endif
default:
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_OPT_INVALID;
return ((OS_FLAGS)0);
}
OSSched(); /* Find next HPT ready to run */
CPU_CRITICAL_ENTER();
switch (OSTCBCurPtr->PendStatus) {
case OS_STATUS_PEND_OK: /* We got the vent flags */
if (p_ts != (CPU_TS *)0) {
*p_ts = OSTCBCurPtr->TS;
}
*p_err = OS_ERR_NONE;
break;
case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
if (p_ts != (CPU_TS *)0) {
*p_ts = OSTCBCurPtr->TS;
}
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_PEND_ABORT;
return ((OS_FLAGS)0);
case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get semaphore within timeout */
if (p_ts != (CPU_TS *)0) {
*p_ts = (CPU_TS )0;
}
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_TIMEOUT;
return ((OS_FLAGS)0);
case OS_STATUS_PEND_DEL: /* Indicate that object pended on has been deleted */
if (p_ts != (CPU_TS *)0) {
*p_ts = OSTCBCurPtr->TS;
}
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_OBJ_DEL;
return ((OS_FLAGS)0);
default:
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_STATUS_INVALID;
return ((OS_FLAGS)0);
}
flags_rdy = OSTCBCurPtr->FlagsRdy;
if (consume == DEF_TRUE) { /* See if we need to consume the flags */
switch (mode) {
case OS_OPT_PEND_FLAG_SET_ALL:
case OS_OPT_PEND_FLAG_SET_ANY: /* Clear ONLY the flags we got */
p_grp->Flags &= ~flags_rdy;
break;
#if OS_CFG_FLAG_MODE_CLR_EN > 0u
case OS_OPT_PEND_FLAG_CLR_ALL:
case OS_OPT_PEND_FLAG_CLR_ANY: /* Set ONLY the flags we got */
p_grp->Flags |= flags_rdy;
break;
#endif
default:
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_OPT_INVALID;
return ((OS_FLAGS)0);
}
}
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_NONE; /* Event(s) must have occurred */
return (flags_rdy);
}
/*$PAGE*/
/*
************************************************************************************************************************
* ABORT WAITING ON AN EVENT FLAG GROUP
*
* Description: This function aborts & readies any tasks currently waiting on an event flag group. This function should
* be used to fault-abort the wait on the event flag group, rather than to normally post to the event flag
* group OSFlagPost().
*
* Arguments : p_grp is a pointer to the event flag group
*
* opt determines the type of ABORT performed:
*
* OS_OPT_PEND_ABORT_1 ABORT wait for a single task (HPT) waiting on the event flag
* OS_OPT_PEND_ABORT_ALL ABORT wait for ALL tasks that are waiting on the event flag
* OS_OPT_POST_NO_SCHED Do not call the scheduler
*
* p_err is a pointer to a variable that will contain an error code returned by this function.
*
* OS_ERR_NONE At least one task waiting on the event flag group and was
* readied and informed of the aborted wait; check return value
* for the number of tasks whose wait on the event flag group
* was aborted.
* OS_ERR_OBJ_PTR_NULL If 'p_grp' is a NULL pointer.
* OS_ERR_OBJ_TYPE If 'p_grp' is not pointing at an event flag group
* OS_ERR_OPT_INVALID If you specified an invalid option
* OS_ERR_PEND_ABORT_ISR If you called this function from an ISR
* OS_ERR_PEND_ABORT_NONE No task were pending
*
* Returns : == 0 if no tasks were waiting on the event flag group, or upon error.
* > 0 if one or more tasks waiting on the event flag group are now readied and informed.
************************************************************************************************************************
*/
#if OS_CFG_FLAG_PEND_ABORT_EN > 0u
OS_OBJ_QTY OSFlagPendAbort (OS_FLAG_GRP *p_grp,
OS_OPT opt,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -