ちょっと長くなりますが、悩んでいますので、ご存じの方がおられたらよろしくお願いします。内容ですが、以下のようなことです。
ある割り込み処理ルーチン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の動作仕様からすると、不具合も起こらないはずにしか思えません。これでは、本当に不具合が修正できているのかわからないのです。
割り込みハンドラ(割り込みベクタ)からの復帰と通常の関数(サブルーチン)からの復帰はCPU内部で動作が違うのでコンパイルされた関数からの戻りとして使われる機械語が違います。RL78ならRETIとRETがあり、割り込みハンドラではRETIが戻りとして使われるので割り込みハンドラを直接関数のように呼び出すと異常な状態になります。もし、ある割り込みハンドラの内部処理を他の割り込みや通常の処理から呼び出したいならその処理を関数として作り直して呼び出すようにすれば解決します…
チョコです。
>それに、この機能は未初期化のメモリアクセスをチェックするものではなくて、RAMのハード的なビット化けのチェックらしいので、今回の件には当てはまらないでしょう。
RL78/F13のハードウェア マニュアルをECCで検索してみたのですが、DTCの所に以下のような記述がありました。ECCは通常は、データ領域に対して使うものですが、どこにもアドレスの記述はありません。DTCでの読み出しで割り込みが発生するなら…
ちょっと気になったので、実際にどの様に動くかやってみました。
簡単な割り込み関数を定義して動作を見る限り、mus.さんの仰っている通り、メイン関数に戻るところでスタックに書かれている値をPSWに戻すので、メイン関数の動作がおかしくなるという現象は見られませんでした。
そこで、どのようなケースでおかしくなるか。意図的に動作がおかしくなるなケースを作ってみました。
#pragma interrupt…
> 割り込み指定のルーチンを割り込み処理からコールすることが問題と通常認識されているかというと、> 高級言語(CとかC++)で開発している人たちからすると問題だと認識するのは難しいように思われますし。難しいかもしれないけど、知っておかなくてはならないことだと思います。(メモリマッピングされたレジスタと本物のメモリセルの挙動が違うとかも同様)割り込みハンドラはマイコンが直接呼び出すのでスタックフレームもないし、割り込みの仕様もデバイス特有のもので普通のC言語の関数と姿は似ていても実現方法からして別物です。そもそも共通の処理なら別の関数を作って両方の割り込みハンドラから呼び出すべきで、たまたま動くからと言って変な書き方を追求するのは実用的な意義がないと思います。頭の体操としてはとても面白いテーマではありますが。
ほやさん
あくまで私の個人的な意見:「書かれていました」・・・この一文から不具合解析関係で調査していると私は推測。「こう書くべき」ってのは分かっててなおの質問だと推測。これだけ突っ込んで調べているとなると資料を見てOKだと思ったけど違ったという部分を報告書に書かないといけないというのなら動機として腑に落ちるんです。実際そうかは不明ですが。本人のみぞ知る。
今回はいろいろとご相談にのっていただき感謝しております。割り込み処理ルーチンを、サブルーチンコールしてしまうという大きなミスがあったので、修正したのですが、なぜそのことが不具合の出る理由(メカニズム)であったかがわからないと、本当に不具合は治ったとの確信が持てません。たたまたまここではないかと修正したら症状が出なくなったというだけでは、不十分なことはここに集いの皆様ならお分かりと思います。また、単に割り込み処理ルーチンをサブルーチンコールするようなコードが良くないのだというよりも、RL78においてはこのような原因なんだとわかったほうが、より理解が深まることと思いますし、経験値が上がるものと思います。
実はRXシリーズでこれまた摩訶不思議な(私にとっては)不具合が発生しましたので相談をさせていただければと思います。RXのForumでよろしくお願いいたします。