/*Begin Function:_Sys_Init***************************************************** Description : Initiate The Application Memory Page Allocation. Input : Void. Output : Void. ******************************************************************************/ void _Sys_Init(void) //The Paramount Process;Its PID is 0,forever. { u16 Count; while(1) { DISABLE_ALL_INTS(); #if(ENABLE_SIGNAL==TRUE) for(Count=1;Count<MAX_NUMBER_OF_TASKS+1;Count++) //Process The Signals Here. _Sys_Signal_Handler(Count); #endif //The Code Below Sets The Task Sequence. PCB_TASK_SEQ_PTR=0; //Reset The Process PTR. for(Count=1;Count<MAX_NUMBER_OF_TASKS+2;Count++) { //From 1,For "Init" Do Not Count Here. if(((PCB_PID_STATUS[Count]&OCCUPY)!=0)&&((PCB_PID_STATUS[Count]&SLEEP)==0)&&((PCB_PID_STATUS[Count]&ZOMBIE)==0)) { PCB_REMAINING_TIME[Count]=PCB_TIM[Count]; PCB_TASK_SEQ[PCB_TASK_SEQ_PTR++]=Count; //Find Out The PIDs Occupied&Not Sleeping&Not Zombie And Create The Next Schedule Table. } } PCB_TASK_SEQ[PCB_TASK_SEQ_PTR]=0; //The Last Must Be The Init process,Or The System Will Crash.Remember To Decrease The value By One,Or The System To Crash. PCB_TASK_SEQ_PTR=0; //Reset The Process PTR. ENABLE_ALL_INTS(); Sys_Switch_Now(); } }
/* Begin Function:_Sys_Systick_Routine **************************************** Description : The systick interrupt routine. No need to disable interrupts here, because other interrupts may override it. Input : None. Output : None. Return : None. ******************************************************************************/ void _Sys_Systick_Routine(void) { /* Always increase the tick count by one */ if(System_Status.Time.OS_Total_Ticks.Low_Bits==0xFFFFFFFF) { System_Status.Time.OS_Total_Ticks.Low_Bits=0; System_Status.Time.OS_Total_Ticks.High_Bits++; } else System_Status.Time.OS_Total_Ticks.Low_Bits++; /* Process the signals again here, because the process may receive signals from ISR */ _Sys_Signal_Handler(Current_PID); /* Process the timers here - see if any of them is expired */ _Sys_Timer_Handler(); /* Process the system process delay here - see if any of them is expired */ _Sys_Proc_Delay_Handler(); /* Do a scheduling here */ _Sys_Schedule_Trigger(); }
/* Begin Function:_Sys_Get_High_Ready ***************************************** Description : The function for deciding the highest priority task. The routine has a very simple way to decide who's the final task to run at last-it will set the "Current_PID" and the "Current_Prio" correspondingly, and this only the two variables will be used by the assembly function. There's no need to disable interrupts here; because this is always at the lowest priority. Input : None. Output : None. Return : None. ******************************************************************************/ void _Sys_Get_High_Ready(void) { /* See if the scheduler is locked .If yes, then we cannot switch the tasks */ if(Scheduler_Locked==0) { /* The system is booting from "Init" process. We need do abandon the SP automatically * saved by the "SYS_SAVE_SP" assembly function this time. */ if(System_Status.Kernel.Boot_Done==FALSE) { PCB_Cur_SP[0]=PCB[0].Info.Init_Stack_Ptr-PRESET_STACK_SIZE; System_Status.Kernel.Boot_Done=TRUE; } /*If possible, decrease the remaining timeslice by 1.*/ if(PCB[Current_PID].Time.Lft_Tim>0) { PCB[Current_PID].Time.Lft_Tim-=1; } else { /* Refresh the timer */ PCB[Current_PID].Time.Lft_Tim=PCB[Current_PID].Time.Cur_Tim; /* If the priority level still exists, then perform a normal context switch */ if(Prio_List[Current_Prio].Proc_Num!=0) { /* Do normal context switch first - See if the current process is running */ if(((struct PCB_Struct*) (Prio_List[Current_Prio].Running_List.Next)) ->Info.PID==Current_PID) { /* If the current process is running, then put it at the end of the queue */ Sys_List_Delete_Node(PCB[Current_PID].Head.Prev,PCB[Current_PID].Head.Next); Sys_List_Insert_Node((struct List_Head*)&(PCB[Current_PID].Head), Prio_List[Current_Prio].Running_List.Prev, (struct List_Head*)&(Prio_List[Current_Prio].Running_List)); } else { /* Do nothing - The current process is not running */ } } } /* Now get the highest priority level's next process to run */ Current_Prio=((struct Prio_List_Struct*)(Prio_List_Head.Next))->Priority; Current_PID=((struct PCB_Struct*) (Prio_List[Current_Prio].Running_List.Next)) ->Info.PID; } else { /* One of the scheduling action is pending due to scheduler lock. So * after the scheduler unlocks, we will perform a schedule right away. */ Pend_Sched_Cnt++; } /* Refresh the system status,which is only for query*/ System_Status.Kernel.Proc_Running_Ptr=(struct List_Head*)(&(PCB[Current_PID].Head)); System_Status.Kernel.Cur_Prio_Ptr=(struct List_Head*)(&(Prio_List[PCB[Current_PID].Status.Priority].Head)); /* Process the signals here - The signal handlers will be directly called */ _Sys_Signal_Handler(Current_PID); }