📄 cxver5.c
字号:
*****************************************************************/
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 + -