📄 cxver5.c
字号:
/************************************************************
The following function will be called by both the K_Task_Wake and
K_Task_Wake_Force functions. This will determine whether a task will
be forced to wake up, or to normally be woken up.
if force = 0, then wake task only if task had called K_Task_Wait
if force = 1, then wake task regardless of what function
was called, that suspended task
************************************************************/
byte K_I_Wake_Common(byte tskid,byte force)
{
tcbpointer tcbptr;
if(K_I_Get_Ptr(tskid,&tcbptr)) /* send address of pointer */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXTWAK_K_ERROR,tskid);
}
#endif
return(K_ERROR);
}
K_I_Disable_Sched(); /* set task block */
/* if force non 0, then wake task, regardless of what it
was waiting for. If force = 0, then only wake task
if it was waiting on time or indefinitely. */
if (tcbptr->tcbstate & (force ? ANY_WAIT : WAIT))
{
/* see if task was waiting for a resource */
if (tcbptr->tcbstate & (RESOURCE | SEMAPHORE))
{
/* yes, remove task from resource wait linked list. */
tcbptr->fwlink->bwlink = tcbptr->bwlink;
tcbptr->bwlink->fwlink = tcbptr->fwlink;
}
/* put task into the RESUME state, also possibly indicate time
expired, though it may not in the true sense */
if (force)
tcbptr->tcbstate = RESUME | TIME_EXPIRED;
else
tcbptr->tcbstate = RESUME;
/* see if this task has a higher priority then the current RUNNING task */
if (tcbptr->priority < active_priority)
{
PREEMPTED; /* yes, set the preempted scheduling flag */
}
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXTWAK_K_OK,tskid);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status */
}
else
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXTWAK_K_NOT_WAITING);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_NOT_WAITING); /* return error that task was not waiting */
}
}
/*****************************************************************
!!! 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();
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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 */
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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 */
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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, for 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 */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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 */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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 */
}
}
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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 */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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. */
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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. */
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in4(CXEWATM_CALL,0,timecnt);
}
#endif
if (K_I_Time_Common(timecnt,FLAGS))
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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. */
}
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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;
#if (defined(CMXTRACKER) || defined(WINTRACKER))
byte cmxtracker_sent;
#endif
if (mode > 0x06) /* see if mode greater then maximum allowed. */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXESIG_MODE,mode);
}
#endif
return(K_ERROR);
}
K_I_Disable_Sched(); /* set task block */
#if (defined(CMXTRACKER) || defined(WINTRACKER))
cmxtracker_sent = 0;
#endif
if (!mode) /* is mode 0. */
{
if(K_I_Get_Ptr(tskid_pri,&tcbptr)) /* send address of pointer */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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:
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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;
}
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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 */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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 */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
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 */
}
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in4(CXRSRSV_CALL,res_grp,timecnt);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -