分享

cortexM3权威指南上下文切换图的问题?

 半佛肉夹馍 2023-10-20 发布于河南

If an interrupt request (IRQ) takes place before the SysTick exception, the SysTick exception might preempt the IRQ handler. In this case, the OS should not carry out the context switching. Otherwise, the IRQ handler process will be delayed (Figure 10.7). And for the Cortex-M3 and Cortex-M4 processors, by default the design does not allow return to Thread mode when there is an active interrupt service (but there is an exception e see Non-base Thread Enable description in section 23.5). If the OS attempts to return to the Thread mode with an active interrupt service running, it triggers a Usage fault exception.

文字的意思是从systick出来不能回到thread模式,但是为什么会回到thread模式呢?IRQ也是中断,只是比systick优先级低,那IRQ被抢断后,应该继续执行IRQ,而不是去执行Task B啊

所以它专门给你画了条线,表示这时候返回线程模式时会触发Usage fault啊:

注意图上的虚线箭头并不是调用关系,而是context切换关系。

意思是,sysTick优先级最高,相当于OS内核层;IRQ是用户空间驱动,优先级第二;Thread是用户程序,优先级最低。

sysTick执行一些内核操作之后、没有任务了,就会Context switching,说白了就是把Thread A的信息载入当前进程控制块、恢复Thread A的寄存器,然后让Thread A执行。

Thread A执行过程中,比如网卡来报文了,发了一个IRQ,此时会立即保存Thread A执行现场(context),切换到IRQ处理程序执行。

如果IRQ还没执行完,sysTick又来了,那么IRQ处理会被打断,保存它的context,载入OS的context,执行sysTick动作。

sysTick动作执行完,自然要保存自己的执行现场、载入其它线程/IRQ的执行现场,让它们继续执行——对于之前被打断的IRQ,这就是IRQ被sysTick延误了。

但,此时OS实现可能存在错误,比如它没去检查还有个IRQ存在,而是直接从一堆context里面随机抓了一个,比如载入Thread B的context,让Thread B执行——那么这时候CPU就会自动识别,并给出一个Usage Fault异常。

注意是Usage Fault,不是use fault。使用方法错误,意思是你的OS实现错了,你不能抛开未完成的IRQ,先去执行Thread(无论是Thread A还是Thread B都不可以)。

再后面你可以理解为alter线,也就是“如果没有切换Thread B这个错误动作应该执行的逻辑”——载入OS context,执行,然后返回IRQ;IRQ处理完,返回Thread A。

这也是一种惯用画法。归根结底是因为计算机里面状态切换太多太频繁,全都画出来需要太多太多图片;所以很多人习惯把每个可能都画在同一幅图上,你自己判断正误、然后只顺着其中一条线看到头——千万不要认为图中画的所有阶段都会发生。

事实上,这副图也没画“如果没有IRQ,直接Thread->sysTick会怎样”,但你自己推测一下很容易就能明白。

或者,说的更明白些:当你看CPU手册时,它给你的“预设身份”并不是普通的应用程序程序员,而是包括操作系统编写者在内的、偏底层的程序员。

当它说OS如何如何时,你千万别觉得“与我无关”——恰恰相反,这段的意思其实就是,如果你是这颗CPU的操作系统编写者,那么你要注意了,千万别在你写的OS中断了一个IRQ的执行时、不是返回这个IRQ让它执行完、而是调度了另一个Thread:你这样写是错误的,CPU默认会给你发一个Usage fault exception。

否则的话,因为这个中断服务程序已经响应了中断,因此不会再因为中断自动返回执行,这是非常危险的,因为被你调度的下一个Thread会执行到时间片结束、然后你的sysTick会调度下一个Thread,使得这个中断服务程序被严重延误,延误时间无法预料(或许下一个中断发生后,这里才会被当做中断嵌套这种情况而得到执行)。哪怕你安排逻辑把中断当thread调度,这也是不允许的,因为thread时间片太长、造成的延误太大时间太无法预料了。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多