• 5
  • 11月

用51移植一个小型OS时,遇到了中断方面的一个问题。

因为,51的中断有一个特性:如果多个中断同时产生中断(或者在关闭EA时发生了多个中断),在EA打开的时后,每执行一个中断,必须执行主程序的一条指令,才能进入下一个中断。据说这个主要是为了实现51的单步调试功能而设计的。我不知道是不是所有的51的特性都是这样,或者其它体系的芯片会不会这样。

这样会有什么问题呢?

在OS任务切换过程,我们会遇到以下形势的代码:

EA = 0;  //进入临界区1<br />
任务1由就绪转入等待;<br />
任务1加入等待队列;<br />
产生任务切换软中断;<br />
EA = 1;  //退出临界区1<br />
(这里将进入软中断,发生任务切换事件)<br />
EA = 0;  //进入临界区2<br />
等待队列中删除任务1;<br />
EA = 1;  //退出临界区2


我们的原意是要在退出临界区1的时候进行任务切换。然而,在临界区1的时候,有可能已经产生了其它中断,而任务切换软中断的自然优先级最低,这时候,由于中断的特性,执行完其它中断任务后,会关闭EA!!

于是,没有在我们预想的地方进行任务切换。真正的切换是等到退出临界区2后!!

接下来问题就大了:由于等待队列中已经删除了任务1,那么任务1将永远无法被唤醒了。任务1就成了一个死任务。

那么,有什么解决办法呢?

1、如果可以更改芯片设计,则改为中断后不执行任何主程序的执令。
2、提高切换任务的优先级至最高。
3、不使用软中断,而是采用直接调用函数的方法进行任务切换。
4、在临界区1与临界区2之间的区域加入足够多的NOP指令。


以上几种方法均能解决。至于详细方法,这里就不多说了。