📄 cxver5.c
字号:
/*********************************************************
Copyright (c) CMX Company. 1999-1999. All rights reserved
*********************************************************/
/* version 5.30 */
#define CMXMODULE 1
#include <cxfuncs.h> /* get cmx include header file */
#include <cxextern.h> /* get cmx include header file */
#ifdef CMXTRACKER
#include <cmxtrack.h> /* get cmx include header file */
#endif
void K_OS_Slice_On(void)
{
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(ENABLE_SLICE_CALL);
}
#endif
SLICE_ON = 1; /* enable time slicing */
tslice_count = TSLICE_SCALE; /* load the time slice counter,
with the scale dictated by user in confiquration module. */
SLICE_ENABLE; /* inform CMX that time slicing is now active. */
}
void K_OS_Slice_Off(void)
{
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(DISABLE_SLICE_CALL);
}
#endif
SLICE_ON = 0; /* this will disable time slicing. */
}
/* K_I_Copy = dest,source,count */
void K_I_Copy(byte *dest,byte *src,byte count)
{
/* this will move the source bytes to the destination */
while (count--) /* post decrement counter, and test */
*dest++ = *src++; /* increment the source and destination pointers */
}
/************************************************************
task done routine, all task's that are finished their code,
will MUST be returned to here. If a task is going to hit it's
end brace, it MUST call the following function.
This function will then decide if the task should be
placed into the IDLE state or READY state because outstanding
triggers (caused by the K_Task_Start function) are present.
**************************************************************/
void K_Task_End(void)
{
K_I_Disable_Sched(); /* set task block */
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXTEND_CALL);
}
#endif
/* now test to see if task has any outstanding start requests.
If so, place task into READY state, if not IDLE state. */
activetcb->tcbstate = (--activetcb->trig) ? READY : IDLE;
PREEMPTED; /* set the preempted scheduling flag */
K_I_Func_Return(); /* release task block */
}
/***************************************************************
This function gets the address of a task's task control block.
also tests to see if task was created and if so not removed.
passes back requested task's address so the function that call
this function will be able to work with the requested task's
task control block.
*****************************************************************/
byte K_I_Get_Ptr(byte tskid,tcbpointer *tcbptr)
{
if (tskid > MAX_TASKS || !tskid) /* see if task exists */
return(K_ERROR); /* no, return error */
*tcbptr = &cmx_tcb[tskid]; /* pass address of task TCB back */
if (((tcbpointer)(*tcbptr))->nxttcb) /* see if NOT NULL */
return(K_OK); /* return good status */
else
return(K_ERROR); /* it was so return error */
}
/***********************************************************************
This function will create a task. The task will be defined to the
task's control block array.
************************************************************************/
byte K_Task_Create(byte priority,byte *tskid,CMX_FP task_addr,word16 stack_size,word16 system_stack_size)
{
tcbpointer tcbptr;
byte i;
K_I_Disable_Sched(); /* set task block */
tcbptr = cmx_tcb; /* start at beginning of linked list. */
for (i = 0; ;i++)
{
if (tcbptr->nxttcb) /* not NULL */
{
if ((++tcbptr) > &cmx_tcb[MAX_TASKS]) /* past MAXIMUM? */
{
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXTCRE_K_ERROR);
}
#endif
K_I_Func_Return(); /* yes, return because no more room. */
return(K_ERROR); /* return ERROR. */
}
}
else
{
break; /* OK, exit out of for loop. */
}
}
K_I_Priority_In(tcbptr,priority); /* go load in task into priority chain */
*tskid = i; /* load in slot number */
tcbptr->task_addr = task_addr; /* load in task's CODE address */
CXTCRE_SPECIFIC();
tcbptr->tcbstate = IDLE; /* put the task into the IDLE state */
tcbptr->trig = 0; /* load the start counter with 0, no starts */
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXTCRE_K_OK);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status */
}
/************************************************************
The following has been added, so user can pass the starting
address of a task, so as to allow multiple creations and
removing of tasks stacks, for when a task is removed after
using the 'normal' K_Task_Create function, the stack area is NOT
reclaimed.
This will allow stack area to be reclaimed if need be and if
user wants, also the ability to have different task use same
stack area, as long as they be CAREFUL to ensure that the tasks
sharing same stack do not run concurrently.
************************************************************/
byte K_Task_Create_Stack(byte priority,byte *tskid,CMX_FP task_addr,word16 *stack_start,word16 *system_stack_start)
{
tcbpointer tcbptr;
byte i;
K_I_Disable_Sched(); /* set task block */
tcbptr = cmx_tcb; /* start at beginning of linked list. */
for (i = 0; ;i++)
{
if (tcbptr->nxttcb) /* not NULL */
{
if ((++tcbptr) > &cmx_tcb[MAX_TASKS]) /* past MAXIMUM? */
{
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXTCRE_K_ERROR);
}
#endif
K_I_Func_Return(); /* yes, return because no more room. */
return(K_ERROR); /* return ERROR. */
}
}
else
{
break; /* OK, exit out of for loop. */
}
}
K_I_Priority_In(tcbptr,priority); /* go load in task into priority chain */
*tskid = i; /* load in slot number */
tcbptr->task_addr = task_addr; /* load in task's CODE address */
tcbptr->stk_start = stack_start;
tcbptr->system_stk_start = system_stack_start;
tcbptr->tcbstate = IDLE; /* put the task into the IDLE state */
tcbptr->trig = 0; /* load the start counter with 0, no starts */
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXTCRE_K_OK);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status */
}
/******************************************************
This function will change the priority of a task, will possibly
re-adjust the linked TCB chain.
******************************************************/
byte K_Task_Priority(byte tskid,byte new_priority)
{
tcbpointer tcbptr;
if(K_I_Get_Ptr(tskid,&tcbptr)) /* send address of pointer */
{
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXTPRI_K_ERROR,tskid);
}
#endif
return(K_ERROR);
}
K_I_Disable_Sched(); /* set task block */
K_I_Unlink(tcbptr); /* take task out of priority chain */
K_I_Priority_In(tcbptr,new_priority); /* now insert the task back into the
priority chain link list */
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in3(CXTPRI_K_OK,tskid,new_priority);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status */
}
/******************************************************
This function will remove a task from the linked list of TCB's.
******************************************************/
void K_I_Unlink(tcbpointer tcbptr)
{
tcbpointer prevtcb;
/* remove the task from linked list */
prevtcb = cmx_tcb;
/* scan TCB's looking for TCB that points to this TCB */
while (prevtcb->nxttcb != tcbptr)
{
prevtcb = prevtcb->nxttcb;
}
prevtcb->nxttcb = tcbptr->nxttcb;
/* the previous tcb nxttcb points to the delink tcb nxttcb */
tcbptr->nxttcb = 0;
/* identify that this task no longers exist */
}
/*******************************************************
This function will place the task into the proper linked list
slot, according to priority. Remember the lower the priority
number, the higher the priority is for this task in relationship
to others.
*******************************************************/
void K_I_Priority_In(tcbpointer tcbptr,byte priority)
{
tcbpointer prevtcb;
tcbpointer tp;
tp = cmx_tcb; /* address of TCB link list. */
do /* insert new tcb at appropriate priority slot in chain...*/
{
prevtcb = tp;
tp = tp->nxttcb;
} while ((tp != cmx_tcb) && (tp->priority <= priority));
/* We should insert it just after prevtcb, just before tp. */
tcbptr->nxttcb = tp; /* adjust priority slot chain */
prevtcb->nxttcb = tcbptr;
tcbptr->priority = priority; /* load in task's priority */
}
/****************************************************************
This function will place a task into the READY state, if in the
IDLE state. If the task is already triggered, then this will
be queued up. The maximum number of starts for a task, can be
255.
*****************************************************************/
byte K_Task_Start(byte tskid)
{
tcbpointer tcbptr;
if(K_I_Get_Ptr(tskid,&tcbptr)) /* send address of pointer */
{
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXTTRIG_K_ERROR,tskid);
}
#endif
return(K_ERROR);
}
K_I_Disable_Sched(); /* set task block */
if (tcbptr->trig != 0xff) /* see if 0xFF, bypass if so */
{
if (++tcbptr->trig == 1) /* increment the task start count byte */
{
/* if count = 1, then put task into READY state */
tcbptr->tcbstate = READY;
/* see if this task has a higher priority then current RUNNING task */
if (tcbptr->priority < active_priority)
PREEMPTED; /* yes, set preempted scheduling flag */
}
}
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXTTRIG_K_OK,tskid);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status */
}
/**************************************************************
The following will place a task into the doubly linked list of
tasks that are waiting on time, if the CMX function was called
specifying a time wait period of non 0 (zero). Also the task
will be put to sleep, for the entity that the task was looking
for, was not present at the time of the function call.
**************************************************************/
byte K_I_Time_Common(word16 timecnt,byte STATE)
{
activetcb->tcbtimer = timecnt; /* load task time counter with proper time */
activetcb->tcbstate = STATE; /* put task to sleep, indicating why */
if (timecnt) /* put into timer chain ?? */
{
/* let task sleep, indicating why and also waiting on time */
activetcb->tcbstate |= TIME;
/* place into the doubly linked list. */
if (tsk_timer_lnk->ftlink != (tcbpointer)tsk_timer_lnk)
{
activetcb->ftlink = tsk_timer_lnk->btlink->ftlink;
tsk_timer_lnk->btlink->ftlink = activetcb;
activetcb->btlink = tsk_timer_lnk->btlink;
}
else
{
activetcb->ftlink = activetcb->btlink = (tcbpointer)tsk_timer_lnk;
tsk_timer_lnk->ftlink = activetcb;
}
tsk_timer_lnk->btlink = activetcb;
}
PREEMPTED; /* set the preempted scheduling flag */
K_I_Func_Return(); /* release task block */
/* the task WILL return to here, when it resumes execution. */
K_I_Disable_Sched(); /* set lock out count. */
if (activetcb->tcbtimer) /* see if timer non 0. */
{
/* if so, remove from link list. */
activetcb->ftlink->btlink = activetcb->btlink;
activetcb->btlink->ftlink = activetcb->ftlink;
}
/* see if task was woken, because the thing it was waiting for happened,
or that the time period specified has elapsed */
if (activetcb->tcbstate & TIME_EXPIRED)
{
K_I_Func_Return(); /* release task block */
return(K_TIMEOUT); /* return the warning: that the time period expired */
}
else
{
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status */
}
}
/************************************************************
This function allows a task to wait for the desired time
period to expire or indefinitely. The K_Task_Wake and K_Task_Wake_Force
function may be used to wake this task, prior to the time
period expiring.
************************************************************/
byte K_Task_Wait(word16 timecnt)
{
K_I_Disable_Sched(); /* set task block */
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in4(CXTWATM_CALL,0,timecnt);
}
#endif
/* call the function that will suspend this task, indicate the
reason to suspend this task */
if (K_I_Time_Common(timecnt,WAIT))
{
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXTWATM_DELAY_K_ERROR);
}
#endif
return(K_TIMEOUT);
}
else
{
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXTWATM_DELAY_K_OK);
}
#endif
return(K_OK);
}
}
/************************************************************
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 */
{
#ifdef CMXTRACKER
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 */
}
#ifdef CMXTRACKER
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXTWAK_K_OK,tskid);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status */
}
else
{
#ifdef CMXTRACKER
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -