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

📄 cxver5.c

📁 CMEX source code RTOS for atmel atmega128
💻 C
📖 第 1 页 / 共 4 页
字号:
*****************************************************************/
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;
			/* update linked list to put owner in correct spot */
			K_I_Unlink(res_ptr->owner);
			K_I_Priority_In(res_ptr->owner,res_ptr->owner->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 */
	active_priority = res_ptr->owner_priority;
	if (res_ptr->owner->priority != active_priority)
		{
		/* update linked list to put owner in correct spot */
		K_I_Unlink(res_ptr->owner);
		K_I_Priority_In(res_ptr->owner,active_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
	queue_ptr = &queue[queuenum];	/* get address of proper queue handler. */

⌨️ 快捷键说明

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