/*Begin Function:main**********************************************************
Description : The Entrance Of The OS.Must Be Set Here.
Input       : Void.
Output      : int-dummy.
******************************************************************************/
int main(void)		                                                           //The main function will only be run ONCE.
{	
	//_Sys_Memory_Init(APP_AVAIL_MEM_START,APP_AVAIL_MEM_END);				   //Not 0x20005000,Or It Will Cause A Implicit Hard Fault.
	_Sys_Kernel_Load(0x20004F50);                                              //The Timeslice Is Dummy.The Init Process Use A Different Way of Context Switching.
	_Sys_Proc_Load(_Sys_Arch,0x20004E00,1,2,(u8*)"Arch");                      //The Arch Process,Which Does Some Chores.Its PID is 1,forever.
	_Sys_Proc_Load(Task1,0x20004C00,2,2,(u8*)"Main_GUI");                      //The GUI Process,Normally.
	_Sys_Proc_Load(Task2,0x20004A00,3,2,(u8*)"Driver_1");			           //The Driver Process 1,Normally.
	//_Sys_Proc_Load(Task3,0x20003900,4,2,(u8*)"Driver_2");                      //The Driver Process 2,Normally.
    _Sys_Systick_Init(0x00010000);                                             //Initialize The System Clock.
	
    _Sys_Start();                                                              //Start From The First PID.
	while(1);												                   //Dead Loop.
	//return(0);											                   //Unreachable Statement.Commented Out.
}
/* Begin Function:_Sys_Load_Init **********************************************
Description : The loader of the "Init" process. The "Init" process is the first
              process in the system, and its priority is the highest at first.
              After it has done the process initialization task, its priority
              will be the lowest one.
Input       : None. 
Output      : None.
Return      : None.
******************************************************************************/
void _Sys_Load_Init(void)                                                  
{   
    /* Load it as a routine*/
    struct Proc_Init_Struct Process;

    Process.PID=0;
    Process.Name=(s8*)"Init";								                                 
    Process.Entrance=_Sys_Init;                                                             
    Process.Stack_Address=(ptr_int_t)Kernel_Stack;				                                          
    Process.Stack_Size=KERNEL_STACK_SIZE;
    Process.Max_Slices=4;                                                           
    Process.Min_Slices=1;                                                           
    Process.Cur_Slices=2;                                                                                                      
    Process.Priority=0;
    Process.Ready_Flag=READY;
    
    /* Load the init process */
    _Sys_Proc_Load(&Process); 

    /* Set the "Current_PID" and "Current_Prio" manually */
    Current_PID=0;
    Prio_List[0].Proc_Num=1;
    Current_Prio=PCB[0].Status.Priority;
         
    /* Set the left time of "Init" to 0 to trigger a normal context switch */
    PCB[0].Time.Lft_Tim=0; 
    
    /* Call the "Init" process function. Never returns.*/
    _Sys_Init();             
}
/* Begin Function:Sys_Start_On_Boot *******************************************
Description : The function will be called by the init process when booting the system.
              The processes referred to will be started on boot.
Input       : None.
Output      : None.
******************************************************************************/
void Sys_Start_On_Boot(void)
{
    /* These processes will be started at the beginning. They will be started by the
     * init process. We can specify the PID for each process when we are booting
     * the OS.
     */
    struct Proc_Init_Struct Process;

    Process.PID=1;
    Process.Name=(s8*)"Arch";
    Process.Entrance=_Sys_Arch;
    Process.Stack_Address=(ptr_int_t)Arch_Stack;
    Process.Stack_Size=ARCH_STACK_SIZE;
    Process.Max_Slices=4;
    Process.Min_Slices=1;
    Process.Cur_Slices=1;
    Process.Priority=1;
    Process.Ready_Flag=READY;
    _Sys_Proc_Load(&Process);

    Process.PID=2;
    Process.Name=(s8*)"Proc1_PID_2";
    Process.Entrance=Proc1;
    Process.Stack_Address=(ptr_int_t)App_Stack_1;
    Process.Stack_Size=APP_STACK_1_SIZE;
    Process.Max_Slices=4;
    Process.Min_Slices=1;
    Process.Cur_Slices=3;
    Process.Priority=1;
    Process.Ready_Flag=READY;
    _Sys_Proc_Load(&Process);

    Process.PID=3;
    Process.Name=(s8*)"Proc2_PID_3";
    Process.Entrance=Proc2;
    Process.Stack_Address=(ptr_int_t)App_Stack_2;
    Process.Stack_Size=APP_STACK_2_SIZE;
    Process.Max_Slices=4;
    Process.Min_Slices=1;
    Process.Cur_Slices=3;
    Process.Priority=1;
    _Sys_Proc_Load(&Process);
}