割り込み処理ルーチンから別の割り込み処理ルーチンを呼ぶ

ちょっと長くなりますが、悩んでいますので、ご存じの方がおられたらよろしくお願いします。
内容ですが、以下のようなことです。

ある割り込み処理ルーチンAから、別の割り込み処理ルーチンBを呼ぶようなコードが書かれていました。
おそらくこのようなコードでは、PSWが破壊されると思いますが、割り込みがかかったメイン処理ルーチンmainに
なぜに影響があるのかが理解できません。でも、実際に、AからBを呼ばないようにすると、安定して動作するのです。
以下はその現象のサンプルです。


#pragma interrupt A_interrupt(vect=XX1)
#pragma interrupt B_interrupt(vect=XX2)

static void A_interrupt(void)
{
      B_interrupt();
}

static void B_Interrupt(void)
{
    // 処理
    // ..
}

static unsigned char ip=0;
static unsigned char op=0;

void main()
{
   while(1){
      if( ip != op ) {
         sub_func();
      }
   }
}

条件は以下となります。
Aの割り込みは頻繁にかかります。
Bの割り込みは決してかかりません。

上記処理では、ip,opが変化がないとすると、main()では
決してsub_func()は呼ばれないはずですが、Aの割り込みがかかると
なぜかsub_func()が呼ばれるようになります。
そして、Aの割り込み処理からBの割り込み処理を呼ばないようにすると
sub_func()は呼ばれないようになります。

動作の推察:
1.Aの割り込みでは、スタックに PSW(1バイト)、PC(3バイト)が保存されます。
2.AからBを呼ぶと、スタックに、0値(1バイト)、PC(3バイト)が保存されます。
3.B処理から戻るときRETIが実行され、PSWには0が取り込まれて、コールした時とは異なる値でPSWが破壊されます。
4.Aの処理終わりで、再びRETIが実行され、スタック上に保存されたPSWが復帰されます。

以上の状態となると、main()でおかしな動作にはならないと思われるのです。
ちゃんと、Aの割り込みの終わりで、PSWが戻っているので。
でも、実際にはPSWが破壊されて、おかしな動作になっていると思われるのです。

どうして、上記のような処理でおかしくなるのか、どなたかご存じでしょうか。

実を言えば、Aから割り込み処理Bを呼んだ事が不具合の原因だと思われ、呼ばないようにすると改善することはテストで確認しました。

しかし、CPUの動作仕様からすると、不具合も起こらないはずにしか思えません。
これでは、本当に不具合が修正できているのかわからないのです。

Top Replies

  • > 割り込み指定のルーチンを割り込み処理からコールすることが問題と通常認識されているかというと、
    > 高級言語(CとかC++)で開発している人たちからすると問題だと認識するのは難しいように思われますし。
    難しいかもしれないけど、知っておかなくてはならないことだと思います。
    (メモリマッピングされたレジスタと本物のメモリセルの挙動が違うとかも同様)

    割り込みハンドラはマイコンが直接呼び出すのでスタックフレームもないし、割り込みの仕様もデバイス特有のもので
    普通のC言語の関数と姿は似ていても実現方法からして別物です。

    そもそも共通の処理なら別の関数を作って両方の割り込みハンドラから呼び出すべきで、
    たまたま動くからと言って変な書き方を追求するのは実用的な意義がないと思います。
    頭の体操としてはとても面白いテーマではありますが。

  • チョコです。

    >前提として、最初のメッセージに書かせていただいているように、

    最初のメッセージの内容は頭から抜けてしまってました。

    >マニュアルに書かれていてもそれを信じないで調べる必要が出てくるので、問題が発生した時の工数が多くなり、非常に困ったことになります。

    おそらく、基本的なところはきちんとチェックされているかと思いますが、今回のような特定の条件で発生する問題に関係する内容に対しては、難しいかもしれませんね。一応、今回の誤記の問題も、Renesasの関係者には申し入れを行っているので、改善されていくと期待しています。

    以上

  • mus.さま

     話の流れが、SP-1に00Hが書き込まれない事が悪いという様に感じましたので、(SP-1に00Hを書かないという仕様で設計した)RL78の設計者は悪くない。問題の本質はCALL-RETIの組み合わせが悪い、という気持ちになりました。

    #設計を長年やっていると、「設計は悪くない、使い方が間違っている!」と言いたくなる気持ちもありまして…

    #もちろん、誤った情報が書かれているマニュアルは悪です

  • ほやさん


    あくまで私の個人的な意見:
    「書かれていました」・・・この一文から不具合解析関係で調査していると私は推測。「こう書くべき」ってのは分かっててなおの質問だと推測。これだけ突っ込んで調べているとなると資料を見てOKだと思ったけど違ったという部分を報告書に書かないといけないというのなら動機として腑に落ちるんです。実際そうかは不明ですが。本人のみぞ知る。

  • 今回はいろいろとご相談にのっていただき感謝しております。
    割り込み処理ルーチンを、サブルーチンコールしてしまうという大きなミスがあったので、修正したのですが、なぜそのことが不具合の出る理由(メカニズム)であったかがわからないと、本当に不具合は治ったとの確信が持てません。たたまたまここではないかと修正したら症状が出なくなったというだけでは、不十分なことはここに集いの皆様ならお分かりと思います。また、単に割り込み処理ルーチンをサブルーチンコールするようなコードが良くないのだというよりも、RL78においてはこのような原因なんだとわかったほうが、より理解が深まることと思いますし、経験値が上がるものと思います。


    実はRXシリーズでこれまた摩訶不思議な(私にとっては)不具合が発生しましたので相談をさせていただければと思います。RXのForumでよろしくお願いいたします。