[技术问答] 汇编代码在PendSV中断服务例程中的具体操作流程是怎样的?

[复制链接]
665|10
爱丽丝的梦 发表于 2025-9-23 14:59 | 显示全部楼层 |阅读模式
汇编代码在PendSV中断服务例程中的具体操作流程是怎样的?
灰色与青 发表于 2025-10-5 16:09 | 显示全部楼层
PendSV 中断服务例程汇编流程:先压栈保存当前寄存器(R0-R15 等)到任务栈,更新当前任务栈指针;再加载下一个任务的栈指针,从新栈中恢复寄存器;最后执行 BX LR 指令退出中断,切换到新任务运行,实现上下文切换。
yiy 发表于 2025-10-9 14:02 | 显示全部楼层
在PendSV中断服务例程中,汇编代码主要负责处理上下文切换(Context Switching)。
yiy 发表于 2025-10-9 14:02 | 显示全部楼层
1. 进入PendSV中断
当PendSV异常触发时,处理器自动将以下寄存器压入当前任务的堆栈:

xPSR(程序状态寄存器)

PC(程序计数器)

LR(链接寄存器)

R12、R3、R2、R1、R0
yiy 发表于 2025-10-9 14:02 | 显示全部楼层
2. 保存当前任务上下文
  1. PendSV_Handler:
  2.     ; 禁用中断(可选,根据具体实现)
  3.     CPSID I
  4.    
  5.     ; 保存剩余寄存器到当前任务堆栈
  6.     MRS R0, PSP          ; 获取当前任务的堆栈指针
  7.     SUBS R0, R0, #0x20   ; 为R4-R11预留空间
  8.     STM R0!, {R4-R11}    ; 保存R4-R11寄存器
  9.    
  10.     ; 保存当前任务堆栈指针到TCB
  11.     LDR R1, =CurrentTCB  ; 获取当前TCB地址
  12.     LDR R2, [R1]
  13.     STR R0, [R2]         ; 更新TCB中的堆栈指针
yiy 发表于 2025-10-9 14:03 | 显示全部楼层
3. 切换任务控制块
  1.     ; 切换到下一个任务的TCB
  2.     LDR R1, =NextTCB     ; 获取下一个TCB地址
  3.     LDR R2, [R1]
  4.     LDR R1, =CurrentTCB
  5.     STR R2, [R1]         ; 更新CurrentTCB为NextTCB
yiy 发表于 2025-10-9 14:03 | 显示全部楼层
4. 恢复新任务上下文
  1.     ; 从新任务的TCB恢复堆栈指针
  2.     LDR R0, [R2]         ; 获取新任务的堆栈指针
  3.    
  4.     ; 恢复R4-R11寄存器
  5.     LDM R0!, {R4-R11}    ; 从堆栈恢复R4-R11
  6.    
  7.     ; 更新PSP为新任务的堆栈指针
  8.     MSR PSP, R0
  9.    
  10.     ; 确保使用PSP作为堆栈指针
  11.     ORR LR, LR, #0x04    ; 设置LR的bit2,表示返回时使用PSP
yiy 发表于 2025-10-9 14:03 | 显示全部楼层
5. 退出中断并切换任务
  1.     ; 重新启用中断
  2.     CPSIE I
  3.    
  4.     ; 中断返回,自动从堆栈恢复剩余寄存器
  5.     BX LR                ; 返回到新任务
yiy 发表于 2025-10-9 14:03 | 显示全部楼层
完整的PendSV处理程序示例
  1. PendSV_Handler:
  2.     CPSID I                   ; 禁用中断
  3.     MRS R0, PSP              ; 获取当前任务堆栈指针
  4.    
  5.     ; 判断是否是第一次上下文切换
  6.     CBZ R0, PendSV_NoSave    ; 如果PSP为0,跳过保存
  7.    
  8.     ; 保存当前任务上下文
  9.     SUBS R0, R0, #0x20       ; 为R4-R11预留32字节空间
  10.     STM R0!, {R4-R11}        ; 保存寄存器
  11.    
  12.     LDR R1, =CurrentTCB
  13.     LDR R2, [R1]
  14.     STR R0, [R2]             ; 保存堆栈指针到当前TCB

  15. PendSV_NoSave:
  16.     ; 切换任务
  17.     LDR R1, =CurrentTCB
  18.     LDR R2, =NextTCB
  19.     LDR R3, [R2]
  20.     STR R3, [R1]             ; 更新CurrentTCB
  21.    
  22.     ; 恢复新任务上下文
  23.     LDR R0, [R3]             ; 获取新任务堆栈指针
  24.     LDM R0!, {R4-R11}        ; 恢复寄存器
  25.     MSR PSP, R0              ; 更新PSP
  26.    
  27.     ORR LR, LR, #0x04        ; 设置返回使用PSP
  28.     CPSIE I                  ; 启用中断
  29.     BX LR                    ; 返回到新任务
yiy 发表于 2025-10-9 14:04 | 显示全部楼层
双堆栈指针:MSP(主堆栈指针)用于异常处理,PSP(进程堆栈指针)用于任务

惰性保存:硬件自动保存部分寄存器,软件保存剩余寄存器

原子操作:在保存和恢复上下文期间通常需要禁用中断

堆栈对齐:需要确保堆栈指针在上下文切换后保持正确的对齐

这种设计使得PendSV成为实时操作系统中实现高效上下文切换的理想选择。
北海道没有冬天 发表于 2025-10-9 21:06 | 显示全部楼层
PendSV 中断服务例程汇编流程:先保存当前寄存器状态到栈中,再判断是否需要任务切换。若切换,读取新任务栈顶指针,从新任务栈恢复寄存器值,最后 PendSV 中断返回,完成上下文切换。此过程确保任务切换无冲突,常用于 RTOS 任务调度。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

57

主题

129

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部