必备知识:
PendSV是什么?
根据 权威指南。为系统设备而设的“可悬挂请求”(pendable request)。
1.上下文切换 不能在中断中进行,会导致中断延期。为了解决这个问题,使用 PendSV。PendSV可以挂起,也就是等到别的 ISR结束后 缓期执行。
2.所以 PendSV是一个最低优先级的异常。
Cortex-M3内核有两个堆栈指针
:MSP-主堆栈指针和PSP-进程堆栈指针,在任何一个时刻只能有一个堆栈指针起作用,也就是说任何一个时刻只能使用一个堆栈指针,要么使用MSP,要么使用PSP。何为堆栈指针,其实就是普通的指针,只是他们指向两个不同的堆栈。
MSP:主堆栈指针
,当程序复位后(开始运行后),一直到第一次任务切换完成前,使用的都是MSP,即:main函数运行时用的是MSP,运行OSStartHighRdy,运行PendSV程序,用的都是MSP。当main函数开始运行前,启动文件会给这个函数分配一个堆栈空间,像ucos给任务分配堆栈空间一样,用于保存main函数运行过程中变量的保存。此时MSP就指向了该堆栈的首地址。
PSP:进程堆栈指针
,切换任务之后PendSV服务程序中有ORR LR, LR, #0x04这句,意思就是PendSV中断返回后使用的PSP指针,此时PSP已经指向了所运行任务的堆栈,所以返回后就可以就接着该任务继续运行下去了。
由于任何一个时刻都只能使用一个堆栈指针(SP),所以,如果在某一个时刻,需要读取或者改变另外一个堆栈指针的内容就得使用特定的指令:MSR和MRS
lr就是连接寄存器(Link Register, LR)
,在ARM体系结构中LR的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。
PC(R15)
是当前地址,把LR给PC就是从子程序返回
源码:
https://github.com/0Hellc0/Elmer-MayDayOS
设计思路:
三个任务设计成 开led 左,开led 右,全关.
执行流程
- 初始化 TCB[3] 。
TCB-taskaddr = 0
;TCB-status
,TCB-stackP = 0
;
相关的几个全局变量 NowTaskNum = 0
创建空转任务,cur
和next TCB
都是空转,cur TCB = idle, next TCB =idle
- 创建任务,其实就是把任务放到TCB中, task1{},task2{},task3{},,空任务
task1stack[20]
,
TCB[0]-taskaddr = task1
;
TCB[0]-stackP = task1stack
;
对任务堆栈
初始化
,entry point = task
地址
xPSR
R0
任务函数参数的所在地址
暂时为
0
其他随机值
- System init
- Hardware init
- OSStart
TCB
里面指向的都是空转任务,开始空转任务
当前执行在 PC
是OSStart
这个函数,
- 第一次 进入pendsv中断,进行切换到 task1。PendSV中断处理:
- 进入临界区
- 判断 NowTaskNum +1 是否正确
- curTCB = TCB[ NowTaskNum +1];
- 把curTCB 里面的堆栈值取出来,加载到 R4~R11寄存器,最后加载pc
- PSP = R0
- CPU会自动从PSP保存和加载8个量至R0~R3,R12,LR,程序入口(这个是理解的关键)和xPSR,我们无需动手
- 退出临界区
- 开始执行 curTCB 指向的任务地址。
- 正常的进入PendSV中断
- 进入临界区
- 保存现在的task 相关寄存器
- R4-R11保存在当前TCB 指向的栈顶
- 保存完毕,切换到下个task,同上
PendSV是什么?
根据 权威指南。为系统设备而设的“可悬挂请求”(pendable request)。
1.上下文切换 不能在中断中进行,会导致中断延期。为了解决这个问题,使用 PendSV。PendSV可以挂起,也就是等到别的 ISR结束后 缓期执行。
2.所以 PendSV是一个最低优先级的异常。
Cortex-M3内核有两个堆栈指针
:MSP-主堆栈指针和PSP-进程堆栈指针,在任何一个时刻只能有一个堆栈指针起作用,也就是说任何一个时刻只能使用一个堆栈指针,要么使用MSP,要么使用PSP。何为堆栈指针,其实就是普通的指针,只是他们指向两个不同的堆栈。
MSP:主堆栈指针
,当程序复位后(开始运行后),一直到第一次任务切换完成前,使用的都是MSP,即:main函数运行时用的是MSP,运行OSStartHighRdy,运行PendSV程序,用的都是MSP。当main函数开始运行前,启动文件会给这个函数分配一个堆栈空间,像ucos给任务分配堆栈空间一样,用于保存main函数运行过程中变量的保存。此时MSP就指向了该堆栈的首地址。
PSP:进程堆栈指针
,切换任务之后PendSV服务程序中有ORR LR, LR, #0x04这句,意思就是PendSV中断返回后使用的PSP指针,此时PSP已经指向了所运行任务的堆栈,所以返回后就可以就接着该任务继续运行下去了。
由于任何一个时刻都只能使用一个堆栈指针(SP),所以,如果在某一个时刻,需要读取或者改变另外一个堆栈指针的内容就得使用特定的指令:MSR和MRS
lr就是连接寄存器(Link Register, LR)
,在ARM体系结构中LR的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。
PC(R15)
是当前地址,把LR给PC就是从子程序返回