起動直後にr_Config_RIIC0_error_interrupt()が永遠に呼ばれる (RX231/CS+ )

いつもお世話になっております。

コード生成で生成したConfig_RIIC0を使用し開発を進めているのですが以下の現象が発生しておりご教授いただけますと幸いです。

 

【発生現象】

R_Config_RIIC0_Start()コール後に、r_Config_RIIC0_error_interrupt()が永遠に呼ばれる

 

r_Config_RIIC0_error_interrupt()を確認した所、どのif/else ifにも入らず、下記のelseに入っております。

                :

else
{
 /* Do nothing */
}

 

【備考】

コード生成のバグがあるようで下記のコードは削除しましたが、そもそもその条件成立しておりません。

https://www.renesas.com/jp/ja/doc/toolnews/jpn/2019/r20ts0462jj0100-cstnno.pdf

 

Parents
  • bunbun様、鈴木と申します。
    お使いのツールはスマートコンフィグレータと思われます。そのためコード生成の不具合は該当いたしません。ツール名とツールのバージョンを教えてください。
    またAPIマニュアルに記載のI2Cサンプルは動作するでしょうか(下記219ページ)
    www.renesas.com/.../r20ut4360jj0103-scapirx.pdf
    以上、よろしくお願いします。
  • 鈴木様
    御世話になっております。
    ご教授有難うございます。

    ●環境は以下です。
    CS+ for CC: V8.03.00
    スマートコンフィグレータ: V1.02.07.01
    Config_RIIC0: 1.8.0


    >またAPIマニュアルに記載のI2Cサンプルは動作するでしょうか(下記219ページ)

    正常動作せず、以下に入ります。
    SCL/SDA波形をみる限りスタートコンディション発行後、SDAがすぐに立ち上がり、クロックすらでておりません。

    r_Config_RIIC0_error_interrupt()
    {
    :
    else if ((1U == RIIC0.ICIER.BIT.NAKIE) && (1U == RIIC0.ICSR2.BIT.NACKF))
    {
    if (_0D_IIC_MASTER_TRANSMIT == g_riic0_mode_flag)          ★★この条件が成立
    {
    RIIC0.ICSR2.BIT.STOP = 0U;                    
    RIIC0.ICCR2.BIT.SP = 1U;
    while (1U != RIIC0.ICSR2.BIT.STOP)
    {
    nop();
    }
    RIIC0.ICSR2.BIT.NACKF = 0U;
    RIIC0.ICSR2.BIT.STOP = 0U;
    }


    取り急ぎ、失礼いたします。
  • bunbun様、鈴木と申します。情報ありがとうございます。

    Q1 -> 引数の認識は問題ありません。アドレスはスマートコンフィグレータで後からR/Wフラグを付加するので、そのままのアドレスを指定します。

    Q2 -> はい、R_Config_RIIC0_Master_Send()をお使いください。

    R_Config_RIIC0_Master_Sendは割り込みで処理されますので、関数を呼んだ後に時間待ちが必要です。(あるいは割り込みハンドラで送信完了を待つ)

    アドレスがあっていれば送信されますので、波形を見てご確認ください。

    SWが押下されたら送信するプログラムで試してみましたが、送信できました。

    volatile uint8_t gSw1;

    volatile uint8_t gData[2] = { 0x2, 0x3 };

    void main(void)

    {

       gSw1 = 0;

       R_Config_ICU_IRQ1_Start();

     R_Config_RIIC0_Start();

     while (1)

     {

        if ( gSw1 == 1 )

      {

                  R_Config_RIIC0_Master_Send( 0x40, gData, 2);

         gSw1 = 0;

      }

     }

    }

  • 鈴木様
    ご教授有難うございます。

    上記の通り「0x03」を送信した際にゴミがのるようなのですが
    volatileは試しておりません(非同期で変化するような変数ではないので不要の認識でした)が
    逆にconstを付与して試しましたがやはりゴミがのります。

    またr_Config_RIIC0_transmit_interrupt()の★gp_riic0_tx_addressが指すアドレスおよびデータをみましたが
    そこは問題ありませんでした。

    2Byte目にゴミがのるような要因は他に考えられるのでしょうか?


    static void r_Config_RIIC0_transmit_interrupt(void)
    {
          :
    else if (_05_IIC_MASTER_SENDS_DATA == g_riic0_state)
    {
    if (0U < g_riic0_tx_count)
    {
    RIIC0.ICDRT = *gp_riic0_tx_address;             ★
    gp_riic0_tx_address++;

          :
  • bunbun様、それはACKではないでしょうか?(スレーブから受け取ったという信号)
    ACKがないと、マスター側は2byte目を送信しないと思います。
  • bunbunさん、こんにちは。NoMaYです。

    割り込み処理のデバッグの際に、一気に実行させた場合とブレークさせながら実行させた場合で動作が異なることは良くあることですので、デバッグ技法的に、N回目の事象該当時にブレークさせたい時に使える手として、以下のような手がありますよ。

    ・グローバル変数 int debug_event_count を作る
    ・事象該当箇所に以下のようなif文を埋め込む

    if (N == debug_event_count++)
    {
        nop(); /* set breakpoint */
    }

    ・上記のnop()にブレークポイントを設定して実行開始させる

    思うに、今回のデバッグの最初の勘所は、一気に実行させた場合に、2つ目の送信データとして RIIC0.ICDRT に書いたのは実際に 0x03 だったのだろうか?では無いかと思うのです。(ブレークさせながらデバッガで確認した値は 0x03 だったとのことですが、一気に実行させた場合の挙動とは異なっているとのことですので。)

  • お二方、ご教授有難うございます。
    下記について後程、確認してご報告いたします。

    1)R_Config_RIIC0_Master_Send()送信後、無限ループさせてみる
    2)1Byte送信後の(SlaveDeviceからの)ACK/NACKの件
    3)カウンタブルブレーク
    4) RIIC0.ICDRT に書きこんだ実際の値( 0x03 なのか?)
  • お二方
    いつも大変お世話になっております。

    下記の確認結果のご報告と一点、ご教授ください。
    /*------------------------------- ご質問 -----------------------------------------------*/
    マスター送信は成功するのですが
    それでもr_Config_RIIC0_error_interrupt()の★2か所に必ず入ります。
    該当コードをみると正常シーケンスのような気がしますが、関数名にerrorとついているのできになります。

    正常なのでしょうか?


    #if FAST_INTERRUPT_VECTOR == VECT_RIIC0_EEI0
    #pragma interrupt r_Config_RIIC0_error_interrupt(vect=VECT(RIIC0,EEI0),fint)
    #else
    #pragma interrupt r_Config_RIIC0_error_interrupt(vect=VECT(RIIC0,EEI0))
    #endif
    static void r_Config_RIIC0_error_interrupt(void)
    {
    :
    else if (_0D_IIC_MASTER_TRANSMIT == g_riic0_mode_flag)
    {
    if ((_01_IIC_MASTER_SENDS_ADR_7_W == g_riic0_state) || (_02_IIC_MASTER_SENDS_ADR_10A_W == g_riic0_state))
    {
    LOG(U_LOG_ERROR, U_LOG_TAG_I2C, "6\n", NULL);                    ★
    RIIC0.ICSR2.BIT.START = 0U;
    RIIC0.ICIER.BIT.STIE = 0U;
    RIIC0.ICIER.BIT.SPIE = 1U;
    }
    else if (_07_IIC_MASTER_SENDS_STOP == g_riic0_state)
    {
    LOG(U_LOG_ERROR, U_LOG_TAG_I2C, "7\n", NULL);                    ★
    RIIC0.ICSR2.BIT.NACKF = 0U;
    RIIC0.ICSR2.BIT.STOP = 0U;
    RIIC0.ICIER.BIT.SPIE = 0U;
    RIIC0.ICIER.BIT.STIE = 1U;

    r_Config_RIIC0_callback_transmitend();
    }

    /*------------------------------- 確認結果 -----------------------------------------------*/
    1)R_Config_RIIC0_Master_Send()送信後、無限ループさせてみる ※現状は100msウェイトで送信成功
    ⇒マスター送信成功

    2)1Byte送信後の(SlaveDeviceからの)ACK/NACKの件
    ⇒SlaveデバイスからはACKが応答されておりました。

    3)カウンタブルブレーク
    ⇒機能致しました。ご教授有難うございます。

    4) RIIC0.ICDRT に書きこんだ実際の値( 0x03 なのか?)
    ⇒「ブレーク+Step実行確認」でも「printfログでの確認」でも「0x03」でした。
  • bunbunさん、こんにちは。NoMaYです。

    すみません、確認ですが、4)は1)の状況でのことですよね?

    > 1)R_Config_RIIC0_Master_Send()送信後、無限ループさせてみる ※現状は100msウェイトで送信成功
    > ⇒マスター送信成功

    > 4) RIIC0.ICDRT に書きこんだ実際の値( 0x03 なのか?)
    > ⇒「ブレーク+Step実行確認」でも「printfログでの確認」でも「0x03」でした。

    それで、以下はRX231マイコンの割り込み仕様が以下の画面コピーの通り、エラー発生とイベント発生で共有されているからではないでしょうか、、、

    > マスター送信は成功するのですが
    > それでもr_Config_RIIC0_error_interrupt()の★2か所に必ず入ります。
    > 該当コードをみると正常シーケンスのような気がしますが、関数名にerrorとついているのできになります。
    > 正常なのでしょうか?

    RX230グループ、RX231グループ  ユーザーズマニュアル ハードウェア編の画面コピー
    www.renesas.com/jp/ja/search/keyword-search.html#genre=document&q=r01uh0496
    r01uh0496jj0120-rx231.pdf

     

  • NoMaYさん、こんにちは。


    >4)は1)の状況でのことですよね?

    はい。(無限ループさせない時でも0x03でした)

    >それで、以下はRX231マイコンの割り込み仕様が以下の画面コピーの通り、エラー発生とイベント発生で共有されているからではないでしょうか、、、

    共通なんですね。。。。(マニュアル記載部のコピーまで有難うございます)



    タイトルの現象は一先ずクリア?できましたので
    本件はクローズさせて頂きます。


    ご教授、誠にありがとうございます。
  • bunbunさん、こんにちは。NoMaYです。

    > >4)は1)の状況でのことですよね?
    > はい。(無限ループさせない時でも0x03でした)
    。。。
    > タイトルの現象は一先ずクリア?できましたので
    > 本件はクローズさせて頂きます。

    クローズすることに、待った、を掛けるほどのことではないですけれど「無限ループさせない時でも0x03でした」という点は、予感として、以下の時から、printfログなどの処理が追加されていて、プログラムの動作タイミングがいろいろ変化していて、現状では一気に実行させていても『SDA波形を確認すると0x03が出力されている』のではないかなぁ、という気がします、、、(デバッグ用printfを挿入したらデバッグ中のプログラムの動作が変わってしまった(動作するようになってしまった or 動作しなくなってしまった)というのも、時々ありますので、、、)

    > 下記のコードを実施した際に、0x03を送信された際のSDA波形が0001 1101(0x1D)になります。
    > 但しr_Config_RIIC0_transmit_interrupt()内にBreakを貼り、1Byteずつ止めるとSDA波形は0x08, 0x02, 0x03と順次送信されました。

    ちなみに、私が推測していた、一気に実行させた時とブレークさせながら実行させた時では、SDA波形の3つ目のデータが、期待値0x03に対して観測値0x1Dだった理由は、以下のようなことではないかなぁ、というものです。

    前提:

    ・ RIICaの送信回路はダブルバッファ構造である
    ・ ダブルバッファ構造の送信回路の一般論として1つ目の送信データの書き込みのすぐ直後にバッファエンプティ割り込みが発生する
    ・ そのバッファエンプティ割り込みで2つ目の送信データを書き込んだ後での次のバッファエンプティ割り込みは暫く間が空く

    一気に実行させた時の推測(あくまで推測ですが):

    ・R_Config_RIIC0_Master_Send()を実行して、1つ目(スレーブアドレス)と2つ目(0x02)を割り込みでICDRTに書いたタイミングまでは、R_Config_RIIC0_Master_Send()を実行した関数内だったのではないだろうか
    ・ところが、3つ目(0x03)をICDRTに書く割り込みが発生したタイミングでは、R_Config_RIIC0_Master_Send()を実行した関数を既に抜けていて、他の関数の呼び出しが行われていて、スタック上に確保されていた送信データの配列自体が書き換わってしまっていて(0x1Dに書き換わっていて)、SDA波形として0x1Dが観測されたのではないだろうか

    ブレークさせながら実行させた時の推測(あくまで推測ですが):

    ・2つ目(0x02)を書く割り込み処理内で一旦ブレークさせると、ブレーク中に、次のバッファエンプティ割り込みが発生してしまうように思われる
    ・なので、GoするとRTE直後に3つ目(0x03)を書く割り込みに入ってブレークしてしまう
    ・通常処理側の視点では、1つ目(スレーブアドレス)と2つ目(0x02)の割り込みが連続するだけでなくて、3つ目(0x03)も連続して発生しているように見える筈である (それに対して、一気に実行させた時は、3つ目(0x03)は暫く間が空いて発生する)
    ・なので、3つ目(0x03)の割り込み発生タイミングでも、R_Config_RIIC0_Master_Send()を実行した関数内に留まっていて、スタック上に確保されていた送信データの配列は書き換わること無く値を保持していて、そのおかげでSDA波形として0x03が観測されたのではないだろうか

    デバッグコンソール出力(?)のデバッグ用printfを挿入した時の推測(あくまで推測ですが):

    ・デバッグ用printfは各回の割り込み発生で毎回printfされるようになっていたとかだろうか?
    ・もしそうなら、2つ目(0x02)を書く割り込み処理内でデバッグ用printfしている内に、次のバッファエンプティ割り込みが発生してしまっているのかも知れない
    ・そうだった場合には、その後の推測は、上のブレークさせながら実行させた時の推測と同じことになるだろうと思われる

  • NoMaYさん、こんにちは。

    何もかもご指摘の通りかと思っています。

    ・(割込処理内に) printfを入れないとデータが正常にでる。
    ・割込処理内にprintf文をいれてしまったので「遅延が発生しタイミングがずれた」
    ・無限ループをいれなかった時は、更に「他の割込が発生」していた

    と思われます。

    また当方もちゃんと手順よく開発すればよかったのですが
    投稿当初はSlaveデバイスは別のデバイスAを接続し確認してしまい(他のボードで実績のあるデバドラ使用)
    NACK応答で、ろくに調べずタイトル通りのerrorとつく名の関数に毎回入っているのが問題だと認識してしまいました。
    (途中からはSlaveデバイス側の挙動がみれるデバイスBにしてデバッグして)

    現在に至っております。

    いずれにしろ、毎度、本当にありがとうございます。
Reply
  • NoMaYさん、こんにちは。

    何もかもご指摘の通りかと思っています。

    ・(割込処理内に) printfを入れないとデータが正常にでる。
    ・割込処理内にprintf文をいれてしまったので「遅延が発生しタイミングがずれた」
    ・無限ループをいれなかった時は、更に「他の割込が発生」していた

    と思われます。

    また当方もちゃんと手順よく開発すればよかったのですが
    投稿当初はSlaveデバイスは別のデバイスAを接続し確認してしまい(他のボードで実績のあるデバドラ使用)
    NACK応答で、ろくに調べずタイトル通りのerrorとつく名の関数に毎回入っているのが問題だと認識してしまいました。
    (途中からはSlaveデバイス側の挙動がみれるデバイスBにしてデバッグして)

    現在に至っております。

    いずれにしろ、毎度、本当にありがとうございます。
Children
No Data