void OSStart (void) { if (OSRunning == OS_FALSE) { OS_SchedNew(); /* Find highest priority's task priority number */ OSPrioCur = OSPrioHighRdy; //最高優先級賦給 當前優先級 OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* 從TCB鏈表中取出最高優先級 賦給 最高級TCB */ OSTCBCur = OSTCBHighRdy; //最高優先級賦給 當前優先級 OSStartHighRdy(); /* */ } }
// 系統執行命令爲彙編代碼 OSStartHighRdy ;設置pendSV中斷優先級 0xff LDR R4, =NVIC_SYSPRI2 ; PendSV 中斷 LDR R5, =NVIC_PENDSV_PRI ;0xff STR R5, [R4] ;將R5寄存器值賦到R4中 ;設置堆棧指針爲0 MOV R4, #0 ; set the PSP to 0 for initial context switch call MSR PSP, R4 ;MSR將R4值賦給PSP ; OSRunning = TRUE LDR R4, =OSRunning ;將=OSRunning指令地址放到R4中 MOV R5, #1 STRB R5, [R4] ;將R5寄存器數據寫入R4地址內存中 ;切換到最高優先級的任務 LDR R4, =NVIC_INT_CTRL ;rigger the PendSV exception (causes context switch) LDR R5, =NVIC_PENDSVSET STR R5, [R4] ;切換到最高級中斷 使能PendSV SysTick中斷 CPSIE I ;開中斷的彙編代碼 OSStartHang B OSStartHang ;should never get here
以上是任務建立的全過程;cpu的PSP初始化爲0來運行咱們系統中優先級最高的任務並將OSRunning標記爲true來表示咱們的內核開始運行了。spa
PendSV_Handler CPSID I ; 關因此中斷 MRS R0, PSP ; PSP是當前進程堆棧的指針,將PSP賦值給R0 CBZ R0, PendSV_Handler_Nosave ; 若是R0爲0時跳轉到PendSV_Handler_Nosave ;已經存在任務 保存正在運行的任務 SUBS R0, R0, #0x20 ; 偏移0x20的位置用來保存R4至R11 STM R0, {R4-R11} ;將剩下的R4至R11寄存器保存在此進程的堆棧中 LDR R1, =p_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; 即OSTCBCur->OSTCBStkPtr這個保存當前的棧尾,以便下次彈出 LDR R1, [R1] STR R0, [R1] ; R0 is SP of process being switched out ;此時,整個上下文的過程已經被保存 PendSV_Handler_Nosave PUSH {R14} ; Save LR exc_return value LDR R0, =OSTaskSwHook ; OSTaskSwHook(); 這裏用於用戶擴展 BLX R0 POP {R14} ;將最高優先級任務賦給當前優先級 LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; LDR R1, =OSPrioHighRdy ;將當前優先級變量指向最高優先級 LDRB R2, [R1] STRB R2, [R0] LDR R0, =p_OSTCBCur ; OSTCBCur = OSTCBHighRdy; LDR R1, =p_OSTCBHighRdy ;TCB表也同樣 LDR R2, [R1] STR R2, [R0] ;到這裏,[R2]保存的是新的進程的堆棧指針SP LDR R0, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; LDM R0, {R4-R11} ; 彈出其它寄存器,和前面的是一個逆過程 ADDS R0, R0, #0x20 ;和前面的逆過程對比可知 MSR PSP, R0 ; 將R0中的SP賦值給PSP寄存器 ORR LR, LR, #0x04 ; 確保異常返回時使用進程堆棧 CPSIE I ;開中斷 BX LR ; 異常返回將恢復那些自動出棧的剩餘寄存器 ;跳到當前任務 開始運行
這裏是系統默認中斷作的事:主要工做有判斷是否第一次運行、將最高級任務賦給當前任務,而後將放到cpu寄存器運行,最高優先級任務開始運行。.net
系統任務切換則是靠OSTimeDly,下節介紹指針