📄 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 + -