任务切换
在多任务情况下,利用中断功能,以及现场保护。
当前任务->停止->用到的寄存器入栈->时间片到了->出栈->恢复继续执行
一共有三个任务为例:
任务1,任务2,任务三。
当时间片1ms到来的时候进入中断,这时候cpu将一部分寄存器入栈,然后freeRTOS又将其他用到的寄存器入栈。注意入的是任务栈,不是cpu的中断处理栈。然后freeRTOS将sp指针指向任务2的栈,将栈帧里面的PC指针指向任务2的PC,LR寄存器也改成任务2的LR。cpu恢复现场的时候就不是恢复任务1的现场,而是任务2的现场,从而达到任务切换的效果。
AI修改后
假设任务1、任务2、任务3 同优先级,按 1ms 时间片轮转。
任务1正在跑:
- CPU 的 PSP 指向任务1的栈。
- PC 指向任务1当前执行到的代码。
1ms 时间片到了:
- SysTick 中断触发,FreeRTOS 通常请求 PendSV,真正切换在 PendSV 里做。
- CPU 硬件自动把任务1的一部分现场压入“任务1自己的栈”:
- R0、R1、R2、R3、R12、LR、PC、xPSR
- FreeRTOS 在 PendSV 里再把剩下的现场压入任务1的栈:
- R4 ~ R11
- 然后把当前 SP/PSP 保存到任务1的 TCB:
TCB1.SP = 任务1栈顶
- 调度器选择下一个任务:任务2。
- 从
TCB2里取出任务2的 SP,让 PSP 指向任务2的栈。 - 从任务2的栈里恢复 R4 ~ R11。
- PendSV 异常返回时,CPU 硬件自动从任务2的栈里弹出:
- R0、R1、R2、R3、R12、LR、PC、xPSR
- 于是 PC 变成任务2上次暂停的位置,CPU 继续跑任务2。
任务2跑 1ms 后,同理保存到任务2的 TCB,再切到任务3。任务3跑完再切回任务1。
任务1栈:
... [R4-R11] [R0-R3, R12, LR, PC, xPSR] <- 切出时 PSP 保存到 TCB1
任务2栈:
... [R4-R11] [R0-R3, R12, LR, PC, xPSR] <- 切入时 PSP 从 TCB2 取出
TCB1 -> 保存任务1的 SP
TCB2 -> 保存任务2的 SP
TCB3 -> 保存任务3的 SP