20 |
6809の割込み動作 (5) |
割込み禁止のCCRへの反映を遅延させるタイミングを作り出しました。全レジスタの退避が終わった後のベクタフェッチは前々稿によれば、SEQ_MEM_READ_Hステートですが、そのタイミングでレジスタにCCR書き込みを指示することを考えます。このステートにはexceptionでない場合というif文がありますが、注目する場合はexception中なので、ちょうどelseの部分に以下の文を記述します。
if (k_set_i) begin
k_set_i_timing <= 1;
k_set_i <= 0;
end
k_set_i_timingとして、k_set_iを遅延させたCCR反映タイミング信号を作り出し、これをレジスタに与えます。なお、このk_set_iはSEQ_IRQステートに入った時点でセットし、一方、RTI命令でk_clear_iをセットします。
これにより正しく割込みが入り、割り込みが禁止されたかと思ったのですが、RTIから戻るところで再度割込みが入る現象が起きました。解析すると、割込みハンドラで割込み原因をクリアしたにも関わらず、CPU内部で割込みをまだ保持していることが原因と判りました。そのため、RTI実行により割り込み許可された途端にまた割り込み処理に移行してしまいます。そこで以下のように、割込み要因を無視するタイミングゲート処理を入れたところ、正しく動作するようになりました。
(修正前)
if (!k_reg_irq[2])
k_reg_irq <= { k_reg_irq[1:0], (!cpu_irq_n)};
(修正後) if (!k_reg_irq[2])
k_reg_irq <= { k_reg_irq[1:0], (!cpu_irq_n & !k_set_i & !k_set_i_timing)};
このタイマ割込みによるハンドラの実行と復帰は、タイマの周期で正しく繰り返されます。割り込みハンドラでは正しく割り込みが禁止され、RTIにより割り込み許可として元のプログラムに戻ります。元のプログラムではタイマ割り込み待ち状態となり、タイマ割り込みが入ると再びスタックへのレジスタ退避やベクタフェッチ等の割り込み処理を行います。