关于rtos中任务切换时的程序流程

今天和一个小伙伴讨论了一下基于cortex-m3内核的RTOS在任务切换时的程序流程,小伙伴说国内某搜索引擎都搜不到这类的信息,所以我才打算写下来,硬件平台是stm32f1​。

这里的切换有两种情况:

第一种:从main函数跳到任务一时的程序流程;

第二种:从任务一跳到任务二时的程序流程。

先说第一种:从stm32f1上电复位说起吧,上电复位之后,cpu执行以下代码:

Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

可见代码先去执行SystemInit()这个函数,执行结束之后去执行main()函数。我为什么要说这个呢,因为在《cortex-m3权威指南》里面有这样一句:“主堆栈指针( MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包括中断服务例程)

也就是说当cpu复位之后执行的SystemInit()和main()函数时用的都是MSP。我为什么要提MSP,因为下面还有个PSP。

继续说main()函数,执行main()函数的时候,肯定会执行一大堆初始化(这里就不多赘述初始化了些啥),然后去找优先级最高的任务,并把这个找到的任务赋给nextTask变量,这时会启动任务调度——也就是说触发PendSV异常。注意到这里用的都是MSP

这里插一句任务切换的本质:“保存上一个任务的运行状态,恢复下个任务任务的运行状态”

触发PendSV异常必然会去执行PendSV_Handler()异常处理函数,在这个函数里执行的就是上面这句红字,但是从main函数到任务一的时候,是没有上一个任务的,所以不需要保存上一个任务,直接恢复下一个任务就行。恢复下一个任务就是把下一个任务的运行状态(这时的运行状态是该任务初始化完成的状态)通过弹栈弹到CPU的寄存器里面然后占据CPU的控制权运行该任务,这时就不用MSP了(因为有专门给任务跑的栈),通过下面这句代码 ORR LR, LR, #0x04  切换到PSP堆栈,就是下图的第二位置1,这个PSP是啥呢,同样在《cortex-m3权威指南》里面有这句解释,进程堆栈指针( PSP):由用户的应用程序代码使用。这个PSP就是专门给任务用的栈,这个时候任务就在PSP上运行了。

这时就是任务一占据CPU的控制权在运行!

再来说第二种:当任务一占据了CPU的使用权在运行时,PendSV异常触发需要切换到任务二。这时CPU会通过压栈的方式把当前任务一的运行状态(就是任务一占据cpu控制权时寄存器的值)压入只属于任务一的独立栈中,这就是保存上一个任务的运行状态;然后恢复下一个任务,任务二的运行状态就是一开始在main()函数中初始化的状态,cpu通过弹栈的方式这些保存在任务二独立栈中的运行状态数据  弹入CPU的寄存器,让任务二占据CPU的控制权并运行。

当然了,在这里多说一句,触发PendSV异常时执行的PendSV_Handler()函数时在MSP上运行的,任务一与任务二运行时是在PSP上面的。

猜你喜欢

转载自www.cnblogs.com/sanshijvshi/p/11773284.html