H8/36094:IRQ0の処理が起動しないことがある

はじめまして。よろしくお願い致します。

H8/36094を以下のクロック、割込を使用して動かしているのですが、IRQ0の処理がたまに(1,000回に1回くらい)起動しないことがあります。

これは、プログラムでIRQ0の処理の入り口でP81=L、出口でP81=Hとし、オシロでIRQ0とP81を観測することで確認しております。

試しにTimerAの割込周期を約50msecにしたところ、上記の現象は100,000回に1回程度になったのでTimerAが影響しているのだろうとは思いますが、どうしてこうなるのか分かりません。

プログラム中では初期設定以外でIENR1やIビットの操作はしていません。

解決のために何をチェックすればよろしいでしょうか。ご教示いただけるとありがたいです。

 

CPUクロック

・オンチップオシレータ 10MHzで動作

IRQ0

・割込周期:約50msec、立下りエッジ検出、Lowレベル:約2msec、処理時間:50usec以下

TimerA

・割込周期:819.2usec、処理時間:50usec以下

ADC

・割込周期:50msecごと、処理時間:50usec以下

WDT

・未使用

  • TimerA の割り込み処理での割り込みフラグレジスタ1(IRR1)のクリアが適切でなくて IRQ0割り込み要求フラグも一緒にクリアしてるってことはないですか?
  • fujita nozomu 様
    早速のご回答ありがとうございます。
    TimerA割込ルーチン内での割込フラグ(IRRTA)のクリアは以下のようにしています。
    (IRRTAのみクリアしているつもり・・・)
    問題ありますでしょうか。よろしくお願い致します。

    MOV.B @IRR1,R1L
    AND.B #H'BF,R1L ;IRR1のbit6 (IRRTA)のみクリア
    MOV.B R1L,@IRR1
  • MOV.B @IRR1,R1L
    AND.B #H'BF,R1L ;IRR1のbit6 (IRRTA)のみクリア
    MOV.B R1L,@IRR1

    確率としては低いものゝ IRR1 を読み込んだ直後のタイミングで IRQ0 が発生した場合、IRR1 への書き込みで上書きリセットしてしまう危険性はあるので、1命令で

    BCLR #6,@IRR1 ;IRR1のbit6 (IRRTA)のみクリア
    

    等とされるが良いと思います(H8 は使ったことないのでこう書けるかはわからん)。

  • fujita nozomu 様
    ご指摘の通りに修正したところ、とりあえず10,000回試験して問題ありませんでした。
    既存のソフトを流用していますので、他にも似たような部分がありそうです。全て見直したほうがよさそうですね。

    こういうことにさらっと気付けるようになりたいです。
    大変助かりました。誠にありがとうございました。
  • わわいです
    割り込みは命令のと命令の間で受け付けられる、ということを意識しましょう
    あらゆる命令の間で割り込みがかかっても、動作が破綻しないように意識してコードを組む必要があります。
    んで、それが無理なとき、割り込まれると具合の悪いところを、割り込みディセーブルとします

    ここらへんの動作のシーケンスというのは単純なもんなんで、頭のなかでここで割り込みが起こればどうなるか?を考えていけばわかってくるとおもいます。

    #んで、考えなしに多重割り込みを許していると、ワケワカランよ~になるというあるあるネタとなります
  • チョコです。
    わわいさん,ちょっと違っていると思います。今回は,割り込み要求フラグのソフトでのクリアとハードでのセットの競合の問題です。これは割り込みを禁止しても変わらないのではないでしょうか。
  • 一般論としてビット操作命令であってもCPUのバス上はリード・モデファイ・ライトだと思っているのですが、H8ではビット操作命令時は割り込み要求フラグのセットを遅延させるようなメカニズムがあったりするのでしょうか、、、

    [追記]

    すみません。RL78のUMにも藤田さんの指摘と同じことが書いてありましたので、そういうメカニズムがあるのでしょうね。(今までずっと気にしていなかったのですが、なぜか今回突然気になって、少々恥をかいてしまいました。)

  • わわいです
    前にも書きましたが、割り込みというのは命令の境い目でおきます。
    ビット操作命令、ってのはおっしゃるとおりリードモディファイライトになりますが、その操作をひっくるめて一つの命令となりますんで、その途中で割り込まれる、ということはないので、この場合はビット操作命令にすることで解決することができます。

    で、注意しなければならないのは、あくまで割り込みは、CPUの命令の境い目でおきるもので、Cのソースの命令の境い目ではない、ということですね。
    IRR1&= ~0x40;
    というソースが、

    >BCLR #6,@IRR1 ;IRR1のbit6 (IRRTA)のみクリア

    という命令に展開されればいいですが、

    >MOV.B @IRR1,R1L
    >AND.B #H'BF,R1L ;IRR1のbit6 (IRRTA)のみクリア
    >MOV.B R1L,@IRR1

    という命令列に展開されると問題が出てしまうことになります
    まあ、ルネサスのコンパイラであれば、こういう心配はまずないでしょうが、割り込みを使用する場合、割り込み相互で変数を操作する場合などは、アセンブルリストを確認するほうがいいかもしれません
  • チョコです。
    その動作は,最近は殆どのデバイスで非同期の動作として対策(リード・モディファイ・ライトの処理期間中は,割り込み要求がペンディングされる等)されていると思います。
  • チョコです。
    わわいさん,割り込みの受付の部分をCPUが受け付けるタイミングと考えていませんか。
    もちろん,わわいさんが書かれていることも重要なことで,割り込みを使用時に注意が必要なことです。
    しかし,ここで問題になっているのは,その前段階のCPUへの割り込み要求を受け付ける部分です。
    この段階では,CPUの命令と命令の境目は直接は関係ありません。