📄 os_task.c
字号:
* need the timestamp.
*
* p_err 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_PEND_ABORT
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the queue was not empty
* OS_ERR_Q_EMPTY
* OS_ERR_SCHED_LOCKED If the scheduler is locked
* OS_ERR_TIMEOUT A message was not received within the specified timeout
* would lead to a suspension.
*
* Returns : A pointer to the message received or a NULL pointer upon error.
*
* Note(s) : 1) It is possible to receive NULL pointers when there are no errors.
************************************************************************************************************************
*/
#if OS_CFG_TASK_Q_EN > 0u
void *OSTaskQPend (OS_TICK timeout,
OS_OPT opt,
OS_MSG_SIZE *p_msg_size,
CPU_TS *p_ts,
OS_ERR *p_err)
{
OS_MSG_Q *p_msg_q;
void *p_void;
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return ((void *)0);
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't Pend from an ISR */
*p_err = OS_ERR_PEND_ISR;
return ((void *)0);
}
#endif
#if OS_CFG_ARG_CHK_EN > 0u /* ---------------- VALIDATE ARGUMENTS ------------------ */
if (p_msg_size == (OS_MSG_SIZE *)0) { /* User must supply a valid destination for msg size */
*p_err = OS_ERR_PTR_INVALID;
return ((void *)0);
}
switch (opt) { /* User must supply a valid option */
case OS_OPT_PEND_BLOCKING:
case OS_OPT_PEND_NON_BLOCKING:
break;
default:
*p_err = OS_ERR_OPT_INVALID;
return ((void *)0);
}
#endif
if (p_ts != (CPU_TS *)0) {
*p_ts = (CPU_TS )0; /* Initialize the returned timestamp */
}
CPU_CRITICAL_ENTER();
p_msg_q = &OSTCBCurPtr->MsgQ; /* Any message waiting in the message queue? */
p_void = OS_MsgQGet(p_msg_q,
p_msg_size,
p_ts,
p_err);
if (*p_err == OS_ERR_NONE) {
#if OS_CFG_TASK_PROFILE_EN > 0u
if (p_ts != (CPU_TS *)0) {
OSTCBCurPtr->MsgQPendTime = OS_TS_GET() - *p_ts;
if (OSTCBCurPtr->MsgQPendTime > OSTCBCurPtr->MsgQPendTimeMax) {
OSTCBCurPtr->MsgQPendTimeMax = OSTCBCurPtr->MsgQPendTime;
}
}
#endif
CPU_CRITICAL_EXIT();
return (p_void); /* Yes, Return oldest message received */
}
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
CPU_CRITICAL_EXIT();
return ((void *)0);
} else { /* Yes */
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't block when the scheduler is locked */
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_SCHED_LOCKED;
return ((void *)0);
}
}
OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
OS_Pend((OS_PEND_DATA *)0, /* Block task pending on Message */
(OS_PEND_OBJ *)0,
(OS_STATE )OS_TASK_PEND_ON_TASK_Q,
(OS_TICK )timeout);
OS_CRITICAL_EXIT_NO_SCHED();
OSSched(); /* Find the next highest priority task ready to run */
CPU_CRITICAL_ENTER();
switch (OSTCBCurPtr->PendStatus) {
case OS_STATUS_PEND_OK: /* Extract message from TCB (Put there by Post) */
p_void = OSTCBCurPtr->MsgPtr;
*p_msg_size = OSTCBCurPtr->MsgSize;
if (p_ts != (CPU_TS *)0) {
*p_ts = OSTCBCurPtr->TS;
#if OS_CFG_TASK_PROFILE_EN > 0u
OSTCBCurPtr->MsgQPendTime = OS_TS_GET() - OSTCBCurPtr->TS;
if (OSTCBCurPtr->MsgQPendTime > OSTCBCurPtr->MsgQPendTimeMax) {
OSTCBCurPtr->MsgQPendTimeMax = OSTCBCurPtr->MsgQPendTime;
}
#endif
}
*p_err = OS_ERR_NONE;
break;
case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
p_void = (void *)0;
*p_msg_size = (OS_MSG_SIZE)0;
if (p_ts != (CPU_TS *)0) {
*p_ts = (CPU_TS )0;
}
*p_err = OS_ERR_PEND_ABORT;
break;
case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get event within TO */
default:
p_void = (void *)0;
*p_msg_size = (OS_MSG_SIZE)0;
if (p_ts != (CPU_TS *)0) {
*p_ts = OSTCBCurPtr->TS;
}
*p_err = OS_ERR_TIMEOUT;
break;
}
CPU_CRITICAL_EXIT();
return (p_void); /* Return received message */
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* ABORT WAITING FOR A MESSAGE
*
* Description: This function aborts & readies the task specified. This function should be used to fault-abort the wait
* for a message, rather than to normally post the message to the task via OSTaskQPost().
*
* Arguments : p_tcb is a pointer to the task to pend abort
*
* opt provides options for this function:
*
* OS_OPT_POST_NONE No option specified
* OS_OPT_POST_NO_SCHED Indicates that the scheduler will not be called.
*
* p_err is a pointer to a variable that will contain an error code returned by this function.
*
* OS_ERR_NONE If the task was readied and informed of the aborted wait
* OS_ERR_PEND_ABORT_ISR If you called this function from an ISR
* OS_ERR_PEND_ABORT_NONE If task was not pending on a message and thus there is nothing to
* abort.
* OS_ERR_PEND_ABORT_SELF If you passed a NULL pointer for 'p_tcb'
*
* Returns : == DEF_FALSE if task was not waiting for a message, or upon error.
* == DEF_TRUE if task was waiting for a message and was readied and informed.
************************************************************************************************************************
*/
#if (OS_CFG_TASK_Q_EN > 0u) && (OS_CFG_TASK_Q_PEND_ABORT_EN > 0u)
CPU_BOOLEAN OSTaskQPendAbort (OS_TCB *p_tcb,
OS_OPT opt,
OS_ERR *p_err)
{
CPU_TS ts;
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (DEF_FALSE);
}
#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_ABORT_ISR; /* ... can't Pend Abort from an ISR */
return (DEF_FALSE);
}
#endif
CPU_CRITICAL_ENTER();
#if OS_CFG_ARG_CHK_EN > 0u
if ((p_tcb == (OS_TCB *)0) || /* Pend abort self? */
(p_tcb == OSTCBCurPtr)) {
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_PEND_ABORT_SELF; /* ... doesn't make sense */
return (DEF_FALSE);
}
#endif
if (p_tcb->PendOn != OS_TASK_PEND_ON_TASK_Q) { /* Is task waiting for a message? */
CPU_CRITICAL_EXIT(); /* No */
*p_err = OS_ERR_PEND_ABORT_NONE;
return (DEF_FALSE);
}
OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();
ts = OS_TS_GET(); /* Get timestamp of when the abort occurred */
OS_PendAbort((OS_PEND_OBJ *)0, /* Abort the pend */
p_tcb,
ts);
OS_CRITICAL_EXIT_NO_SCHED();
if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
OSSched(); /* Run the scheduler */
}
*p_err = OS_ERR_NONE;
return (DEF_TRUE);
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* POST MESSAGE TO A TASK
*
* Description: This function sends a message to a task
*
* Arguments : p_tcb is a pointer to the TCB of the task receiving a message. If you specify a NULL pointer then
* the message will be posted to the task's queue of the calling task. In other words, you'd be
* posting a message to yourself.
*
* p_void is a pointer to the message to send.
*
* msg_size is the size of the message sent (in #bytes)
*
* opt specifies whether the post will be FIFO or LIFO:
*
* OS_OPT_POST_FIFO Post at the end of the queue
* OS_OPT_POST_LIFO Post at the front of the queue
*
* OS_OPT_POST_NO_SCHED Do not run the scheduler after the post
*
* Note(s): 1) OS_OPT_POST_NO_SCHED can be added with one of the other options.
*
*
* p_err is a pointer to a variable that will hold the error code associated
* with the outcome of this call. Errors can be:
*
* OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_Q_MAX If the queue is full
* OS_ERR_MSG_POOL_EMPTY If there are no more OS_MSGs available from the pool
*
* Returns : none
************************************************************************************************************************
*/
#if OS_CFG_TASK_Q_EN > 0u
void OSTaskQPost (OS_TCB *p_tcb,
void *p_void,
OS_MSG_SIZE msg_size,
OS_OPT opt,
OS_ERR *p_err)
{
CPU_TS ts;
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
ts = OS_TS_GET(); /* Get timestamp */
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) {
OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_MSG, /* Post to ISR queue */
(void *)p_tcb,
(void *)p_void,
(OS_MSG_SIZE)msg_size,
(OS_FLAGS )0,
(OS_OPT )opt,
(CPU_TS )ts,
(OS_ERR *)p_err);
return;
}
#endif
OS_TaskQPost(p_tcb,
p_void,
msg_size,
opt,
ts,
p_err);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -