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

📄 rtexec.c

📁 GPS导航定位程序
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "includes.h"

/****************************************************************************    
* Disable all compiler optimizations (except register variables) for this
* module.  Common-subexpression optimizations place hidden local variables on 
* procedure stacks.  Most of the procedures in this module need to know their 
* exact invocation sequences in order to manipulate the machine context.
****************************************************************************/

#pragma option -Od -Z- -r


/* Real-time executive functions are collected together in this module. */

extern void TBeep(void);      /* Beeper management task */
extern void TDisplay(void);   /* Display update task */
extern void TProcSbf(void);   /* Process subframes task */
extern void TRTCM(void);      /* Differential corrections task */

/****************************************************************************    
* Task definitions.  The context that exists when the program begins
*  executing becomes the lowest priority task, which must have the task
*  name "MAIN".  Since the list is in priority order, MAIN is always at
*  the end of the list.
****************************************************************************/

tcbstruc TCB[] =
{
    {"TBeep",2000,TBeep,NULL},         /* Beep task (mostly a case study). */
    {"TDisplay",10000,TDisplay,NULL},              /* Display update task. */
    {"TRTCM",4000,TRTCM,NULL},           /* Differential corrections task. */
    {"TProcSbf",4000,TProcSbf,NULL},            /* Process subframes task. */
    {"MAIN",0,NULL,NULL}                       /* MAIN must be at the end. */
};

/* Information about Current Task. */

int CurrentTask;                              /* TCB index of CurrentTask. */
unsigned CurrentStack;             /* CurrentTask's private stack segment. */

/* Index of the TCB at the head of the suspended list.  This list is
   ordered by the scheduled activation times.  A link of -1 indicates
   the end of the suspended list. */

int SuspTask;

/* Index of the MAIN task (it's always the last entry in the TCB array). */

int MainTask;

unsigned savedSS,savedSP,taskSS,taskSP,taskCS,taskIP;
unsigned InitSegTemp,InitOffTemp;
unsigned far *InDOSPtr;

/****************************************************************************    
* Function: void InitialiseTasks(void)
*
* Allocate stacks for each task from the far heap. Initialize all the tasks
* preassigned in the data structure TCB. (The exact initialization procedure
* is be compiler-dependent. The initialisation used here is appropriate for
* Borland C/C++.) Place all the tasks on the suspended list except MAIN,
* which will be left executing and identified as CurrentTask, the current
* active task.
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void InitialiseTasks(void)
{
    int i;
    
    _AH = 0x34;                       /* Save a pointer to the InDOS flag. */
    geninterrupt(0x21);
    InDOSPtr = (unsigned int *)MK_FP(_ES,_BX);

    PROTECT++;

    /* Allocate stacks for all the tasks (except MAIN, which already has
       a stack and is currently running). */

    i=0;
    while(stricmp(TCB[i].TNAME,"MAIN"))
    {
	if(TCB[i].TSTKSIZE < 2000)
	{
	    printf("\nERROR: %s task stack size is too small. "
		   "Increase it.\r\n",TCB[i].TNAME);
	    QuitGpsBuilder();
	}
	TCB[i].TSTACK = farmalloc(TCB[i].TSTKSIZE+32);
	if(TCB[i].TSTACK==NULL)
	{
	    printf("\nERROR: Insufficient conventional memory.\r\n");
	    QuitGpsBuilder();
	}
	TCB[i].STRTSS = FP_SEG(TCB[i].TSTACK)+FP_OFF(TCB[i].TSTACK)/16+1;
	TCB[i].MinSP = TCB[i].STRTSP = TCB[i].TSTKSIZE;

	/* Clone the floating point emulator/coprocessor interface data
	   structures which exist in the low addresses of the task's stack
	   segment.  The number of bytes that needs to be cloned grows with
	   each BC revision, so we are doing 1024 to be conservative. */

	_fmemcpy(MK_FP(TCB[i].STRTSS,0),MK_FP(MStkSS,0),1024);

	i++;
    }

    MainTask = i;                      /* Save the index of the MAIN task. */

    /* Show MAIN as the current task (it's active, too). */

    TCB[MainTask].STRTSS = MStkSS;       /* Saved at invocation of main(). */
    TCB[MainTask].STRTSP = TCB[MainTask].MinSP = MStkSP;
    TCB[MainTask].Active = 1;
    CurrentTask = MainTask;
    CurrentStack = TCB[MainTask].STRTSS;

    /* Place all the other tasks on the suspended list with zero suspend
       intervals, and mark them inactive. */

    SuspTask = 0;
    for(i=0;i<MainTask;i++)
    {
	TCB[i].Active = 0;
	TCB[i].SuspTics = 0;
	if((i+1)==MainTask)
	    TCB[i].NxtSusp=-1;
	else
	    TCB[i].NxtSusp = i+1;
    }

    if(_8087)
    {
	/* Wait for any pending coprocessor operation to complete before
	   disabling interrupts.  Then save the coprocessor state, and wait
	   for the save to complete before proceeding. */
 
	InitSegTemp = FP_SEG(TCB[MainTask].SAV8087);
	InitOffTemp = FP_OFF(TCB[MainTask].SAV8087);
	asm{
	    mov   es,InitSegTemp
	    mov   bx,InitOffTemp
	    fwait
	    cli
	    fsave es:[bx]
	    fwait
	    sti
	}
    }

    /* Initialize the task contexts. Important note: do not reference
       local variables while the stack pointer is being redirected. */

    for(i=0;i<MainTask;i++)
    {
	InitSegTemp = FP_SEG(TCB[i].SAV8087);  /* FP context save pointer. */
	InitOffTemp = FP_OFF(TCB[i].SAV8087);
	taskSS = TCB[i].STRTSS;
	taskSP = TCB[i].STRTSP;
	taskCS = FP_SEG(TCB[i].TSTART);
	taskIP = FP_OFF(TCB[i].TSTART);

	/* No local variable references or procedure calls should be made
	   until further notice (see below). */

	savedSS = _SS;
	savedSP = _SP;
	_CX = taskCS;
	_DX = taskIP;
	_SS = taskSS;
	_SP = taskSP;

	/* NOTE: Borland C versions 3.1 and earlier saved only a 16-bit
	   context when entering routines declared as "interrupt".  Borland
	   C/C++ version 4.0 saves a 32-bit context (when compiling in 32-bit
	   mode).  Thus, the construction of a task's initial context must
	   be handled differently under the two compiler revisions. */

#if (CompilerVersion > 31) && (INSTRMODE==32)

	/* Construct an initial version 4.0 32-bit context.  Push the
	   following onto the empty stack:

	   Flags
	   CS part of task starting address
	   IP part of task starting address
	   Initial values for: eax,ebx,ecx,edx,es (zeroes)
	   Initial value for ds (set to DGROUP, same as for MAIN)
	   Initial values for: esi,edi,bp (0)

	   The task's stack looks like the invocation of an interrupt
	   procedure with no local variables. */

	asm{
	    pushf                         /* Task's initial flag settings. */
	    pop     ax         /* Task must start with interrupts enabled. */
	    or      ax,200h
	    push    ax
	    push    cx
	    push    dx
	    push    0                       /* Initial (32-bit) eax value. */
	    push    0
	    push    0                       /* Initial (32-bit) ebx value. */
	    push    0
	    push    0                       /* Initial (32-bit) ecx value. */
	    push    0
	    push    0                       /* Initial (32-bit) edx value. */
	    push    0
	    push    0                        /* Initial (16-bit) es value. */
	    push    ds                       /* Initial (16-bit) ds value. */
	    push    0                       /* Initial (32-bit) esi value. */
	    push    0
	    push    0                       /* Initial (32-bit) edi value. */
	    push    0
	    push    0                        /* Initial (16-bit) bp value. */
	}
#endif

#if (CompilerVersion > 31) && (INSTRMODE==16)

	/* Construct an initial version 4.0 16-bit context.  Push the
	   following onto the empty stack:

	   Flags
	   CS part of task starting address
	   IP part of task starting address
	   Initial values for: ax,bx,cx,dx,es (zeroes)
	   Initial value for ds (set to DGROUP, same as for MAIN)
	   Initial values for: si,di,bp (0)

	   The task's stack looks like the invocation of an interrupt
	   procedure with no local variables. */

	asm{
	    pushf                         /* Task's initial flag settings. */
	    pop     ax         /* Task must start with interrupts enabled. */
	    or      ax,200h
	    push    ax
	    push    cx
	    push    dx
	    push    0                        /* Initial (16-bit) ax value. */
	    push    0                        /* Initial (16-bit) bx value. */
	    push    0                        /* Initial (16-bit) cx value. */
	    push    0                        /* Initial (16-bit) dx value. */
	    push    0                        /* Initial (16-bit) es value. */
	    push    ds                       /* Initial (16-bit) ds value. */
	    push    0                        /* Initial (16-bit) si value. */
	    push    0                        /* Initial (16-bit) di value. */
	    push    0                        /* Initial (16-bit) bp value. */
	}     
#endif

#if (CompilerVersion == 31)

	/* Construct an initial version 3.1 context.  Push the following
	   onto the empty stack:

	   Flags
	   CS part of task starting address
	   IP part of task starting address
	   Initial values for: ax,bx,cx,dx,es (zeroes)
	   Initial value for ds (set to DGROUP, same as for MAIN)
	   Initial values for: si,di,bp (0)

	   The task's stack looks like the invocation of an interrupt
	   procedure with no local variables. */

	asm{
	    pushf                         /* Task's initial flag settings. */
	    pop     ax         /* Task must start with interrupts enabled. */
	    or      ax,200h
	    push    ax
	    push    cx
	    push    dx
	    push    0                        /* Initial (16-bit) ax value. */
	    push    0                        /* Initial (16-bit) bx value. */
	    push    0                        /* Initial (16-bit) cx value. */
	    push    0                        /* Initial (16-bit) dx value. */
	    push    0                        /* Initial (16-bit) es value. */
	    push    ds                       /* Initial (16-bit) ds value. */
	    push    0                        /* Initial (16-bit) si value. */
	    push    0                        /* Initial (16-bit) di value. */
	    push    0                        /* Initial (16-bit) bp value. */
	}
#endif

#if (CompilerVersion==31) && (INSTRMODE==32)

	/* If we're in compiler version 3.1 and generating 32-bit
	   instructions, add some logic to save and restore the 32-bit
	   registers. */

	asm{
	    db   0x66          /* OPSIZ: */
	    db   0x60          /* PUSHA */
	}
#endif

	asm{
	    cli
	    fninit      /* Initialize H/W coprocessor or S/W emulator */
	    fwait
	    sti
	}

	taskSS = _SS;
	taskSP = _SP;

	if(_8087)
	{
	    /* Wait for any pending coprocessor operation to complete before
	       disabling interrupts.  Then save the coprocessor state, and
	       wait for the save to complete before proceeding. */

	asm{
	    mov   es,InitSegTemp
	    mov   bx,InitOffTemp
	    fwait
	    cli
	    fsave es:[bx]
	    fwait
	    sti
	}
    }                                                   /* Of for() tasks. */

    _SS = savedSS;
    _SP = savedSP;

    /* Now it is OK to reference local variables and make procedure
       calls. */

    TCB[i].SAVSS = taskSS;
    TCB[i].SAVSP = taskSP;

    }

    if(_8087)
    {
	/* Restore MAIN's hardware coprocessor state. */

	InitSegTemp = FP_SEG(TCB[MainTask].SAV8087);
	InitOffTemp = FP_OFF(TCB[MainTask].SAV8087);
	asm{
	    mov   es,InitSegTemp
	    mov   bx,InitOffTemp
	    cli
	    frstor es:[bx]
	    fwait
	    sti
	}
    }

    PROTECT--;
}

int Cur,Prev,Next;

unsigned TaskBeingSuspended;
unsigned NewStackSeg,NewStackPtr;
unsigned TotalSuspTics;
unsigned SuspTics;
unsigned SuspSegTemp,SuspOffTemp;

/****************************************************************************    
* Function: void interrupt far ExecSuspendFunction(void)
*
* No action is taken if CurrentTask is MAIN or still has additional
* activation counts (which may result from activations which occur while the 
* task is in progress). Otherwise, the context of CurrentTask is saved,
* partly on its stack and partly in its TCB entry. The task being suspended
* (the former CurrentTask) is added to the suspended list according to its
* suspension interval. The highest priority active task is identified. Its
* context is restored and it is resumed. The newly suspended task will resume 
* execution when either 1) Its suspend interval expires, or 2) Another task
* explicitly activates it.
*
* This routine cannot declare any local variables or take any stack
* arguments. Its argument, the number of TICS to suspend the calling task,
* is passed in the _AX register. The task whose TCB index is in CurrentTask 
* must in fact be the current task.
*
* Input: None.

⌨️ 快捷键说明

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