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

📄 rtexec.c

📁 GPS导航定位程序
💻 C
📖 第 1 页 / 共 3 页
字号:
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void interrupt far ExecSuspendFunction(void)
{
    /* DO NOT declare any local variables. */

    disable();

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

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

    PROTECT++;
    SuspTics = _AX;

    if(CurrentTask==MainTask)
    {
	PROTECT--;

#if (CompilerVersion==31) && (INSTRMODE==32)
	asm{
	    db   0x66                                           /* OPSIZ:. */
	    db   0x61                                             /* POPA. */
	}
#endif

	return;                               /* MAIN cannot be suspended. */
    }

    if(TCB[TaskBeingSuspended].Active > 1)
    {
	/* The task still has activation counts.  Let it continue. */

	TCB[TaskBeingSuspended].Active -= 1;
	PROTECT--;
#if (CompilerVersion==31) && (INSTRMODE==32)
	asm{
	    db   0x66          /* OPSIZ: */
	    db   0x61          /* POPA */
	}
#endif
	return;
    }

    /* Save the context of the task being suspended. */

    TaskBeingSuspended = CurrentTask;
    if(_8087)
    {
	/* Save the coprocessor state without waiting for the pending
	   operation to complete. Wait for the save to complete before
	   proceeding. */

	SuspSegTemp = FP_SEG(TCB[TaskBeingSuspended].SAV8087);
	SuspOffTemp = FP_OFF(TCB[TaskBeingSuspended].SAV8087);

	asm{
	    mov   es,SuspSegTemp
	    mov   bx,SuspOffTemp
	    fnsave es:[bx]
	    fwait
	}
    }

    TCB[TaskBeingSuspended].SAVSS = _SS;
    TCB[TaskBeingSuspended].SAVSP = _SP;

    /* Find where to place the task in the suspend list. */

    if(SuspTask == -1)
    {

	/* Suspend list is empty: put task at the head of the list. */

	SuspTask = TaskBeingSuspended;
	TCB[TaskBeingSuspended].SuspTics = SuspTics;
	TCB[TaskBeingSuspended].NxtSusp = -1;
    }
    else
    {
	/* Suspend list is nonempty:  insert task in the list. */

	TotalSuspTics = 0;
	Cur = SuspTask;
	Prev = -1;
	while(TRUE)
	{
	    if(SuspTics < (TCB[Cur].SuspTics+TotalSuspTics))
	    {
		/* The task which is being suspended is scheduled to resume
		   before Cur. Insert the new entry before this task. Note
		   that the newly suspended task is inserted into the list
		   AFTER all other tasks which have suspension intervals that
		   expire at the same time. */

		TCB[TaskBeingSuspended].NxtSusp = Cur;
		TCB[Cur].SuspTics -= (SuspTics - TotalSuspTics);
		if(Prev == -1)
		{
		    SuspTask = TaskBeingSuspended;
		    TCB[TaskBeingSuspended].SuspTics = SuspTics;
		}
		else
		{
		    TCB[Prev].NxtSusp = TaskBeingSuspended;
		    TCB[TaskBeingSuspended].SuspTics =
						    SuspTics - TotalSuspTics;
		}
		break;
	    }

	    TotalSuspTics += TCB[Cur].SuspTics;
	    Prev = Cur;
	    Cur = TCB[Cur].NxtSusp;
	    if(Cur == -1)
	    {

		/* The task now being suspended is scheduled to resume later
		   than any other task in the suspend list. Insert it at the 
		   end of the list. */

		TCB[Prev].NxtSusp = TaskBeingSuspended;
		TCB[TaskBeingSuspended].NxtSusp = -1;
		TCB[TaskBeingSuspended].SuspTics = SuspTics - TotalSuspTics;
		break;
	    }
	}
    }

    /* Inactivate TaskBeingSuspended. Find the highest priority active
       task and make it the new current task. */

    TCB[TaskBeingSuspended].Active = 0;
    for(CurrentTask=0;CurrentTask<=MainTask;CurrentTask++)
	if(TCB[CurrentTask].Active)
	    break;
    CurrentStack = TCB[CurrentTask].STRTSS;
    TCB[CurrentTask].Slices++;

    /* Restore the context of the new CurrentTask and resume it. */

    _SS = TCB[CurrentTask].SAVSS;
    _SP = TCB[CurrentTask].SAVSP;
    if(_8087)
    {
	SuspSegTemp = FP_SEG(TCB[CurrentTask].SAV8087);
	SuspOffTemp = FP_OFF(TCB[CurrentTask].SAV8087);
	asm{
	    mov   es,SuspSegTemp
	    mov   bx,SuspOffTemp
	    frstor es:[bx]
	    fwait
	}
    }

    PROTECT--;

#if (CompilerVersion==31) && (INSTRMODE==32)
    asm{
	db   0x66          /* OPSIZ: */
	db   0x61          /* POPA */
    }
#endif

    return;
}

/****************************************************************************    
* Function: void Suspend(unsigned SuspTics)
*
* This is an interface between ExecSuspendFunction and calling tasks. This is 
* because calling tasks cannot pass a parameter reentrantly to an procedure
* defined as interrupt without using a register, and it's inelegant to
* require an application-level task to use in-line assembly language. Can
* only be called from a task. Suspends the calling task for a specified
* interval.
*
* Input: SuspTics - suspend interval in TICs.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void Suspend(unsigned SuspTics)
{
    _AX = SuspTics;
    ExecSuspendFunction();
}

volatile TaskBeingActivated;
volatile ActSegTemp,ActOffTemp;

/****************************************************************************    
* Function: void interrupt far ExecActivateFunction(void)
*
* Removes a task from the suspend list (if it is there) and marks it 
* activated. If the task is higher priority that the one that activated it
* by calling this routine, a task switch takes place. This routine cannot
* declare any local variables or take any stack arguments. Its argument, the
* index of the task to be activated, is passed in the _AX register. The
* specified task is removed from the suspended list, if it was in fact
* suspended. The activation count of the task is incremented. If the calling 
* task cannot be positively identified as the CurrentTask, we leave the
* situation there and return to the caller. Otherwise, the priority of the
* CurrentTask is compared with the priority of the newly activated task.
* Depending on whether the newly acttivated task is higher priority, the
* context of CurrentTask may be saved and a switch to the newly activated
* task performed.
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void interrupt far ExecActivateFunction(void)
{
    /* DO NOT declare any local variables. */

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

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

    PROTECT++;
    TaskBeingActivated = _AX;

    /* Remove the task from the suspended list (if it is on that list). */

    if(SuspTask != -1)
    {
	Cur = SuspTask;
	Prev = -1;
	while(TRUE)
	{
	    if(Cur == -1)              /* Task wasn't in the suspend list. */
		break;
	    if(Cur != TaskBeingActivated)  /* Other task.  Keep searching. */
	    {
		Prev = Cur;
		Cur = TCB[Cur].NxtSusp;
		continue;
	    }

	    /* "Cur" is the index of the task to be activated.  Take it out
	       of the suspend list. */

	    Next = TCB[Cur].NxtSusp;
	    if(Prev == -1)
		SuspTask = Next;
	    else
		TCB[Prev].NxtSusp = Next;
	    if(Next != -1)
		TCB[Next].SuspTics += TCB[Cur].SuspTics;
	    break;
	}
    }

    disable();
    TCB[TaskBeingActivated].Active += 1;  /* Incr task's activation count. */

    /* Don't switch tasks if:

       1) We weren't called from the context of the current application
	  task (that is, the active stack isn't the one that was
	  originally assigned to the task), or
       2) The caller was in a protected region of code, as indicated by
	  PROTECT.  This is indicated if PROTECT>1, since on entry to
	  this routine we incremented PROTECT.

       In these cases, just leave the task in the active list and it will
       eventually get into execution through the normal operation of the
       task switcher. */

    if(_SS!=CurrentStack || PROTECT>1)
    {
	PROTECT--;

#if (CompilerVersion==31) && (INSTRMODE==32)
	asm{
	    db   0x66                                           /* OPSIZ:. */
	    db   0x61                                             /* POPA. */
	}
#endif

	return;
    }

    /* If TaskBeingActivated has equal or lower priority than CurrentTask,
       just return to the calling task. Otherwise, save CurrentTask's
       context, select a new CurrentTask, and resume it. */

    if(TaskBeingActivated < CurrentTask)
    {
	/* Save the context of CurrentTask. */

	if(_8087)
	{

	    /* Save the coprocessor state without waiting for any pending
	       operation to complete, then wait for the save to complete
	       before proceeding. */

	    ActSegTemp = FP_SEG(TCB[CurrentTask].SAV8087);
	    ActOffTemp = FP_OFF(TCB[CurrentTask].SAV8087);
	    asm{
		mov   es,ActSegTemp
		mov   bx,ActOffTemp
		fnsave es:[bx]
		fwait
	    }
	}
	TCB[CurrentTask].SAVSS = _SS;
	TCB[CurrentTask].SAVSP = _SP;

	/* TaskBeingActivated is the new CurrentTask. */

	CurrentTask = TaskBeingActivated;
	CurrentStack = TCB[CurrentTask].STRTSS;
	TCB[CurrentTask].Slices++;

	/* Restore the new CurrentTask's context. */

	_SS = TCB[CurrentTask].SAVSS;
	_SP = TCB[CurrentTask].SAVSP;

	if(_8087)
	{
	    ActSegTemp = FP_SEG(TCB[CurrentTask].SAV8087);
	    ActOffTemp = FP_OFF(TCB[CurrentTask].SAV8087);
	    asm{
		mov   es,ActSegTemp
		mov   bx,ActOffTemp
		frstor es:[bx]
		fwait
	    }
	}
    }

    PROTECT--;

#if (CompilerVersion==31) && (INSTRMODE==32)
    asm{
	db   0x66                                               /* OPSIZ:. */
	db   0x61                                                 /* POPA. */
    }
#endif

    return;
}

/****************************************************************************    
* Function: void Activate(char *TaskName)
*
* This is an interface between ExecActivateFunction and calling tasks. This
* is because calling tasks cannot pass a parameter reentrantly to an
* procedure defined as interrupt without using a register, and it's
* inelegant to require an application-level task to use in-line assembly
* language. Can only be called from a task. Activates the specified task,
* cancelling a suspend interval if necessary. May cause a task switch if the
* activated task is higher priority that the calling task.
*
* Input: TaskName - pointer to the task name string.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void Activate(char *TaskName)
{
    int i;

    for(i=0;i<MainTask;i++)
    {
	if(stricmp(TCB[i].TNAME,TaskName)==0)
	{

⌨️ 快捷键说明

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