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