os_core.c

来自「ARM7 based on STR71x, UCOS migration」· C语言 代码 · 共 998 行 · 第 1/3 页

C
998
字号
					   &OSTaskIdleStk[0],
					   OS_IDLE_PRIO);
	#endif
#endif
}

/*********************************************************************************************************
*											 INITIALIZATION
*									  CREATING THE STATISTIC TASK
*
* Description: This function creates the Statistic Task.
*
* Arguments  : none
*
* Returns	: none
********************************************************************************************************/
#if OS_TASK_STAT_EN > 0
static  void  OS_InitTaskStat (void)
{
#if OS_TASK_CREATE_EXT_EN > 0
	#if OS_STK_GROWTH == 1
	(void)OSTaskCreateExt(OS_TaskStat,
						  (void *)0,									// No args passed to OS_TaskStat()
						  &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],	// Set Top-Of-Stack
						  OS_STAT_PRIO,									// One higher than the idle task
						  OS_TASK_STAT_ID,
						  &OSTaskStatStk[0],							// Set Bottom-Of-Stack
						  OS_TASK_STAT_STK_SIZE,
						  (void *)0,									// No TCB extension
						  OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);	// Enable stack checking + clear
	#else
	(void)OSTaskCreateExt(OS_TaskStat,
						  (void *)0,									// No args passed to OS_TaskStat()
						  &OSTaskStatStk[0],							// Set Top-Of-Stack
						  OS_STAT_PRIO,									// One higher than the idle task
						  OS_TASK_STAT_ID,
						  &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],	// Set Bottom-Of-Stack
						  OS_TASK_STAT_STK_SIZE,
						  (void *)0,									// No TCB extension
						  OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);	// Enable stack checking + clear
	#endif
#else
	#if OS_STK_GROWTH == 1
	(void)OSTaskCreate(OS_TaskStat,
					   (void *)0,										// No args passed to OS_TaskStat()
					   &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],		// Set Top-Of-Stack
					   OS_STAT_PRIO);									// One higher than the idle task
	#else
	(void)OSTaskCreate(OS_TaskStat,
					   (void *)0,										// No args passed to OS_TaskStat()
					   &OSTaskStatStk[0],								// Set Top-Of-Stack
					   OS_STAT_PRIO);									// One higher than the idle task
	#endif
#endif
}
#endif

/*********************************************************************************************************
*											 INITIALIZATION
*							INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS
*
* Description: This function is called by OSInit() to initialize the free list of OS_TCBs.
*
* Arguments  : none
*
* Returns	: none
********************************************************************************************************/
static  void  OS_InitTCBList (void)
{
	INT8U	i;
	OS_TCB  *ptcb1;
	OS_TCB  *ptcb2;

	OSTCBList	 = (OS_TCB *)0;									// TCB Initialization
	for (i = 0; i < (OS_LOWEST_PRIO + 1); i++) {				// Clear the priority table
		OSTCBPrioTbl[i] = (OS_TCB *)0;
	}
	ptcb1 = &OSTCBTbl[0];
	ptcb2 = &OSTCBTbl[1];
	for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {	// Init. list of free TCBs
		ptcb1->OSTCBNext = ptcb2;
		ptcb1++;
		ptcb2++;
	}
	ptcb1->OSTCBNext = (OS_TCB *)0;								// Last OS_TCB
	OSTCBFreeList	= &OSTCBTbl[0];
}

/*********************************************************************************************************
*											  SCHEDULER
*
* Description: This function is called by other uC/OS-II services to determine whether a new, high
*			  priority task has been made ready to run.  This function is invoked by TASK level code
*			  and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).
*
* Arguments  : none
*
* Returns	: none
*
* Notes	  : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
*			  2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
********************************************************************************************************/
void  OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3								// Allocate storage for CPU status register
	OS_CPU_SR cpu_sr;
#endif	
	INT8U y;

	OS_ENTER_CRITICAL();
	if ((OSIntNesting == 0) && (OSLockNesting == 0)) {	// Sched. only if all ISRs done & not locked
		y = OSUnMapTbl[OSRdyGrp];						// Get pointer to HPT ready to run
		OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
		if (OSPrioHighRdy != OSPrioCur) {				// No Ctx Sw if current task is highest rdy
			OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
			OSCtxSwCtr++;								// Increment context switch counter
			OS_TASK_SW();								// Perform a context switch
		}
	}
	OS_EXIT_CRITICAL();
}

/*********************************************************************************************************
*											  IDLE TASK
*
* Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks
*			  executes because they are ALL waiting for event(s) to occur.
*
* Arguments  : none
*
* Returns	: none
*
* Note(s)	: 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be
*				 enabled for at least a few instructions.  On some processors (ex. Philips XA), enabling
*				 and then disabling interrupts didn't allow the processor enough time to have interrupts
*				 enabled before they were disabled again.  uC/OS-II would thus never recognize
*				 interrupts.
*			  2) This hook has been added to allow you to do such things as STOP the CPU to conserve 
*				 power.
********************************************************************************************************/
void  OS_TaskIdle (void *pdata)
{
#if OS_CRITICAL_METHOD == 3						// Allocate storage for CPU status register
	OS_CPU_SR  cpu_sr;
#endif	
	
	pdata = pdata;								// Prevent compiler warning for not using 'pdata'
	for (;;) {
		OS_ENTER_CRITICAL();
		OSIdleCtr++;
		OS_EXIT_CRITICAL();
		OSTaskIdleHook();						// Call user definable HOOK
	}
}

/*********************************************************************************************************
*											STATISTICS TASK
*
* Description: This task is internal to uC/OS-II and is used to compute some statistics about the
*			  multitasking environment.  Specifically, OS_TaskStat() computes the CPU usage.
*			  CPU usage is determined by:
*
*										  OSIdleCtr
*				 OSCPUUsage = 100 * (1 - ------------)	 (units are in %)
*										 OSIdleCtrMax
*
* Arguments  : pdata	 this pointer is not used at this time.
*
* Returns	: none
*
* Notes	  : 1) This task runs at a priority level higher than the idle task.  In fact, it runs at the
*				 next higher priority, OS_IDLE_PRIO-1.
*			  2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
*			  3) We delay for 5 seconds in the beginning to allow the system to reach steady state and
*				 have all other tasks created before we do statistics.  You MUST have at least a delay
*				 of 2 seconds to allow for the system to establish the maximum value for the idle
*				 counter.
********************************************************************************************************/
#if OS_TASK_STAT_EN > 0
void  OS_TaskStat (void *pdata)
{
#if OS_CRITICAL_METHOD == 3						// Allocate storage for CPU status register
	OS_CPU_SR  cpu_sr;
#endif
	INT32U run;
	INT32U max;
	INT8S usage;

	pdata = pdata;								// Prevent compiler warning for not using 'pdata'
	while (OSStatRdy == FALSE) {
		OSTimeDly(2 * OS_TICKS_PER_SEC);		// Wait until statistic task is ready
	}
	max = OSIdleCtrMax / 100L;
	for (;;) {
		OS_ENTER_CRITICAL();
		OSIdleCtrRun = OSIdleCtr;				// Obtain the of the idle counter for the past second
		run = OSIdleCtr;
		OSIdleCtr = 0L;							// Reset the idle counter for the next second
		OS_EXIT_CRITICAL();
		if (max > 0L) {
			usage = (INT8S)(100L - run / max);
			if (usage >= 0) {					// Make sure we don't have a negative percentage
				OSCPUUsage = usage;
			} else {
				OSCPUUsage = 0;
			}
		}
		else {
			OSCPUUsage = 0;
			max = OSIdleCtrMax / 100L;
		}
		OSTaskStatHook();						// Invoke user definable hook
		OSTimeDly(OS_TICKS_PER_SEC);			// Accumulate OSIdleCtr for the next second
	}
}
#endif

/********************************************************************************************************
*											INITIALIZE TCB
*
* Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when
*			  a task is created (see OSTaskCreate() and OSTaskCreateExt()).
*
* Arguments  : prio		  is the priority of the task being created
*
*			  ptos		  is a pointer to the task's top-of-stack assuming that the CPU registers
*							have been placed on the stack.  Note that the top-of-stack corresponds to a
*							'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory
*							location if OS_STK_GROWTH is set to 0.  Note that stack growth is CPU
*							specific.
*
*			  pbos		  is a pointer to the bottom of stack.  A NULL pointer is passed if called by
*							'OSTaskCreate()'.
*
*			  id			is the task's ID (0..65535)
*
*			  stk_size	  is the size of the stack (in 'stack units').  If the stack units are INT8Us
*							then, 'stk_size' contains the number of bytes for the stack.  If the stack
*							units are INT32Us then, the stack contains '4 * stk_size' bytes.  The stack
*							units are established by the #define constant OS_STK which is CPU
*							specific.  'stk_size' is 0 if called by 'OSTaskCreate()'.
*
*			  pext		  is a pointer to a user supplied memory area that is used to extend the task
*							control block.  This allows you to store the contents of floating-point
*							registers, MMU registers or anything else you could find useful during a
*							context switch.  You can even assign a name to each task and store this name
*							in this TCB extension.  A NULL pointer is passed if called by OSTaskCreate().
*
*			  opt		   options as passed to 'OSTaskCreateExt()' or,
*							0 if called from 'OSTaskCreate()'.
*
* Returns	: OS_NO_ERR		 if the call was successful
*			  OS_NO_MORE_TCB	if there are no more free TCBs to be allocated and thus, the task cannot
*								be created.
*
* Note	   : This function is INTERNAL to uC/OS-II and your application should not call it.
********************************************************************************************************/
INT8U  OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
#if OS_CRITICAL_METHOD == 3						// Allocate storage for CPU status register
	OS_CPU_SR  cpu_sr;
#endif	
	OS_TCB *ptcb;

	OS_ENTER_CRITICAL();
	ptcb = OSTCBFreeList;							// Get a free TCB from the free TCB list
	if (ptcb != (OS_TCB *)0) {
		OSTCBFreeList = ptcb->OSTCBNext;			// Update pointer to free TCB list
		OS_EXIT_CRITICAL();
		ptcb->OSTCBStkPtr = ptos;					// Load Stack pointer in TCB
		ptcb->OSTCBPrio = (INT8U)prio;				// Load task priority into TCB
		ptcb->OSTCBStat = OS_STAT_RDY;				// Task is ready to run
		ptcb->OSTCBDly = 0;							// Task is not delayed

#if OS_TASK_CREATE_EXT_EN > 0
		ptcb->OSTCBExtPtr = pext;					// Store pointer to TCB extension
		ptcb->OSTCBStkSize = stk_size;				// Store stack size
		ptcb->OSTCBStkBottom = pbos;				// Store pointer to bottom of stack
		ptcb->OSTCBOpt = opt;						// Store task options
		ptcb->OSTCBId = id;							// Store task ID
#else
		pext = pext;								// Prevent compiler warning if not used
		stk_size = stk_size;
		pbos = pbos;
		opt = opt;
		id = id;
#endif

#if OS_TASK_DEL_EN > 0
		ptcb->OSTCBDelReq	= OS_NO_ERR;
#endif

		ptcb->OSTCBY = prio >> 3;					// Pre-compute X, Y, BitX and BitY
		ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
		ptcb->OSTCBX = prio & 0x07;
		ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];

#if OS_EVENT_EN > 0
		ptcb->OSTCBEventPtr  = (OS_EVENT *)0;		// Task is not pending on an event
#endif

#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
		ptcb->OSTCBFlagNode  = (OS_FLAG_NODE *)0;	// Task is not pending on an event flag
#endif

#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
		ptcb->OSTCBMsg = (void *)0;					// No message received
#endif

#if OS_VERSION >= 204
		OSTCBInitHook(ptcb);
#endif

		OSTaskCreateHook(ptcb);						// Call user defined hook
		
		OS_ENTER_CRITICAL();
		OSTCBPrioTbl[prio] = ptcb;
		ptcb->OSTCBNext	= OSTCBList;				// Link into TCB chain
		ptcb->OSTCBPrev	= (OS_TCB *)0;
		if (OSTCBList != (OS_TCB *)0) {
			OSTCBList->OSTCBPrev = ptcb;
		}
		OSTCBList = ptcb;
		OSRdyGrp |= ptcb->OSTCBBitY;					// Make task ready to run
		OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
		OS_EXIT_CRITICAL();
		return (OS_NO_ERR);
	}
	OS_EXIT_CRITICAL();
	return (OS_NO_MORE_TCB);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?