?? os_cpu_a.s
字號:
.file "os_cpu_a.S".text @------------------------------------------------------------------------- .align 2 .global OSStartHighRdy .type OSStartHighRdy,functionOSStartHighRdy: @ // 1) 調用 用戶編寫的 hook 函數 BL OSTaskSwHook @ Call user defined task switch hook @ // 2) 設置 OSRunning 變量為 true , 表示多任務調度開始 LDR r4,=OSRunning @ Indicate that multitasking has started MOV r5, #1 STRB r5, [r4] @ // 3) 獲得最高優先級任務的 TCB 塊指針,得到該任務的堆棧, @ // 從堆棧中依次恢復出 SPSR, CPSR, r0-r12, lr, pc LDR r4, =OSTCBHighRdy @ Get highest priority task TCB address LDR r4, [r4] @ get stack pointer LDR sp, [r4] @ switch to the new stack LDMFD sp!, {r4} @ pop new task s spsr MSR SPSR, r4 LDMFD sp!, {r4} @ pop new task s psr MSR CPSR, r4 LDMFD sp!, {r0-r12,lr,pc} @ pop new task s r0-r12,lr & pc @ End of OSStartHighRdy @----------------------------------------------------------------------- .align 2 .global OSCtxSw .type OSCtxSw,functionOSCtxSw:/* Perform a context switch. On entry, OSTCBCur and OSPrioCur hold the current TCB and priority and OSTCBHighRdy and OSPrioHighRdy contain the same for the task to be switched to. The following code assumes that the virtual memory is directly mapped into physical memory. If this is not true, the cache must be flushed at context switch to avoid address aliasing.*/ @ // 1) PUSH ALL 將當前執行任務的 CPU 現場保存到 該任務的堆棧中 @ // 依次將 pc, lr, r12-r0, CPSR, SPSR 推入 堆棧 sp 中 STMFD sp!, {lr} @ push pc (lr should be pushed in place of PC) STMFD sp!, {r0-r12,lr} @ push lr & register file MRS r4, cpsr STMFD sp!, {r4} @ push current psr MRS r4, spsr STMFD sp!, {r4} @ push current spsr @ // 2) 設置當前優先級為最高任務的優先級 OSPrioHighRdy @ OSPrioCur = OSPrioHighRdy LDR r4, =OSPrioCur LDR r5, =OSPrioHighRdy LDRB r6, [r5] STRB r6, [r4] @ // 3) 獲得當前執行任務的 TCB 塊指針 @ Get current task TCB address LDR r4, =OSTCBCur LDR r5, [r4] STR sp, [r5] @ store sp in preempted tasks s TCB @ // 4) 調用用戶定義的 hook 函數 BL OSTaskSwHook @ call Task Switch Hook @ // 5) 獲得最高優先級任務的 TCB 塊指針, 并且將它的堆棧指針復制到 CPU 的 sp 中, 改變當前堆棧 @ Get highest priority task TCB address LDR r6, =OSTCBHighRdy LDR r6, [r6] LDR sp, [r6] @ get new task s stack pointer @ // 6) 將最高優先級任務的 TCB 塊指針 復制到 當前任務 TCB 指針中 @ OSTCBCur = OSTCBHighRdy STR r6, [r4] @ set new current task TCB address @ // 7) 將堆棧中保存的最高優先級任務的 CPU 現場恢復出來 @ // 一次從堆棧中彈出 SPSR, CPSR, r0-r12, lr, pc LDMFD sp!, {r4} @ pop new task s spsr MSR SPSR, r4 LDMFD sp!, {r4} @ pop new task s psr MSR CPSR, r4 LDMFD sp!, {r0-r12,lr,pc} @ pop new task s r0-r12,lr & pc @----------------------------------------------------------------------- .align 2 .global OSIntCtxSw .type OSIntCtxSw,functionOSIntCtxSw: @ // 1) 這個就是會被 OSIntExit() 調用的 OSIntCtxSw() 函數入口 @ // 在這里的處理僅僅是設置了一個標志位 OSIntCtxSwFlag = True @ OSIntCtxSwFlag = True LDR r0, =OSIntCtxSwFlag MOV r1, #1 STR r1, [r0] @ // 2) 函數返回 MOV pc, lr .align 2 .global OSTickISR .type OSTickISR,functionOSTickISR: @ // 1) PUSH ALL 將當前執行任務的 CPU 現場保存到 該任務的堆棧中 STMDB sp!, {r0-r11, lr} @ // 2) 調用系統中斷進入和退出的 hook 函數 @BL OSIntEnter BL OSTimeTick BL do_IRQ @BL OSIntExit @ // 3) 從 OSIntExit() 中退出時,如果需要進行中斷級的上下文切換,則系統會調用 OSIntCtxSw @ // 其結果就是 此時的標志位 OSIntCtxSwFlag == True LDR r0, =OSIntCtxSwFlag LDR r1, [r0] CMP r1, #1 BEQ _IntCtxSw @ // 如果此時標志位被設置,則跳轉到 _IntCtxSw 執行中斷級的上下文切換 @ // 4) 如果此時 標志位 沒有被設置, 則不需要進行調度,直接從中斷中返回原來的任務 LDMFD sp!, {r0-r11, lr} SUBS pc, lr, #4 _IntCtxSw: @ // 3.0) 改變處理器模式, MRS lr, SPSR AND lr, lr, #0xFFFFFFE0 ORR lr, lr, #0x13 MSR CPSR, lr @ // 3.1) 先恢復堆棧指針 sp 到初始位置:即 1) PUSH ALL 以前的值,同時恢復原來任務的上下文 LDMFD sp!, {r0-r11, lr} SUB lr, lr, #4 @ // 3.2) 執行跳轉到 任務上下文的切換 代碼 B OSCtxSw @---------------------------------------------------------------------- .align 2 .global ARMDisableInt .type ARMDisableInt,functionARMDisableInt: @ // 1) 保存 CPSR 到當前任務的堆棧 => push CPSR MRS r0, CPSR STMFD sp!, {r0} @ push current PSR @ // 2) 設置 CPSR 的中斷屏蔽位 @ORR r0, r0, #0xC0 @ mask IRQ Int s ORR r0, r0, #0x80 @ mask IRQ Int s @ // 3) 屏蔽中斷 MSR CPSR, r0 @ disable IRQ Int s @ // 4) 返回 MOV pc, lr @------------------------------------------------------------------------ .align 2 .global ARMEnableInt .type ARMEnableInt,functionARMEnableInt: @ // 1) 從堆棧中彈出 CPSR => pop CPSR 到 r0 LDMFD sp!, {r0} @ pop current PSR @ // 2) 用 r0 來恢復 CPSR MSR CPSR, r0 @ restore original CPSR @ // 3) 返回 MOV pc, lr @------------------------------------------------------------------------ @-------------------------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -