📄 os_cpu_a.s
字号:
@*************************************************************************@ uC/OS-II for SkyEye simulator @ @ Revision: 1.0 @ Bugs Report: lmcs00@mails.tsinghua.edu.cn@ Date: Dec 18 2002 1:06:30 @@************************************************************************* .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 块指针,得到该任务的堆栈 sp , @ // 从堆栈 sp 中依次恢复出 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 @----------------------------------------------------------------------- .align 2 .global OSCtxSw .type OSCtxSw,functionOSCtxSw: @ // 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_OSCtxSw: @ // 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 @----------------------------------------------------------------------- @ // 用来临时保存 某些 寄存器的值, 这里不能使用 push 和 pop, 因为前后的 sp 可能会不一样. SAVED_REG: .long 0x00000000 SAVED_LR: .long 0x00000000 .align 2 .global OSTickISR .type OSTickISR,functionOSTickISR: @ // 1) PUSH ALL 将当前执行任务的 CPU 现场保存到 该任务的堆栈中, 注意 pc.return = lr - 4 SUB lr, lr, #4 STMFD sp!, {r0-r12, lr} @ // 1.1) 同时也将 spsr_irq 压入堆栈, spsr_irq = cpsr_svc MRS r4, spsr STMFD sp!, {r4} @ push current spsr @ // 2) 调用系统中断进入和退出的 hook 函数, do_IRQ 是用于更新仿真硬件中断屏蔽位寄存器的操作 BL OSIntEnter @ chy 2003-01-18 the OSTimeTick is called in do_IRQ @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) 将中断前的 CPCS_svc ( 目前保存在 spsr_irq 中 ) 推入堆栈 LDMFD sp!, {r4} MSR spsr, r4 @ // 5) 如果此时 标志位 没有被设置, 则不需要进行调度,直接从中断中返回原来的任务 @ // 使用 ^ 的作用是 可以在恢复 pc 的时候, 同时也把 spsr -> cpsr LDMFD sp!, {r0-r12, pc}^_IntCtxSw: @ // 0) 这里需要首先将那个切换标志 OSIntCtxSwFlag 恢复成 0 LDR r0, =OSIntCtxSwFlag MOV r1, #0 STR r1, [r0] @ // 1) 然后也从栈中恢复 出 spsr_irq = cpsr_svc LDMFD sp!, {r4} MSR spsr, r4 @ // 2) 先恢复堆栈指针 sp 到初始位置:即 PUSH ALL 以前的值,同时恢复原来任务的上下文 LDMFD sp!, {r0-r12, lr} @ // 3) 这里我们先需要保存 r4 作为中间变量, lr_irq 作为将来任务返回的 pc 恢复值 STR r4, SAVED_REG @ 这里需要先借用一下 r4, 所以先把它保存一下 STR lr, SAVED_LR @ 这里需要记录下返回地址 lr_irq , 所以先把它保存一下 @ // 4) 此时需要改变处理器的模式, 以便来恢复 svc 状态下下的 sp_svc 值, 也就是当前任务的"当前"堆栈指针 MOV r4, #0x00000093 MSR cpsr, r4 @ // 5) 这里获得将来进行任务恢复时的 pc 值, 就是中断态下的 lr_irq LDR r4, SAVED_LR @ 这里获得恢复时的 pc 值( lr_irq )放入 r4 @ // 6) 把将来的任务返回地址 lr_irq 压入堆栈 sp_svc 中, 这个 sp_svc 也就是被中断的任务的堆栈指针 STMFD sp!, {r4} @ push pc (lr_irq should be pushed in place of PC) @ // 7) 已经用完了 r4, 这里恢复它的原值 LDR r4, SAVED_REG @ ok, here we recover r4 , because r4 has done its job. @ // 8) 执行保存 CPU 现场的操作, 然后进行跳转任务级的切换代码中 STMFD sp!, {r0-r12,lr} @ push lr & register file MRS r4, spsr STMFD sp!, {r4} @ push current psr MRS r4, spsr STMFD sp!, {r4} @ push current spsr @ // 9) 执行跳转到 任务上下文的切换 代码 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, #0x80 @ // 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_c, r0 @ restore original cpsr @ // 3) 返回 MOV pc, lr @------------------------------------------------------------------------ @-------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -