微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > uC/OS II的任务切换机理及中断调度优化

uC/OS II的任务切换机理及中断调度优化

时间:12-01 来源:互联网 点击:

我们把这个函数称作任务调度的前导函数。它先判断要进行任务切换的条件,如果条件允许进行任务调度,则调用OSCtxSw()。这个函数是真正实现任务调度的函数。由于期间要对堆栈进行操作,所以OSCtxSw()一般用汇编语言写成。它将正在运行的任务的CPU的SR寄存器推入堆栈,然后把 R4~R15压栈。接着把当前的SP保存在TCB->OSTCBStkPtr中,缓蟀炎罡哂畔燃兜腡CB->

2)在中断的处理过程中,有别的中断产生,产生中断嵌套。
  如图5所示,由于在处理中断的时候,SP已经被移到系统堆栈去了,只有当中断退出的时候才可能把SP移到别的任务的任务堆栈中。所以在中断的时候进行中断嵌套,那么对于中断的处理和第一次是一样的,所不同的是,这次保存在堆栈中的不是任务运行中的寄存器,而是中断处理中的寄存器,而且是保存在系统堆栈中而不是任务堆栈中。从这里就可以看出优化内存的效果。所有的中断嵌套中的寄存器压栈都压在系统堆栈中,这样对于任务堆栈内存大小的要求大大降低。


  因为uC/OS II在进入中断中,会把全局变量OSIntNesting++;在退出中断的时候,又会把OSIntNesting--。在退出中断进行任务切换之前,uC/OS II会先判断OSIntNesting是否为0,是0才会进行任务调度。当第二中断运行结束以后,退出中断嵌套的时候, OSIntNesting不为0,也就不会进行任务调度。因此,仍旧在系统堆栈出栈,那么系统会继续前面没有完成的中断服务程序。

接着退出中断的顺序和非中断嵌套的顺序是一样的。在中断处理完以后,SP会自动回到图4中③的SP位置。接着,系统会查询到优先级最高的任务,然后把SP的指针移到优先级最高的任务的任务堆栈。进行R15~R4的出栈工作,最后用RETI中断返回指令返回到新的任务。

中断的情况基本上就是上述两种。对于有些文献中提到的在中断中会调度到更高优先级的任务的情况,笔者觉得是不应该发生的。因为从上面的分析可以看出,默认的(uC/OS II的设计思路)中断处理会同时对全局变量OSIntNesting进行增减处理,

以给出是否需要任务调度的条件。那么即使在中断服务程序中把更高优先级的任务就绪,也会等到中断退出以后再进行调度,除非是在中断中直接调用更高优先级的任务函数。但这种方法应该是和uC/OS II的原则相违背的,沿用的是以前前后台设计的思路。

对于这样的设计方式,时钟节拍的处理方式必须和一般的中断处理方式是一样的。一般来说,MSP430使用WATCHDOG时钟中断作为时钟节拍的产生源。从本质上来说,时钟节拍本身也是中断处理过程,所以对于时钟节拍的处理应该和其它的中断处理过程相同。实际上,在时钟节拍的处理过程中也可能会存在中断嵌套的问题。

中断堆栈和任务堆栈分离设计的程序流程如图6所示。

4 几点建议

  1. 编写中断程序的时候,有条件尽量使用汇编语言。因为这样可以避免一些编译器自己进行的操作,减少指针调整的次数。
  2. 在用C编写中断服务的时候,因为有些功能必须调用汇编的函数才能实现。调用函数时,有些时候压栈的PC会破坏堆栈的结构。这个时候需要把堆栈进行适当的调整,保证堆栈格式的正确。
  3. 中断处理过程中调用OSIntExit()的时候,由于 uC/OS II的原始设计中SP指针有时是不调整的,所以在OSIntExit()返回了以后,还要判断一下是否中断嵌套。因为有的时候是需要切换任务的。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top