www.pudn.com > 51_00_OS.rar > task_switch.C, change:2006-02-24,size:4059b


/******************************************************* 
*************基于51内核的圈圈操作系统***************** 
本程序只供学习使用,未经作者许可,不得用于其它任何用途 
 
Task_Switch.c file 
 
Created by Computer-lov 
Date: 2005.10.27 
 
Edit date:2006.2.24 
 
Version V1.1 
Copyright(C) Computer-lov 2005-2015 
All rigths reserved 
 
******************************************************/ 
 
#include "AT89X52.h" 
#include "task_switch.h" 
#include "MAIN.H" 
#include "OS_core.h" 
 
///////////////////////////////////////////任务切换函数///////////////////////////////// 
void OS_Task_Switch(void) 
{ 
 static unsigned char i;    //使用static申明局部变量,避免临时变量使用相同地址 
 static unsigned char temp; 
 
 EA=0;                //关中断 
 __asm PUSH ACC       //保护当前任务寄存器 
 __asm PUSH B 
 __asm PUSH PSW 
 __asm PUSH DPL 
 __asm PUSH DPH 
 __asm PUSH 0         //0-7为工作寄存器 
 __asm PUSH 1 
 __asm PUSH 2 
 __asm PUSH 3 
 __asm PUSH 4 
 __asm PUSH 5 
 __asm PUSH 6 
 __asm PUSH 7 
 
 OS_pcb[OS_Current_ID].Task_SP=SP;   //保存当前堆栈指针 
 
 OS_Current_ID=0;     //设置为空闲任务的ID号,优先级最低 
  
 temp=0x01; 
 for(i=0;i<MAX_TASK;i++)   //查找优先级最高的任务 
  { 
   if(OS_Task_List&temp)   //判断是否有该任务 
    { 
     if(OS_pcb[i].Suspend==0)   //查找未挂起任务 
      { 
       if(OS_pcb[i].Priority<OS_pcb[OS_Current_ID].Priority)   //如果优先级高,则切换之 
        { 
         OS_Current_ID=i; 
        } 
      } 
    } 
   temp<<=1;    //调整temp的值,以检查下一个任务 
  } 
 
 SP=OS_pcb[OS_Current_ID].Task_SP;     //任务堆栈指针切换 
 
 __asm POP 7         //恢复任务寄存器 
 __asm POP 6 
 __asm POP 5 
 __asm POP 4 
 __asm POP 3 
 __asm POP 2 
 __asm POP 1 
 __asm POP 0 
 __asm POP DPH 
 __asm POP DPL 
 __asm POP PSW 
 __asm POP B 
 __asm POP ACC 
 
 EA=1;      //开中断 
} 
///////////////////////////////////////////////////////////////////////////////////////////// 
 
 
//////////////////////////////////////////定时器中断服务函数////////////////////////////////// 
void Timer2ISR(void) interrupt 5 using 1 
{ 
 unsigned char i; 
 unsigned char temp; 
 
 EA=0;            //关中断 
 
 __asm PUSH DPL    //保护当前任务寄存器,其中ACC,PSW,B寄存器编译器自动压栈 
 __asm PUSH DPH 
 __asm PUSH 0 
 __asm PUSH 1 
 __asm PUSH 2 
 __asm PUSH 3 
 __asm PUSH 4 
 __asm PUSH 5 
 __asm PUSH 6 
 __asm PUSH 7 
 
 TF2=0;        //清中断标志TF2 
 
 
 if(!OS_Running)  //如果是第一次进入,则调整好堆栈指针位置,使其不返回主函数 
  { 
   SP-=2;         //将堆栈指针下移2,因为从主函数中断时压栈的两个返回地址是无用的 
   for(i=1;i<Num_PUSH_bytes+1;i++)   //同时将刚被压栈的那几个往下平移2个字节 
    { 
     ((unsigned char idata *)(SP-Num_PUSH_bytes))[i]=((unsigned char idata *)(SP-Num_PUSH_bytes+2))[i]; 
    } 
   OS_Running=1;     //开始运行 
   OS_Run_Time=0;   //运行总时间清0 
  } 
 
 OS_Run_Time++;    //每一个时钟节拍,运行总时间加1 
 
 OS_pcb[OS_Current_ID].Task_SP=SP;      //保存当前任务堆栈指针 
 
 OS_Current_ID=0;                    //设置为空闲任务的ID号,优先级最低 
 
 temp=0x01; 
 for(i=0;i<MAX_TASK;i++)          //查找优先级最高的任务 
  { 
   if(OS_Task_List&temp)          //如果此任务存在 
    { 
     if(OS_pcb[i].Delay!=0)            //如果任务需要延时 
      { 
       OS_pcb[i].Delay--;              //延时时间减1 
       if(OS_pcb[i].Delay==0)          //如果延时时间到 
        { 
         OS_pcb[i].Suspend=0;          //任务解挂起 
        } 
      } 
     if(OS_pcb[i].Suspend==0)          //查找未挂起任务 
      { 
       if(OS_pcb[i].Priority<OS_pcb[OS_Current_ID].Priority)   //如果优先级高,则切换之  
        { 
         OS_Current_ID=i; 
        } 
      } 
    } 
   temp<<=1;    //调整temp的值,以检查下一个任务  
  } 
 
 SP=OS_pcb[OS_Current_ID].Task_SP;    //任务堆栈指针切换 
 
 __asm POP 7 
 __asm POP 6 
 __asm POP 5 
 __asm POP 4 
 __asm POP 3 
 __asm POP 2 
 __asm POP 1 
 __asm POP 0 
 __asm POP DPH 
 __asm POP DPL         //恢复任务寄存器 
 
 EA=1;              //开中断 
} 
////////////////////////////////////////////////////////////////////////////////////////////