⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cxver5.c

📁 上传一个带源代码的嵌入式实时多任务操作系统CMX
💻 C
📖 第 1 页 / 共 4 页
字号:
		}
}

/*****************************************************************
		!!! WARNING: the CMX timer task will not run !!!!
 The CMX timer task will not be executed, nor the interrupt pipe
 if this function is called. The task that called this function should
 release it, by using the K_Task_Unlock function as soon as possible.
 In most cases this function should NOT be used. Improper use is
 abuse. Also the task that calls this function, MUST NOT call any
 function that may suspend this task
*****************************************************************/
void K_Task_Lock(void)
{
	/* set the task lock flag. This will stop the K_I_Scheduler
		from re-scheduling, until the K_Task_Unlock function is called */

	K_I_Disable_Sched();
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in1(CXPRVR_CALL);
			}
#endif
}
/****************************************************************
 Should be used ONLY if the task used the K_Task_Lock function.
*****************************************************************/
void K_Task_Unlock(void)
{
	/* lower the task privilege flag. See if the K_I_Scheduler
		should be invoked */

#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in1(CXPRVL_CALL);
			}
#endif
	K_I_Func_Return();
}
/***************************************************************
 The following function performs a cooperative scheduling.
***************************************************************/
void K_Task_Coop_Sched(void)
{
	K_I_Disable_Sched();	/* set task block */
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in1(CXSCHED_CALL);
			}
#endif
	DO_COOP_SCHED;	/* set the cooperative scheduling flag */
	K_I_Func_Return();	/* release task block */
}

/***********************************************************
 Remove a task. Once removed this task can not be used in anyway
 Also the task MUST NOT be waiting on anything, foe it will not
 be removed if so.
***********************************************************/
byte K_Task_Delete(byte tskid)
{
	tcbpointer tcbptr;

	if(K_I_Get_Ptr(tskid,&tcbptr))	/* send address of pointer */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXTRMV_K_ERROR,tskid);
			}
#endif
		return(K_ERROR);
		}
	K_I_Disable_Sched();	/* set task block */
	if (tcbptr->tcbstate & ANY_WAIT)	/* see if task waiting */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXTRMV_WAIT_K_ERROR,tskid);
			}
#endif
		K_I_Func_Return();	/* task was waiting, cannot terminate this task */
		return(K_ERROR);	/* return error status, task was not terminated */
		}
	else
		{
		K_I_Unlink(tcbptr);	/* no, task not waiting. Remove task from TCB */
		if (tcbptr == activetcb)	/* is task trying to commit suicide */
			{
			activetcb->tcbstate = 0;	/* load in highest priority task */
			PREEMPTED;	/* set the preempted scheduling flag */
			}
		}
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXTRMV_K_OK,tskid);
			}
#endif
	K_I_Func_Return();	/* release task block */
	return(K_OK);	/* return good status, if task not committing suicide */
}

/***********************************************************************

		TASK GENERAL PURPOSE FLAGS SYNCHRONIZATION

************************************************************************/
/***************************************************************
 This allows a task to reset a task's event flags that they
 would like to be cleared.
***************************************************************/
byte K_Event_Reset(byte tskid,word16 event)
{
	tcbpointer tcbptr;

	if(K_I_Get_Ptr(tskid,&tcbptr))	/* send address of pointer */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXERST_K_ERROR,tskid);
			}
#endif
		return(K_ERROR);
		}
	K_I_Disable_Sched();	/* set task block */
	tcbptr->e_flags &= (~event);		/* place the event bit(s) into clear state, indicated by mask. */
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in4(CXERST_K_OK,tskid,event);
			}
#endif
	K_I_Func_Return();	/* release task block */
	return(K_OK);	/* return good status, if task not committing suicide */
}
/***************************************************************
 The following allows a task to wait for 1 or more events to be
 set, if they are not. Also a time period may be specified on how
 long the task will wait for at least 1 event to be set, in which
 the task wants.
MODE:
= 0 nothing
= 1 clear at beginning
= 2 auto clear on match
= 3 both 1 and 2
***************************************************************/
word16 K_Event_Wait(word16 match,word16 timecnt,byte mode)
{
	word16 good_bits;

	K_I_Disable_Sched();	/* set task block */
	if (mode & 0x01) 	/* see if we should clear specified events at beginning. */
		{
		activetcb->e_flags &= (~match);	/* yes, clear them. */
		}
		/* see if ANY task flags match */
	if (!(activetcb->e_flags & (activetcb->e_match = match)))
		{
		/* NO, so call CMX function that will suspend task. */
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in4(CXEWATM_CALL,0,timecnt);
			}
#endif
		if (K_I_Time_Common(timecnt,FLAGS))	
			{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in1(CXEWATM_DELAY_K_TIMEOUT);
			}
#endif
			return(0);	/* return the warning: that the time period expired */
			}
		K_I_Disable_Sched();	/* set task block. */
		}
	good_bits = activetcb->e_flags & match;	/* what event bits matched. */
	if (mode & 0x02)	/* should we clear the events now? */
		{
		activetcb->e_flags &= ~match;	/* yes, clear them. */
		}
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in4(CXEWATM_K_OK,0,good_bits);
			}
#endif
	K_I_Func_Return();	/* release task lock. */
	return(good_bits);	/* return events that were set according to mask. */
}

/**********************************************************************
 The following function will set possibly set an event.

byte mode: 	0 = specific task
				1 = highest priority (single task even if more then one of same)
				2 = highest priority waiting task on THIS EVENT
				3 = all tasks
				4 = all waiting tasks THIS EVENT
				5 = all with same priority (specify priority)
				6 = all waiting with same priority (specify priority) THIS EVENT
************************************************************************/
byte K_Event_Signal(byte mode, byte tskid_pri,word16 flag)
{
	tcbpointer tcbptr;
#ifdef CMXTRACKER
	byte cmxtracker_sent;
#endif

	if (mode > 0x06)	/* see if mode greater then maximum allowed. */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXESIG_MODE,mode);
			}
#endif
		return(K_ERROR);
		}
	K_I_Disable_Sched();	/* set task block */
#ifdef CMXTRACKER
	cmxtracker_sent = 0;
#endif
	if (!mode)	/* is mode 0. */
		{
		if(K_I_Get_Ptr(tskid_pri,&tcbptr))	/* send address of pointer */
			{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXESIG_K_ERROR,tskid_pri);
			}
#endif
			K_I_Func_Return();
			return(K_ERROR);
			}
		goto test_event;
		}
	else
		{
		tcbptr = timertask->nxttcb;	/* start at head of linked list. */
		}
	for (; tcbptr != cmx_tcb; tcbptr = tcbptr->nxttcb) /* see if we tested all. */
		{
		if (mode > 0x04)	/* is mode greater then 4? */
			{
			if (tcbptr->priority != tskid_pri)	/* see if priority match. */
				continue;
			}
		if (!(mode & 0x01))	/* see if task must be waiting on this EVENT */
			{
			if (!((tcbptr->e_match & flag) &&
				(tcbptr->tcbstate & FLAGS)))
				{
				continue;	/* continue if task was not. */
				}
			}
test_event:
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			if (!cmxtracker_sent)
				{
				cmxtracker_sent = tcbptr - cmx_tcb;
				}
			}
#endif
		/* see if task event(s) match. */
		if (tcbptr->e_match & (tcbptr->e_flags |= flag))
			{
			if (tcbptr->tcbstate & FLAGS)	/* see if task was waiting on EVENT. */
				{
				tcbptr->tcbstate = RESUME; /* yes, the task may now resume. */
				
				if (TEST_NOT_PREEMPTED)	/* see if preempted flag not set yet. */
					{
					if (tcbptr->priority < active_priority)
						PREEMPTED;	/* yes, set the preempted scheduling flag */
					}
				if (mode < 0x03)	/* see if we should exit function. */
					break;
				}
			}
		if (mode < 0x02)	/* see if we should exit function. */
			break;
		}
#ifdef CMXTRACKER
 	if (CMXTRACKER_ON)
		{
		cmxtracker_in3(CXESIG_K_OK,mode,cmxtracker_sent);
		}
#endif
	K_I_Func_Return();	/* call CMX function, that will release task block */	
	return(K_OK);	/* return good status */
}

/*******************************************************************
		RESOURCE MANAGER
********************************************************************/

/*******************************************************************
 This function allows a task to reserve or get this resource.

 if func_mode = 1, then means get resource if free, otherwise return

 if func_mode = 0, then if the resource is "owned" by another task,
 then this task will be suspended until this resource is free or time
 period expires.
*******************************************************************/
byte K_I_Resource_Common(byte res_grp,word16 timecnt,byte func_mode)
{
	RESHDR *res_ptr;
	tcbpointer tp;

	if (res_grp >= MAX_RESOURCES)	/* see if resource number allowed */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in3(CXRSRSV_K_ERROR,res_grp,func_mode);
			}
#endif
		return(K_ERROR);	/* no, return error status */
		}

	K_I_Disable_Sched();	/* set task block */

	res_ptr = &res_que[res_grp];	/* get address of resource */

	if (res_ptr->owner)	/* does a task own this resource? */
		{
		/* yes, what function was used. */
		if (func_mode)		/* did the K_Resource_Get function call this function */
			{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXRSRSV_K_RESOURCE_OWNED,res_grp);
			}
#endif
			 K_I_Func_Return();	/* release task block */
			 return(K_RESOURCE_OWNED);	/* return error that resource is already owned */
			}
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in4(CXRSRSV_CALL,res_grp,timecnt);
			}
#endif
		/* place the task into the resource doubly linked wait list. */

	tp = (tcbpointer)res_ptr;	/* address of resource link list. */
	do /* insert tcb at appropriate wait slot, based on priority. */
		{
		tp = tp->fwlink;
		} while ((tp != (tcbpointer)res_ptr) && (tp->priority <= activetcb->priority));
	/* We should insert it just after prevtcb, just before tp. */

		activetcb->fwlink = tp->bwlink->fwlink;
		tp->bwlink->fwlink = activetcb;
		activetcb->bwlink = tp->bwlink;
		tp->bwlink = activetcb;

		if (res_ptr->fwlink->priority < res_ptr->owner->priority)
			{
			res_ptr->owner->priority = res_ptr->fwlink->priority;
			}
		/*
			res_ptr->fwlink->priority is highest priority !!!
			which we will then raise owner to highest !!!
		*/
		/* go place task into suspended state. */
		if (K_I_Time_Common(timecnt,RESOURCE))
			{
#ifdef CMXTRACKER
			if (CMXTRACKER_ON)
				{
				cmxtracker_in1(CXRSRSV_DELAY_K_TIMEOUT);
				}
#endif
			return(K_TIMEOUT);	/* return the warning: that the time period expired */
			}
			else
			{
#ifdef CMXTRACKER
			if (CMXTRACKER_ON)
				{
				cmxtracker_in2(CXRSRSV_K_OK,res_grp);
				}
#endif
			return(K_OK);	
			}
		}
	/* NO, no task owned this resource. This task is now the owner of
		this resource */
	res_ptr->fwlink = res_ptr->bwlink = (tcbpointer)(res_ptr);
	res_ptr->owner = activetcb;
	res_ptr->owner_priority = activetcb->priority;
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in3(CXRSRSV_K_OK,res_grp,func_mode);
			}
#endif
	K_I_Func_Return();	/* release task block. */
	return(K_OK);	/* return good status. */
}

/*****************************************************************
 This lets a task that owns a resource, to release it. Once the resource
 is released, if another task is waiting for it, then that task will
 automatically become the owner.
******************************************************************/
byte K_Resource_Release(byte res_grp)
{
	RESHDR *res_ptr;

	if (res_grp >= MAX_RESOURCES)	/* see if resource group OK */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXRSREL_K_ERROR,res_grp);
			}
#endif
		return(K_ERROR);	/* no, return error status */
		}

	res_ptr = &res_que[res_grp];	/* get address of resource */
	if (res_ptr->owner != activetcb)	/* see if task really "owns" this. */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXRSREL_K_RESOURCE_NOT_OWNED,res_grp);
			}
#endif
		return(K_RESOURCE_NOT_OWNED);	/* resource not owned by this task */
		}
	K_I_Disable_Sched();	/* set task block */
	/* restore original task's priority */
	res_ptr->owner->priority = active_priority = res_ptr->owner_priority;
	/* see if another task waiting for this resource. */
	if ((res_ptr->owner = res_ptr->fwlink) != (tcbpointer)res_ptr)
		{
		/* properly adjust the linked list. */
		res_ptr->fwlink = res_ptr->fwlink->fwlink;
		res_ptr->fwlink->bwlink = res_ptr->owner->bwlink;
		res_ptr->owner->tcbstate = RESUME;	/* wake task that was sleeping. */
		if (res_ptr->owner->priority < active_priority) 
			PREEMPTED;	/* yes, set the preempted scheduling flag */
		res_ptr->owner_priority = res_ptr->owner->priority;
		}
	else
		{
		res_ptr->owner = NULL;
		}
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXRSREL_K_OK,res_grp);
			}
#endif
	K_I_Func_Return();	/* release task block */
	return(K_OK);	/* return good status to caller */
}

/*****************************************************************

		QUEUE MANAGER

******************************************************************/
byte K_Que_Create(sign_word16 num_slots,byte slot_size,byte *queuearray,byte queuenum)
{
	QUEHDR *queue_ptr;

	if (queuenum >= MAX_QUEUES)	/* see if queue number OK. */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXQCRE_K_ERROR,queuenum);
			}
#endif
		return(K_ERROR);
		}
	K_I_Disable_Sched();	/* set task block. */
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXQCRE_K_OK,queuenum);
			}
#endif

⌨️ 快捷键说明

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