RTOS内功修炼记(十) | 深度解析RTOS内核上下文切换机制

一、风平浪静的程序世界

芯片上电的那一刻,犹如小船撑起了帆,开始远航。

这艘小船上,PC寄存器负责航行路线,按照路线图(可执行固件)告诉船长(CPU)接下来该往走哪个方向,船长在走的时候,还要依赖R0-R12这些通用寄存器来完成一些基本的计算。

这一路上,还会遇到很多的港口,船长有点不太安分想进港玩玩,但这个时候PC指针不干了:

“船长,我自己只能无脑的向前冲,现在我们要偏离路线进港的话,有可能会回不来了”!

船长一听,这问题不大啊,喊过来LR寄存器:

“你记一下现在的位置,我们待会进港玩完了要回来这里,一船人的性命就交给你了,你可得记好呀!”

LR寄存器把地址记在了自己的身上,大家开心的进港玩耍。

灯红酒绿的港口里,这个小国家有着自己的货币,但是这些货币离开港口之后就没什么用了,机智的船长想到了一个好主意。

他叫过来了SP指针:“听说你很能装是吧?”

SP指针小声bb:“也不是很能装,装多了会炸。”

船长:“交给你一个任务,我们现在去兑点这个国家的货币,先存到你这里,无论怎么用,在我们离开这个地方的时候,记得都给清空了~”

船上的人因为有了SP指针,所以不停的花钱存钱,在这个小港口玩的很开心。

在离开的时候,SP指针清空了所有属于这个港口的东西,它们只属于这里,能带走的也许仅仅只有美好的回忆吧。

接着LR寄存器告诉PC指针当初那个偏离航线的地址,外面的世界再精彩,他们不会忘记当初为什么要出发。

PC指针回到了离开航线的那个地方,开始继续无脑的继续向前冲。

船上的人各司其职,井井有序,一只小船平稳的向前航行,风平浪静。

二、风暴来临

远航的路上总要经历点风浪。

这天突然风暴来临(发生了中断),小船上的人们都开始切换到战斗模式,准备应对。

CPU当机离断:“赶紧先保存当前现场,不要被毁了!”

R0、R1、R2、R3、R12寄存器首当其冲,先将自己的值存到了SP那里。

接着是LR寄存器和PC指针,也将自己的值存到了SP那里。

最后是程序状态寄存器xPSR,也将自己的值存了进去。


这下好了,工作现场都被保存起来,大家都可以放心的去应对风暴(执行中断服务函数),只要不被风暴干翻,风暴过后还可以继续航行。

中断服务函数执行完毕后,风暴总算应对过去了,小船又可以远航了。

xPSR从SP那里要到了之前保存的值,重新加载进来。

LR和PC寄存器也从SP那里要到了之前保存的值,重新加载进来。

R12、R3、R2、R1、R0也分别拿到了之前的值,重新加载进来。

大家又回到了风暴来临前的状态,开始干活,一切安静的像没有发生过一样。

三、有人叛变了

RTOS内核大哥有一天上了船,这玩意坏的很。

风暴过后大家都去SP那里找之前的工作现场,他看准了这个点,想要拉SP指针下水。

“大兄弟,你说你担任着这么重要的角色,他们总是在需要的时候才想起你,那个鬼船长还说你是不是很能装,你今天遇到我,就是千里马遇到了伯乐,要不要跟我一起大干一把,做大做强,再创辉煌!”

SP指针看了一眼:“快滚”。

这可被PSP指针看在了眼里,他找到内核大哥:“大哥你不知道,SP其实有两个,你刚找的那是我哥MSP,我是PSP,我才是那匹千里马!平常都是他在干活,大家都不知道,这次我一定要跟着大哥你干票大的!”

内核大哥一看:“卧槽,小兄弟你可真是太委屈了,就你了,干它!”

接下来,他们开始谋划干起了一件大事。

万事具备,只欠东风。干大事讲究天时地利人和,天时怎么找呢?

RTOS内核大哥盯上了PendSV中断,他发现这个风暴可以手动触发,犹如信号枪一样。

妙啊,他掌握了触发这个风暴的方法后,现在就只剩一步没有谋划,人们处理这个风暴的时候,都是有对应的处理方法的,他得想办法把这个处理方法给改了。

于是他和PSP开始联合,改起了PendSV风暴的预定处理办法。

“风暴来临的时候,我们得先把中断关了,免得让别人影响我们的计划。”

CPSID   I

“PSP,船长已经叫他们把工作现场都存到你那里了,为了不露出破绽,我得把你的值也存起来,先放到R0吧,接着做事!”

MRS     R0, PSP

“PSP,除了他们之前存的那些数据,你也得把R4-R11寄存器的值存进去,我内核这个人做事讲究稳妥。”

“好的,大哥。”

STMFD   R0!, {
    
    R4 - R11}

“好了,都存完了,PSP,是时候找地方存他们之前用过的sp指针地址了,不然就暴露了,存到任务控制块的sp成员吧!”

OV32   R5, k_curr_task
LDR     R6, [R5]
STR     R0, [R6]

“该保存的都存完了,他们不会发现我们了!PSP,现在我们要开始干我们的大事了,看我给你表演什么叫偷梁换柱。”

RTOS内核大哥:“我去拿新任务的控制块”。

; k_curr_task = k_next_task
MOV32   R1, k_next_task
LDR     R2, [R1]
STR     R2, [R5]

RTOS内核大哥从新任务的控制块成员中拿出sp成员的值,放到R0寄存器开始操作,准备取数据:

LDR     R0, [R2]

取出值恢复到R4-R11寄存器中:

LDMFD   R0!, {
    
    R4 - R11}

此时的值,就是RTOS内核还未动手之前,船长带领众人存完现场的SP指针地址,将它恢复到PSP指针中:

 MSR     PSP, R0

干完大事,RTOS内核偷梁换柱成功,此时的PSP指针,指向的早已不是之前的值,已经是新任务的任务栈地址了。

开中断,收工:

CPSIE   I

跳转到LR寄存器保存的返回地址,PendSV中断处理函数完成,一场风暴又过去了。

船长号召大家来SP指针这里拿值,恢复工作现场,却不知PSP早已叛变,指向了别的地方。

xPSR从SP那里领走了它的值。

LR和PC寄存器也从SP那里领走了它的值。

R12、R3、R2、R1、R0也分别领走了他们的值。

大家又回到了风暴来临前的状态,开始干活,一切安静的像没有发生过一样。

唉,看似一切回到了风平浪静的状态,殊不知,只要RTOS内核触发PendSV中断 ,风暴过后,整条船的方向都会变,连船长也不知道会变到哪里,只有RTOS内核知道。

一条风平浪静的小船,船长带领着大家努力的向着远方航行,但是他们永远不会判断方向,船长也不会。

RTOS内核成了这条船上,真正的主宰。

猜你喜欢

转载自blog.csdn.net/Mculover666/article/details/124354080