?? os_core.c
字號:
* case of any error(s).
*********************************************************************************************************
*/
/*$PAGE*/
#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0))
INT16U OSEventPendMulti (OS_EVENT **pevents_pend, OS_EVENT **pevents_rdy, void **pmsgs_rdy, INT16U timeout, INT8U *perr)
{
OS_EVENT **pevents;
OS_EVENT *pevent;
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
OS_Q *pq;
#endif
BOOLEAN events_rdy;
INT16U events_rdy_nbr;
INT8U events_stat;
#if (OS_CRITICAL_METHOD == 3) /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
#if (OS_ARG_CHK_EN > 0)
if (perr == (INT8U *)0) { /* Validate 'perr' */
return (0);
}
if (pevents_pend == (OS_EVENT **)0) { /* Validate 'pevents_pend' */
*perr = OS_ERR_PEVENT_NULL;
return (0);
}
if (pevents_rdy == (OS_EVENT **)0) { /* Validate 'pevents_rdy' */
*perr = OS_ERR_PEVENT_NULL;
return (0);
}
if (pmsgs_rdy == (void **)0) { /* Validate 'pmsgs_rdy' */
*perr = OS_ERR_PEVENT_NULL;
return (0);
}
#endif
*pevents_rdy = (OS_EVENT *)0; /* Init array to NULL in case of errors */
pevents = pevents_pend;
pevent = *pevents;
while (pevent != (OS_EVENT *)0) {
switch (pevent->OSEventType) { /* Validate event block types */
#if (OS_SEM_EN > 0)
case OS_EVENT_TYPE_SEM:
break;
#endif
#if (OS_MBOX_EN > 0)
case OS_EVENT_TYPE_MBOX:
break;
#endif
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
case OS_EVENT_TYPE_Q:
break;
#endif
case OS_EVENT_TYPE_MUTEX:
case OS_EVENT_TYPE_FLAG:
default:
*perr = OS_ERR_EVENT_TYPE;
return (0);
}
pevents++;
pevent = *pevents;
}
if (OSIntNesting > 0) { /* See if called from ISR ... */
*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return (0);
}
if (OSLockNesting > 0) { /* See if called with scheduler locked ... */
*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return (0);
}
/*$PAGE*/
OS_ENTER_CRITICAL();
events_rdy = OS_FALSE;
events_rdy_nbr = 0;
events_stat = OS_STAT_RDY;
pevents = pevents_pend;
pevent = *pevents;
while (pevent != (OS_EVENT *)0) { /* See if any events already available */
switch (pevent->OSEventType) {
#if (OS_SEM_EN > 0)
case OS_EVENT_TYPE_SEM:
if (pevent->OSEventCnt > 0) { /* If semaphore count > 0, resource available; */
pevent->OSEventCnt--; /* ... decrement semaphore, ... */
*pevents_rdy++ = pevent; /* ... and return available semaphore event */
events_rdy = OS_TRUE;
*pmsgs_rdy++ = (void *)0; /* NO message returned for semaphores */
events_rdy_nbr++;
} else {
events_stat |= OS_STAT_SEM; /* Configure multi-pend for semaphore events */
}
break;
#endif
#if (OS_MBOX_EN > 0)
case OS_EVENT_TYPE_MBOX:
if (pevent->OSEventPtr != (void *)0) { /* If mailbox NOT empty; ... */
/* ... return available message, ... */
*pmsgs_rdy++ = (void *)pevent->OSEventPtr;
pevent->OSEventPtr = (void *)0;
*pevents_rdy++ = pevent; /* ... and return available mailbox event */
events_rdy = OS_TRUE;
events_rdy_nbr++;
} else {
events_stat |= OS_STAT_MBOX; /* Configure multi-pend for mailbox events */
}
break;
#endif
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
case OS_EVENT_TYPE_Q:
pq = (OS_Q *)pevent->OSEventPtr;
if (pq->OSQEntries > 0) { /* If queue NOT empty; ... */
/* ... return available message, ... */
*pmsgs_rdy++ = (void *)*pq->OSQOut++;
if (pq->OSQOut == pq->OSQEnd) { /* If OUT ptr at queue end, ... */
pq->OSQOut = pq->OSQStart; /* ... wrap to queue start */
}
pq->OSQEntries--; /* Update number of queue entries */
*pevents_rdy++ = pevent; /* ... and return available queue event */
events_rdy = OS_TRUE;
events_rdy_nbr++;
} else {
events_stat |= OS_STAT_Q; /* Configure multi-pend for queue events */
}
break;
#endif
case OS_EVENT_TYPE_MUTEX:
case OS_EVENT_TYPE_FLAG:
default:
OS_EXIT_CRITICAL();
*pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */
*perr = OS_ERR_EVENT_TYPE;
return (events_rdy_nbr);
}
pevents++;
pevent = *pevents;
}
if ( events_rdy == OS_TRUE) { /* Return any events already available */
*pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (events_rdy_nbr);
}
/*$PAGE*/
/* Otherwise, must wait until any event occurs */
OSTCBCur->OSTCBStat |= events_stat | /* Resource not available, ... */
OS_STAT_MULTI; /* ... pend on multiple events */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */
OS_EventTaskWaitMulti(pevents_pend); /* Suspend task until events or timeout occurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready */
OS_ENTER_CRITICAL();
switch (OSTCBCur->OSTCBStatPend) { /* Handle event posted, aborted, or timed-out */
case OS_STAT_PEND_OK:
case OS_STAT_PEND_ABORT:
pevent = OSTCBCur->OSTCBEventPtr;
if (pevent != (OS_EVENT *)0) { /* If task event ptr != NULL, ... */
*pevents_rdy++ = pevent; /* ... return available event ... */
*pevents_rdy = (OS_EVENT *)0; /* ... & NULL terminate return event array */
events_rdy_nbr++;
} else { /* Else NO event available, handle as timeout */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_TO;
OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend);
}
break;
case OS_STAT_PEND_TO: /* If events timed out, ... */
default: /* ... remove task from events' wait lists */
OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend);
break;
}
switch (OSTCBCur->OSTCBStatPend) {
case OS_STAT_PEND_OK:
switch (pevent->OSEventType) { /* Return event's message */
#if (OS_SEM_EN > 0)
case OS_EVENT_TYPE_SEM:
*pmsgs_rdy++ = (void *)0; /* NO message returned for semaphores */
break;
#endif
#if ((OS_MBOX_EN > 0) || \
((OS_Q_EN > 0) && (OS_MAX_QS > 0)))
case OS_EVENT_TYPE_MBOX:
case OS_EVENT_TYPE_Q:
*pmsgs_rdy++ = (void *)OSTCBCur->OSTCBMsg; /* Return received message */
break;
#endif
case OS_EVENT_TYPE_MUTEX:
case OS_EVENT_TYPE_FLAG:
default:
OS_EXIT_CRITICAL();
*pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */
*perr = OS_ERR_EVENT_TYPE;
return (events_rdy_nbr);
}
*perr = OS_ERR_NONE;
break;
case OS_STAT_PEND_ABORT:
*pmsgs_rdy++ = (void *)0; /* NO message returned for abort */
*perr = OS_ERR_PEND_ABORT; /* Indicate that event aborted */
break;
case OS_STAT_PEND_TO:
default:
*pmsgs_rdy++ = (void *)0; /* NO message returned for timeout */
*perr = OS_ERR_TIMEOUT; /* Indicate that events timed out */
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 */
OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
OSTCBCur->OSTCBMsg = (void *)0; /* Clear task message */
OS_EXIT_CRITICAL();
return (events_rdy_nbr);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* INITIALIZATION
*
* Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to
* creating any uC/OS-II object and, prior to calling OSStart().
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
void OSInit (void)
{
OSInitHookBegin(); /* Call port specific initialization code */
OS_InitMisc(); /* Initialize miscellaneous variables */
OS_InitRdyList(); /* Initialize the Ready List */
OS_InitTCBList(); /* Initialize the free list of OS_TCBs */
OS_InitEventList(); /* Initialize the free list of OS_EVENTs */
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_FlagInit(); /* Initialize the event flag structures */
#endif
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
OS_MemInit(); /* Initialize the memory manager */
#endif
#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
OS_QInit(); /* Initialize the message queue structures */
#endif
OS_InitTaskIdle(); /* Create the Idle Task */
#if OS_TASK_STAT_EN > 0
OS_InitTaskStat(); /* Create the Statistic Task */
#endif
#if OS_TMR_EN > 0
OSTmr_Init(); /* Initialize the Timer Manager */
#endif
OSInitHookEnd(); /* Call port specific init. code */
#if OS_DEBUG_EN > 0
OSDebugInit();
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* ENTER ISR
*
* Description: This function is used to notify uC/OS-II that you are about to service an interrupt
* service routine (ISR). This allows uC/OS-II to keep track of interrupt nesting and thus
* only perform rescheduling at the last nested ISR.
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -