Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page

RI78V4の割込みハンドラ起動時の異常挙動

CS+ for C.CにてRL78/G14をRTOSで動かしているのですが,adcの割込みハンドラ発生時に

0番地に飛んでしまうことがあります。

発生タイミングの判断理由としてトレース情報をみて「CALL   !!__kernel_int_entry」の後に

0番地に移動していることを確認しております。

 

同じプログラムでも必ず起きるわけでもなく何時間も起きなかったり,

数秒で起きたりし,なぜか一度ファイルを捨てて少し前のデータから同じ処理を

追加しなおすと起きなくなるなどなかなか再現性がない状況です。

正直状況を説明するのに何が情報として必要かすら悩んでいる状況で

恐縮ですが,何か可能性等思いつくことがあればご意見いただけると幸いです。

  • 電子妖精さん、こんにちは。NoMaYと申します。#RI78V4の使用経験は無いですが、、、

    > 発生タイミングの判断理由としてトレース情報をみて「CALL   !!__kernel_int_entry」の後に
    > 0番地に移動していることを確認しております。

    この「トレース情報」はIECUBEのトレースデータのことでしょうか?それとも、オンチップデバッグのトレースデータのことでしょうか?また、CALL !!__kernel_int_entryの少し前から、0番地に移動した後の少し後まで、のトレース情報を見せて頂くことは出来ますか?

  • In reply to NoMaY:

    NoMaYさんこんばんは
    リプありがとうございます。

    トレース情報はオンチップデバッグのトレースデータとなります。
    GW中は手元に評価基板がないため、トレース情報がだせません。

    イメージ的にはADの計算で実効値やDFTの演算をしている都合上、処理が破綻しない程度には膨大なため、トレース情報で見えるのはその演算の途中にタイマ割り込みを起動要件(タスク管理外)にしてAD変換完了後ADCの割り込みが2,3回程度見えるのが実態です。
    (ほかのタスク関連は大体待ち状態か休止状態でデジタル入力判定用のタスクが動いているくらいですが、リセットされた時のトレース上で見たことはないです。)

    最後はCMP X 0 (だったかな?)が実行されてstart.asmの先頭から再起動します。
  • In reply to 電子妖精:

    電子妖精さん、こんにちは。NoMaYです。

    今までは「0番地に移動」であれば中身が0の関数ポインタで0番地をコールしてしまったとかかな?と思っていたのですが、それが「start.asmの先頭から再起動」ということなら、リセットが発生したということですかね。ならば、RAMパリティエラーか不正メモリアクセスのリセットでしょうか、、、

    トレースデータはGW明けを待とうと思いますが、トレースデータを見ていない状態で考えを巡らせると、トレースデータの最後の分岐元アドレスから関数を特定して、その関数内でポインタ経由でアクセスしている箇所すべてにポインタ値チェック処理を入れ、ポインタ値の異常を検出したらブレークするようにしてみることかな?と思うのですが、頂いたトレース情報のイメージの説明を読むと、なにかややこしい話もありそうかな?という気もします、、、 ここは一度トレースデータを見たいですね。

  • In reply to NoMaY:

    NoMaYさんこんばんは

    お待たせしておりましたトレースデータを回収しました。
    テキストデータをそのまま貼ると長いのでupローダーに上げましたのでそちらをご覧ください。
    (相変わらず同じソースで発生したりしなかったりでなかなか厄介です。)

    dotup.org/.../dotup.org1840739.txt.html

    password:cafe
  • 電子妖精さん、こんにちは。NoMaYです。

    トレースデータをどうも有難う御座いました。終わりが以下のようになっていますね。(見易くなるように少し加工しました。) 私は以下のようなことではないかと推測しました。

    トレース回路ハードウェアに関する推測:

    正直な感想を言うと、赤文字箇所のデータはオンチップデバッグ回路の誤動作のような気がします。本来は、ここに__kernel_int_entryの最初の分岐命令のアドレスが入るのではないかと予想します。しかし、そのアドレスが正しくトレースメモリ(確かRL78/G14は内蔵RAMの一部をトレースメモリとして使うようになっていたのではないでしょうか)へ書き込み完了する前に、(可能性としては)RAMパリティエラーか不正メモリアクセスのリセットが発生してしまってトレース回路が誤動作し、0x00000という不正データが書かれたのではないだろうかと予想します。

    デバッガソフトウェアに関する推測:

    CMP0 Xというのは命令コードとしては 0xD0 であり、おそらく 0番地,1番地 に書かれているリセットベクタ 0xD0,0x00 の1バイト目のような気がします。(なお、アドレス0x000D0はデバッグモニタの内部ですね。) そして、デバッガはトレースメモリから読み出したトレースデータ(=分岐元アドレス)が0x00000だったので、アドレス0x00000の命令により分岐したものだと誤認識して、アドレス0x00000のCMP0 X(=0xD0)を表示したのだろうと予想します。

    今後のデバッグ作業案:

    (1) RAMパリティエラーか不正メモリアクセスのリセットが発生していないかリセット要因レジスタのRESFを確認 → たぶん発生していると思うのですが、、、

    (2) __kernel_int_entryの逆アセンブルコードを調べて、1つ目の分岐~2つ目の分岐の区間で、[HL]や[DE]などによるリードライトを行っている命令がないかどうか確認

    (3) もしあれば、ソースコードを調べて、そもそも何をアクセスしようとしていたのか把握して、範囲チェックコードを埋め込んで、範囲外であればデバッガがブレークするように仕込む

    (4) もしなかったら、また考えを巡らせてみる、、、(その前に、ルネサスさんに、このような事例ではトレースデータが不正(なのではないかと私は感じているのですが)になるトレースエントリの数は何個までか(1エントリだけなのか、2エントリ以上あり得るのか、など)を尋ねた方が良いかも知れません。)

    トレースデータの終わりの箇所:

    番号   時間   行番号/アドレス     ソース/逆アセンブル                                       
    --------------------------------------------------------------------------------------------

    ...略...

                                      __COM_llmul:                                              
    222           0x00ade             +49         CALL  !!__REL_llmul_addh                      

                                      __REL_llmul_addh:                                         
    223           0x00ae9             +4          MOVW  AX,[HL+4H]                              

                                      _r_adc_interrupt:                                         
    224           r_cg_AD_task.c#73   void __near r_adc_interrupt(void)                         
    224           0x00454             +4          CALL  !!__kernel_int_entry                    

    225           0x00000                         CMP0  X

    RAMパリティエラーか不正メモリアクセスのリセットが発生?

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    トレースされないようになっているのだと思いますが、このあたりはデバッグモニタが実行されていると思います
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                                      _start:                                                   
    256           start.asm#62        MOVW SP,#LOWW(__STACK_ADDR_START)                         
    256           0x003ec             +0          MOVW  SP,#0FE20H                              
                                      ソフトウエア・ブレークにより停止しました。               

     

  • In reply to NoMaY:

    NoMaYさんこんにちは

    とりあえず(1)について実施したところ不正メモリアクセスのリセットが発生していました。
    (2)以降については見ることはできますが使用許諾上認められていないため,実施することができません。

    現状Trial版でサポートを受けられないのがネックなのでライセンスを購入してルネサスさんに直接聞くしかないかなといった状況です。
  • 電子妖精さん、こんにちは。NoMaYです。

    今回の件は、今のところ一番ありそうな状況(でも、あくまで可能性の一つ、ですけど)は、カーネル側のポインタ変数の値を壊しているユーザアプリケーション側の壊れた値のポインタ変数がある、というものかと思います。(このスレッドに目を通した人のうちの少なくない人数の人が、そう予感しているのではないかと思います。)

    この、ユーザアプリケーション側の壊れた値のポインタ変数、および、値が壊れてしまった理由、を見付けるのも、なかなか大変な気がします。それでも、ユーザアプリケーション側ソース、カーネル側ソース、そしてIECUBE(のフルトレース機能)、の3つが揃えば難易度は随分下がるとは思いますが、オンチップデバッグだけでやろうとすると変数アクセスブレーク機能だけが頼みの綱で、いささか心許ないところです。

    カーネルのソースコードライセンスを購入したものの、オンチップデバッグでは思うようにデバッグ出来なくて、最終的に、ユーザアプリケーション側でポインタ変数でアクセスしている箇所すべてにポインタ値チェックを入れてデバッグする、ということになってしまって、結局、カーネルのソースコードは余り役立たなかった、ということもあるかも知れないです。

    ただ、ユーザアプリケーション側の壊れた値のポインタ変数の候補として可能性が高いのは割り込み処理と通常処理の両方で操作されるポインタ変数、そして、値が壊れてしまった理由として可能性が高いのは通常処理側での所謂DI/EI処理(これはPUSH PSW/DI/POP PSWなど含みます)の漏れではないかと思います(特にRL78は16bitマイコン(というか実質8bitマイコン相当)なので漏れが不具合に繋がり易いような気はします)。今思い付くのは、そういったポインタ変数に優先的にポインタ値チェックを入れてみることかな、と思います。

  • In reply to NoMaY:

    NoMaYさんこんばんは

    こんな情報が足りない中、本当に何度も丁寧にありがとうございます。
    相変わらず暗中模索中ですが、状況報告です。

    私もポインタや配列等でしょうもないミス等からきているというところは内心ずっと抱えながら調べています。(尤もポインタはほとんどコメントアウトしてしまって残っていませんので候補箇所も少ない状況です。)

    今日はE1なしで同じことが起きるかという観点でもう少し調べてみました。
    具体的には、イニシャライズでLEDを1度だけ点灯させ、スタートに戻ったことが分かるように処理を追加したソフトで、E1で毎回同じタイミング(RUNーBREAKタイマで同じ時間)で異常になることを確認し、E1から切断、その後E1を使わずに動作させてリセットがかかっていそうかどうかを確認しました。

    結果としては、何種類のパターンで試しましたがリセットがかかっていそうな挙動は確認できず、また、E1デバッグ中にadc_interraptの割り込みからCALL !!__kernel_int_entry の間にブレークを入れておくと異常がずっと起きないなどといった事象も確認し、ユーザーコードでないところで起きているような印象を受けました。
    (基本的に独学のアマチュアレベルの考えなので信憑性はないです。)

    そのため、私の中ではRTOSの仕様書の読み込み不足で何かやってはいけないことをしているのではないかと今は考えています。

  • 電子妖精さん、こんにちは。NoMaYです。

    > E1デバッグ中にadc_interraptの割り込みからCALL !!__kernel_int_entry の間にブレークを入れておくと異常がずっと起きない

    これって、頻繁にブレークしているのですよね? ブレークさせると現象が発生しなくなる、といった話は昨日もありましたが、実は良くある話だったりします。

    SCI通信の受信をDTCで受けてみるも転送先バッファにデータが格納されない
    japan.renesasrulz.com/cafe_rene/f/forum5/5767/sci-dtc/31991#31991

    ブレークポイントを貼ると送信データはちゃんと意図した7byteが送信されるのですが、
    ブレークポイントを貼らない場合、6byteしか送信されず、またデータの末尾が0xFEとなります。


    また、私の頭の中で近い話として分類されているものでは、連休前にあった(継続中の)スレッドでの、割り込みの優先順位を変更したら現象が発生しなくなった、という話もあります。

    RZ/T1で例外処理が発生し悩んでいます。
    japan.renesasrulz.com/cafe_rene/f/103__-_forum/5761/rz-t1/31934#31934

    暫定処理として全ての割り込みの優先順位を同じにしたところ、(いまのところ)止まっていません。


    考えてみれば、先日のリプライに書いたDI/EI処理の漏れで不具合が発生する話とかは、数十Kバイト、数百Kバイト、といったサイズのプログラムでの、わずか数命令から数十命令のヤバイ区間にまさにドンピシャリのタイミングで割り込みが発生して不具合になってしまう、のですから、ある意味スゴイことですよね。(原因が分かった時には自分が疫病神に取り憑かれているような気分になりますね。)

    自分の印象としては、今回の件では、以下の2点が重たい事象かな、という気がしています。

    (1) 分岐トレースデータの終わりの方でCALL !!__kernel_int_entry以後の分岐命令の可能性は1つだけだった(さすがに__kernel_int_entryからリターンしてはいないと思われる)

    (2) リセット要因レジスタのRESFを確認したら不正メモリアクセスのリセットが発生していた

    それから、E1接続の有無の件では、次の可能性が気になります。

    ・ E1接続時は、もしかしたら、RAMモニタ機能が動作したことによってE1未接続時とはプログラムの動作タイミングが変わってしまった為に現象の有無が異なっている、という可能性はないだろうか、、、

    あと、もう1つ気になるのは、果たして関係があるのかどうか分からないですが(E1未接続時には現象が起きないということですし)、RI78V4のTrial版は以下の使用制限があることを思い出しましたが、現象発生までの時間は30分よりずっと短いですよね?

    RL78ファミリ用リアルタイムOS [RI78V4] V2 製品ページ
    www.renesas.com/jp/ja/products/software-tools/software-os-middleware-driver/itron-os/ri78v4-v2-for-rl78-family.html

    Trial版のRI78V4は、以下の使用制限があります。なお、性能および機能は製品版と同一です。

    RI78V4が約30分動作した後、動作を停止します(無限ループに入ります)。


  • 電子妖精さん、こんにちは。NoMaYです。

    目が覚めて、1つ思い浮かんだ(というか思い出した)ことがあります。E1を外すと動作するが、E1を繋ぐと動作しない、という件で、かつ、オンチップデバッグ使用時、かつ、トレース機能使用時、ということですと、以下の点も確認したいです。

    ・内蔵RAMのトレースRAM領域をプログラム(カーネル側&アプリケーション側)で使用してしまっていないか?(MAPファイルを見れば分かるかと思います。)

    そういえば、昔、かふぇルネで何か投稿があったような気がするなぁ、というのを思い出したので、ググって探してみました。なお、RI78V4は使用していませんが、、、(最初の投稿の「再現性がない」こととは辻褄が合っていないのですが、昨夜の投稿では再現性が上がったような印象なので可能性も無くは無いかも、と思った次第です、、、)

    CS+3デバッグツールの不具合?
    japan.renesasrulz.com/cafe_rene/f/forum21/2498/cs-3/11091#11091

    ちなみに、RL78/G14のハードウェアマニュアルでは、以下のように記載されていました。(スタックメモリ云というのは記載ミスなのかも知れないですが、、、)

    RL78/G14 ユーザーズマニュアル ハードウェア編
    www.renesas.com/jp/ja/doc/products/mpumcu/doc/rl78/r01uh0186jj0330-rl78g14.pdf
    145頁

    3.1.3 内部データ・メモリ空間

    ...略...

    注意4. 次に示す製品の内部RAM 領域は,オンチップ・デバッキングのトレース機能使用時にスタック・メモリとして使用できません。
    R5F104xJ (x = A-C, E-G, J, L) :FA300H-FA6FFH
    R5F104xL (x = G, L, M, P)   :F4300H-F46FFH

  • In reply to NoMaY:

    NoMaYさんこんにちは

    まず1点訂正です。(うすうす間違って伝わっている気がしていました。)
    再現性がないというところですが,1度デバッグで接続したときは基本的に毎回同じタイミングで停止し,一度デバッグを解除してソフトを書き換えて一度書込み,ソフトを元に戻して再書き込みするとなぜかリセットがかかる時間が変わるorリセットがかからなくなるといった意味になります。(プログラムの変更が1度必須,リビルドではダメ)
    また,ブレークを立てながら調べている途中であきらめて1度リセットした後ブレークを外して実行するとなぜか一切止まらなくなることもあります。


    さて,とりあえずすぐ確認できたものとして
    ・頻繁にブレークについては確かにそうなのですが早い条件でリセットがかかるときは3回目のADCで止まるときが最短となるため,そこまで多いわけでもありません。
    ・30分制限についてはそれよりもはるかに短い時間のできごとなので無関係です。
     (違う止まり方をすることを確認しています。)
    ・メモリ領域についても競合しているということはなさそうです。

    いずれにしてもオンチップデバッグの影響で何か実行タイミングがずれている影響はあると思います。
  • 電子妖精さん、こんにちは。NoMaYです。

    そういうことだったのですね。ところで、以下の2点はデバッガソフトウェアの内部処理において、フラッシュメモリ書き換えを行ったかどうか、という共通点がありそうです。(単に「書き換える」ということだけでなく、書き換える為に必要な前処理(例えば内蔵RAMの内容を吸い上げてから書き換えプログラムや書き換えデータを内蔵RAMに転送したり等)や後処理(例えば吸い上げた内蔵RAMの内容を書き戻したり等)が行われることも含みます。)

    (1) 一度デバッグを解除してソフトを書き換えて一度書込み,ソフトを元に戻して再書き込みするとなぜかリセットがかかる時間が変わるorリセットがかからなくなる(プログラムの変更が1度必須,リビルドではダメ)

    (2) ブレークを立てながら調べている途中であきらめて1度リセットした後ブレークを外して実行するとなぜか一切止まらなくなることもあります

    というのは、

    (1') 単にリビルドした時は、ダウンロードが異様に速かったりしないでしょうか?
    ⇒ デバッガはフラッシュメモリの内容をキャッシュしていて、書き換えが不要だと判断したら書き換えていない、ということです。

    (2') ブレークポイントを設定 or 外した直後のGo→Breakは、2回目以降よりも一呼吸長かったりしないでしょうか?
    ⇒ デバッガはブレークポイントを設定 or 外された場合、フラッシュメモリにブレーク命令を書き込んだり or 書き込んだブレーク命令を元々の命令に書き戻したり、を行っているということです。

    正直なところ、これが今回の現象にどう関係するのか(果たして関係するのかも)今のところは推測が出来ないのですが、共通点として、この点はありそうです。

    [追記]

    ですので、デバッガのメモリウィンドウでフラッシュメモリの内容を書き換える、ということでも、リセットがかかる時間が変わるorリセットがかからなくなる、ということが起きる予感がします。

  • In reply to NoMaY:

    NoMaYさんこんにちは

    色々あってなかなかソフトを触る時間がなく少し時間が空いてしまいましたがとりあえずまずは先回の回答です。
    (1') についてはNoです。
    (2') についてはYesです。

    特別なにかしたということはないつもりなのですが、コンフィギュレーションファイルのスタックの値※によってトライアル版上限の30分連続で動く確率が高い条件が見つかりそれでひとまず別の部分のデバッグを進めていたところ、時々ですがRAMパリティエラーでリセットがかかっている場合があることを確認しました。
    ※大きなプログラムでもないので元々スタック破壊は起きないくらい余裕をもって確保してあります。RTOSのセミナー資料に書かれているやり方に対し、基本的にリエントラント性は不要なプログラムですがどうせあまっているので2~3倍は確保済

    RAMパリティーということで紆余曲折ありましたが最終的に以前にNoMaYさんが投稿されたスタートアップルーチンに入れ替えを行いました。
    この記事のもの)
    その結果として、現状は不正メモリアクセスはなくなりRAMパリティーまたはwdtによるリセットがかかる状態でデバッグから切り離してもリセットが発生する状態に変化しました。(大半はRAMパリティー)
    また、wdtでリセットがかかる場合に不思議なのがトレースデータを見ると内容こそ都度変化するとは言えすべて同じコマンドで埋め尽くされているところから例のCMPX 0が実行されているようになり、完全にトレースデータが壊れているように見えてしまう状況になっています。

    RAMパリティーについてはこの記事も見ましたが状況が変わってしまいまたまたちんぷんかんぷんな状況です。

  • 電子妖精さん、こんにちは。NoMaYです。

    > wdtでリセットがかかる場合に不思議なのがトレースデータを見ると内容こそ都度変化するとは言えすべて同じコマンドで埋め尽くされているところから例のCMPX 0が実行されているようになり

    同じコマンドというのはfor節なりwhile節なりの中のループさせる為の分岐命令ではないでしょうか? つまり、本来なにがしかの回数を回った後にループを抜ける条件が成立して抜ける筈のループに、不具合によりいつまでたっても条件が成立せず居続けてしまい、やがてウォッチドッグタイマリセットが掛かった、というのではないでしょうか?

    > リエントラント性は不要なプログラムですがどうせあまっているので2~3倍は確保済

    リエントラント性(再入可能性:関数の途中で割り込みなりタスク切り替えなりが発生して、関数を抜けていない状態で、割り込み処理内や別のタスクにおいて再びその関数が呼び出されても大丈夫であるという性質:タスク切り替えに関する話題の中ではスレッドセーフという言葉が用いられたりもする)は、スタックサイズとは関係無い概念ですよ。

    それで、以前に書いた「壊れた値のポインタ変数がある」と仮定してみると、RAMパリティエラーも不正メモリアクセスもどちらが起きても不思議はないですし、その壊れた値のポインタ変数によるメモリライトで上に書いたループを抜ける条件に関係するような変数の値が壊れてループに居続けたことで、やがてウォッチドッグタイマリセットが掛かってしまう、というのも充分に考えられます。

    それから、以前に以下のように書きましたが、RTOS使用時はもう1種類危惧されるものがありますね。


    ただ、ユーザアプリケーション側の壊れた値のポインタ変数の候補として可能性が高いのは割り込み処理と通常処理の両方で操作されるポインタ変数、そして、値が壊れてしまった理由として可能性が高いのは通常処理側での所謂DI/EI処理(これはPUSH PSW/DI/POP PSWなど含みます)の漏れではないかと思います(特にRL78は16bitマイコン(というか実質8bitマイコン相当)なので漏れが不具合に繋がり易いような気はします)。


    もし複数のタスクからアクセスされるポインタ変数がある場合、ミューテックスなりセマフォなりでポインタ操作を調停するか、割り込みの場合と同様に所謂DI/EI処理で(タスク切り替えが行われないようにしてしまうことで)ポインタ操作を調停するか、といったことをする必要がありますが、それに漏れがあったりしないかどうかも確認が必要なところですね。

    あと、いっそデバッグの為に、一時的に、RAMパリティエラーや不正メモリアクセスエラーやウォッチドッグタイマリセットを無効にした方がデバッグ作業が進んだりしないかなぁ?という考えもし始めています、、、

  • 電子妖精さん、こんにちは。NoMaYです。

    > (1') についてはNoです。

    以前の電子妖精さんの投稿を読み直して気付きましたが「一度デバッグを解除して」とありますね。その場合はきっと「異様に速く」とまでは行かないのでしょうね。これは、今週投稿されていた別スレッド「フラッシュFITモジュールについて質問です」の話から考えられることでもありますが、以下の(A)の場合にはダウンロードが一番早くなるだろうと考えられるのに対し、今回は(B)の場合なのかな、という気がします。

    (A) 以前にフラッシュメモリに書き込んだ内容がキャッシュされていれば、それとダウンロードする内容が比較され、同じであれば以下の(C)のフラッシュメモリ書き換えが行われない(なお(B)のフラッシュメモリ読み出しもされない)

    (B) デバッガ起動後の最初の時は以前にフラッシュメモリに書き込んだ内容はキャッシュされていないので、一度はフラッシュメモリが読み出されて、それとダウンロードする内容が比較され、同じであれば以下の(C)のフラッシュメモリ書き換えが行われない

    (C) 上記の(1)や(2)の比較でダウンロードする内容が異なっていた場合には、フラッシュメモリ書き換えが行われる

    あと、プログラムが作成中で日々変化している&日々変化していたであろう状況なので、以下は、その当時においては、(不正メモリアクセスの発生ではなくて)RAMパリティエラーの発生に関係していたのかも知れない、という考えも思い浮かび始めています、、、(可能性としてですが、、、)


    以下の2点はデバッガソフトウェアの内部処理において、フラッシュメモリ書き換えを行ったかどうか、という共通点がありそうです。(単に「書き換える」ということだけでなく、書き換える為に必要な前処理(例えば内蔵RAMの内容を吸い上げてから書き換えプログラムや書き換えデータを内蔵RAMに転送したり等)や後処理(例えば吸い上げた内蔵RAMの内容を書き戻したり等)が行われることも含みます。)


    正直なところ、これが今回の現象にどう関係するのか(果たして関係するのかも)今のところは推測が出来ないのですが、共通点として、この点はありそうです。

Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page