PRESERVE8 ; 8 字节对齐 THUMB ; 使用 Thumb 指令集 AREA |.text|, CODE, READONLY ; 定义代码段 EXPORT PendSV_Handler ; 导出 PendSV_Handler 符号 IMPORT current_task ; 从 C 代码导入 current_task 指针 IMPORT next_task ; 从 C 代码导入 next_task 指针 IMPORT switch_to_next_task ; 从 C 代码导入 switch_to_next_task 函数 PendSV_Handler PROC ;-------------------------------------------------- ; 1. 关闭中断(确保不会被更高优先级任务打断) ;-------------------------------------------------- CPSID I ; 禁用中断 (PRIMASK=1) CPSID F ; 禁用快速中断 (FAULTMASK=1) ;-------------------------------------------------- ; 2. 更新当前任务的栈指针到 TCB ;-------------------------------------------------- LDR R1, = current_task ; 加载 current_task 的地址到 R1 LDR R1, [R1] ; 获取 current_task 指针的值(TCB地址) CBZ R1, switch_nosave ; 如果获取到底SP为空就不需要保存,并且跳转到switch_nosave函数 ;-------------------------------------------------- ; 3. 保存当前任务上下文(R4-R11 手动保存) ; 硬件自动保存: R0-R3, R12, LR, PC, PSR (通过 PSP) ;-------------------------------------------------- MRS R0, PSP ; 获取当前任务的栈指针 PSP STMFD R0!, {R4-R11} ; 将 R4-R11 压入任务栈(地址递增) STR R0, [R1] ; 将PSP保存进TCB的SP switch_nosave ;-------------------------------------------------- ; 4. 切换当前任务和下一个任务(调用 C 函数) ;-------------------------------------------------- BL switch_to_next_task ; 调用 C 函数witch_to_next_task 获取下一个TCB ;-------------------------------------------------- ; 5. 加载下一个任务的上下文 ;-------------------------------------------------- LDR R1, = current_task ; 重新加载 current_task(此时已切换为新任务) LDR R2, [R1] ; 获取新任务的 TCB 地址 LDR R0, [R2] ; 从 TCB 中获取新任务的栈指针 PSP ;-------------------------------------------------- ; 6. 恢复新任务的 R4-R11 寄存器 ;-------------------------------------------------- LDMFD R0!, {R4-R11} ; 从栈中弹出 R4-R11(地址递减) ;-------------------------------------------------- ; 7. 更新 PSP 为新任务的栈指针 ;-------------------------------------------------- MSR PSP, R0 ; 设置新任务的栈指针 PSP ;-------------------------------------------------- ; 8. 恢复中断并退出异常 ;-------------------------------------------------- CPSIE F ; 启用快速中断 (FAULTMASK=0) CPSIE I ; 启用中断 (PRIMASK=0) ;-------------------------------------------------- ; 9. 异常返回(硬件自动恢复 R0-R3, R12, LR, PC, PSR) ; LR 需包含 EXC_RETURN 值(例如 0xFFFFFFFD 表示使用 PSP) ;-------------------------------------------------- MOV LR, #0xFFFFFFFD ; EXC_RETURN 标志:返回线程模式并使用 PSP BX LR ; 退出异常,开始执行新任务 ENDP ALIGN ; 确保代码对齐 END