uCOS-Ⅲ中PendSV任务切换详细分析(运行模式切换会自动加载的内容)

当调用OSStartHighRdy()函数,会触发PendSV异常后,就需要编写PendSV异常(可以手动触发,也叫软中断)服务函数,然后在里面进行任务的切换。

         PendSV异常服务中主要完成两个工作,一是保存上文,即保存当前正在运行的任务的环境参数;二是切换下文,即把下一个需要运行的任务的环境参数从任务栈中加载到CPU寄存器,从而实现任务的切换。

         PendSV异常服务中用到了OSTCBCurPtr和OSTCBHighRdyPtr这两个全局变量,这两个全局变量在os.h中被定义。

         PendSV异常服务函数名称必须与启动文件里面的向量表中的PendSV的向量名一致,如果不一致则内核是响应不了用户编写的PendSV异常服务函数的,只响应启动文件里面默认的PendSV异常服务函数,启动文件里面为每个异常都编写好默认的异常服务函数,函数体都是一个死循环,当你发现代码跳转到这些启动文件里面默认的异常服务的函数,就要检查下异常函数名称是否写错了,没有跟向量表里面的一致。

        在进入PendSV异常服务函数时,首先是关闭中断(NMI与HardFault除外),防止上下文切换时被中断,当然,在上下文切换完毕之后,会重新打开中断。

        将PSP的值加载到R0寄存器中,判断R0的值,如果为0则跳转到OS_CPU_PendSVHandler_nosave。进行第一次任务切换的时候,PSP在OSStartHighRdy初始化为0,所以此时R0肯定为0。

当执行过一次任务切换之后,则顺序执行到切换下文,

首先加载OSTCBCurPtr指针的地址到R0,

加载OSTCBHighRdyPtr指针的地址到R1,

加载OSTCBHighRdyPtr指针到R2,

存储OSTCBHighRdyPtr到OSTCBCurPtr,实现下一个要运行的任务的TCB存储到OSTCBCurPtr。

加载OSTCBHighRdyPtr指针的地址到R0,而TCB中第一个成员是栈指针StkPtr,所以此时R0=StkPtr。

将任务栈中需要手动加载的内容加载到CPU寄存器R4-R11,同时递增R0,让R0指向空闲栈的栈顶。此时栈的空间分布情况如下图:

当把需要手动加载到CPU的栈内容加载完毕之后,栈的空间分布情况如下图:(注意这个时候StkPtr不变,变的是R0)

更新PSP的值,而且PSP与上图中R0的指向是一致的,设置LR寄存器的位2为1,确保异常退出时使用的堆栈指针是PSP,然后打开中断。

异常返回(此时会发生CPU运行模式切换),这个时候任务堆栈中剩下的内容将会自动加载到xPSR,PC,R14,R1,R3,R0,R2这些寄存器中,这个和cortex-a内核运行模式切换自动加载内容不一样(可以看这篇文章arm cortex-a的运行模式切换自动完成哪些事情),同时PSP的值也将更新,即指向任务堆栈的栈顶,这样就切换到了新的任务,这个时候栈空间的分布如图:

手动存储CPU寄存器R4-R11的值到当前任务的堆栈。当异常发生时,进入PendSV异常服务函数的时候,当前CPU寄存器xPSR,PC,R14,R1,R3,R0,R2会自动加载到当前的任务堆栈,同时递减PSP的值,此时当前任务堆栈空间分布如图:

加载OSTCBCurPtr指针的地址到R1,

加载OSTCBCurPtr指针到R1,

存储R0的值到OSTCBCurPtr->OSTCBStkPtr,这个时候R0存的是任务空闲栈的栈顶,此时保存上文完成,此时的堆栈空间分布如图:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值