📄 os_core.c
字号:
/* Prevent OSLockNesting from wrapping back to 0 */
OSLockNesting++; /* Increment lock nesting level */
}
}
OS_EXIT_CRITICAL();
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* ENABLE SCHEDULING
*
* Description: This function is used to re-allow rescheduling.
*
* Arguments : none
*
* Returns : none
*
* Notes : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair. In other words, for every
* call to OSSchedLock() you MUST have a call to OSSchedUnlock().
*********************************************************************************************************
*/
#if OS_SCHED_LOCK_EN > 0
void OSSchedUnlock(void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (OSRunning == OS_TRUE)
{
/* Make sure multitasking is running */
OS_ENTER_CRITICAL();
if (OSLockNesting > 0)
{
/* Do not decrement if already 0 */
OSLockNesting--; /* Decrement lock nesting level */
if (OSLockNesting == 0)
{
/* See if scheduler is enabled and ... */
if (OSIntNesting == 0)
{
/* ... not in an ISR */
OS_EXIT_CRITICAL();
OS_Sched(); /* See if a HPT is ready */
}
else
{
OS_EXIT_CRITICAL();
}
}
else
{
OS_EXIT_CRITICAL();
}
}
else
{
OS_EXIT_CRITICAL();
}
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* START MULTITASKING
*
* Description: This function is used to start the multitasking process which lets uC/OS-II manages the
* task that you have created. Before you can call OSStart(), you MUST have called OSInit()
* and you MUST have created at least one task.
*
* Arguments : none
*
* Returns : none
*
* Note : OSStartHighRdy() MUST:
* a) Call OSTaskSwHook() then,
* b) Set OSRunning to OS_TRUE.
* c) Load the context of the task pointed to by OSTCBHighRdy.
* d_ Execute the task.
*********************************************************************************************************
*/
void OSStart(void)
{
if (OSRunning == OS_FALSE)
{
OS_SchedNew(); /* Find highest priority's task priority number */
OSPrioCur = OSPrioHighRdy;
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */
OSTCBCur = OSTCBHighRdy;
OSStartHighRdy(); /* Execute target specific code to start task */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* STATISTICS INITIALIZATION
*
* Description: This function is called by your application to establish CPU usage by first determining
* how high a 32-bit counter would count to in 1 second if no other tasks were to execute
* during that time. CPU usage is then determined by a low priority task which keeps track
* of this 32-bit counter every second but this time, with other tasks running. CPU usage is
* determined by:
*
* OSIdleCtr
* CPU Usage (%) = 100 * (1 - ------------)
* OSIdleCtrMax
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
#if OS_TASK_STAT_EN > 0
void OSStatInit(void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
OSTimeDly(2); /* Synchronize with clock tick */
OS_ENTER_CRITICAL();
OSIdleCtr = 0L; /* Clear idle counter */
OS_EXIT_CRITICAL();
OSTimeDly(OS_TICKS_PER_SEC / 10); /* Determine MAX. idle counter value for 1/10 second */
OS_ENTER_CRITICAL();
OSIdleCtrMax = OSIdleCtr; /* Store maximum idle counter count in 1/10 second */
OSStatRdy = OS_TRUE;
OS_EXIT_CRITICAL();
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* PROCESS SYSTEM TICK
*
* Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
* as a 'clock tick'). This function should be called by the ticker ISR but, can also be
* called by a high priority task.
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
void OSTimeTick(void)
{
OS_TCB *ptcb;
#if OS_TICK_STEP_EN > 0
BOOLEAN step;
#endif
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_TIME_TICK_HOOK_EN > 0
OSTimeTickHook(); /* Call user definable hook */
#endif
#if OS_TIME_GET_SET_EN > 0
OS_ENTER_CRITICAL(); /* Update the 32-bit tick counter */
OSTime++;
OS_EXIT_CRITICAL();
#endif
if (OSRunning == OS_TRUE)
{
#if OS_TICK_STEP_EN > 0
switch (OSTickStepState)
{
/* Determine whether we need to process a tick */
case OS_TICK_STEP_DIS:
/* Yes, stepping is disabled */
step = OS_TRUE;
break;
case OS_TICK_STEP_WAIT:
/* No, waiting for uC/OS-View to set ... */
step = OS_FALSE; /* .. OSTickStepState to OS_TICK_STEP_ONCE */
break;
case OS_TICK_STEP_ONCE:
/* Yes, process tick once and wait for next ... */
step = OS_TRUE; /* ... step command from uC/OS-View */
OSTickStepState = OS_TICK_STEP_WAIT;
break;
default:
/* Invalid case, correct situation */
step = OS_TRUE;
OSTickStepState = OS_TICK_STEP_DIS;
break;
}
if (step == OS_FALSE)
{
/* Return if waiting for step command */
return;
}
#endif
ptcb = OSTCBList; /* Point at first TCB in TCB list */
while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO)
{
/* Go through all TCBs in TCB list */
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0)
{
/* No, Delayed or waiting for event with TO */
if (--ptcb->OSTCBDly == 0)
{
/* Decrement nbr of ticks to end of delay */
/* Check for timeout */
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY)
{
ptcb->OSTCBStat &= ~(INT8U) OS_STAT_PEND_ANY; /* Yes, Clear status flag */
ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */
}
else
{
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY)
{
/* Is task suspended? */
OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
}
}
ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */
OS_EXIT_CRITICAL();
}
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* GET VERSION
*
* Description: This function is used to return the version number of uC/OS-II. The returned value
* corresponds to uC/OS-II's version number multiplied by 100. In other words, version 2.00
* would be returned as 200.
*
* Arguments : none
*
* Returns : the version number of uC/OS-II multiplied by 100.
*********************************************************************************************************
*/
INT16U OSVersion(void)
{
return (OS_VERSION);
}
/*$PAGE*/
/*
*********************************************************************************************************
* DUMMY FUNCTION
*
* Description: This function doesn't do anything. It is called by OSTaskDel().
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
#if OS_TASK_DEL_EN > 0
void OS_Dummy(void)
{
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* MAKE TASK READY TO RUN BASED ON EVENT OCCURING
*
* Description: This function is called by other uC/OS-II services and is used to ready a task that was
* waiting for an event to occur.
*
* Arguments : pevent is a pointer to the event control block corresponding to the event.
*
* pmsg is a pointer to a message. This pointer is used by message oriented services
* such as MAILBOXEs and QUEUEs. The pointer is not used when called by other
* service functions.
*
* msk is a mask that is used to clear the status byte of the TCB. For example,
* OSSemPost() will pass OS_STAT_SEM, OSMboxPost() will pass OS_STAT_MBOX etc.
*
* pend_stat is used to indicate the readied task's pending status:
*
* OS_STAT_PEND_OK Task ready due to a post (or delete), not a timeout or
* an abort.
* OS_STAT_PEND_ABORT Task ready due to an abort.
*
* Returns : none
*
* Note : This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************************************
*/
#if OS_EVENT_EN
INT8U OS_EventTaskRdy(OS_EVENT *pevent, void *pmsg, INT8U msk, INT8U pend_stat)
{
OS_TCB *ptcb;
INT8U x;
INT8U y;
INT8U prio;
#if OS_LOWEST_PRIO <= 63
INT8U bitx;
INT8U bity;
#else
INT16U bitx;
INT16U bity;
INT16U *ptbl;
#endif
#if OS_LOWEST_PRIO <= 63
y = OSUnMapTbl[pevent->OSEventGrp]; /* Find HPT waiting for message */
bity = (INT8U) (1 << y);
x = OSUnMapTbl[pevent->OSEventTbl[y]];
bitx = (INT8U) (1 << x);
prio = (INT8U) ((y << 3) + x); /* Find priority of task getting the msg */
#else
if ((pevent->OSEventGrp & 0xFF) != 0)
{
/* Find HPT waiting for message */
y = OSUnMapTbl[pevent->OSEventGrp & 0xFF];
}
else
{
y = OSUnMapTbl[(pevent->OSEventGrp >> 8) & 0xFF] + 8;
}
bity = (INT16U) (1 << y);
ptbl = &pevent->OSEventTbl[y];
if ((*ptbl & 0xFF) != 0)
{
x = OSUnMapTbl[*ptbl & 0xFF];
}
else
{
x = OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8;
}
bitx = (INT16U) (1 << x);
prio = (INT8U) ((y << 4) + x); /* Find priority of task getting the msg */
#endif
pevent->OSEventTbl[y] &= ~bitx; /* Remove this task from the waiting list */
if (pevent->OSEventTbl[y] == 0)
{
pevent->OSEventGrp &= ~bity; /* Clr group bit if this was only task pending */
}
ptcb = OSTCBPrioTbl[prio]; /* Point to this task's OS_TCB */
ptcb->OSTCBDly = 0; /* Prevent OSTimeTick() from readying task */
ptcb->OSTCBEventPtr = (OS_EVENT *) 0; /* Unlink ECB from this task */
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
ptcb->OSTCBMsg = pmsg; /* Send message directly to waiting task */
#else
pmsg = pmsg; /* Prevent compiler warning if not used */
#endif
ptcb->OSTCBStatPend = pend_stat; /* Set pend status of post or abort */
ptcb->OSTCBStat &= ~msk; /* Clear bit associated with event type */
if (ptcb->OSTCBStat == OS_STAT_RDY)
{
/* See if task is ready (could be susp'd) */
OSRdyGrp |= bity; /* Put task in the ready to run list */
OSRdyTbl[y] |= bitx;
}
return (prio);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* MAKE TASK WAIT FOR EVENT TO OCCUR
*
* Description: This function is called by other uC/OS-II services to suspend a task because an event has
* not occurred.
*
* Arguments : pevent is a pointer to the event control block for which the task will be waiting for.
*
* Returns : none
*
* Note : This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************************************
*/
#if OS_EVENT_EN
void OS_EventTaskWait(OS_EVENT *pevent)
{
INT8U y;
OSTCBCur->OSTCBEventPtr = pevent; /* Store pointer to event control block in TCB */
y = OSTCBCur->OSTCBY; /* Task no longer ready */
OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0)
{
OSRdyGrp &= ~OSTCBCur->OSTCBBitY; /* Clear event grp bit if this was only task pending */
}
pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; /* Put task in waiting list */
pevent->OSEventGrp |= OSTCBCur->OSTCBBitY;
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* MAKE TASK READY TO RUN BASED ON EVENT TIMEOUT OR ABORT
*
* Description: This function is called by other uC/OS-II services to make a task ready to run because a
* timeout or abort occurred.
*
* Arguments : pevent is a pointer to the event control block which is readying a task.
*
* Returns : none
*
* Note : This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************************************
*/
#if OS_EVENT_EN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -