RX65NのRIIC0にて、アービトレーションロスト検出後にストップコンディションを実行したい

お世話になります。

kukoと申します。

RX65NのRIIC0で通信中に、ノイズによってアービトレーションロストを検出するのですが、

このとき通信の終了処理として、ストップコンディションを実行して、終了したいのですが、

ストップコンディション要求をしても実行してくれません。

どのような手続きを行えば、ストップコンディションを実行してくれるのか、

ご教授いただきく、宜しくお願い致します。

RIIC0のドライバは、COnfig_RIIC0のver.1.4.0をベースとしています。

アービトレーションロスト検出時の各レジスタの状態は以下になります。

void r_Config_RIIC0_error_interrupt(void)
{
 if ((1U == RIIC0.ICIER.BIT.ALIE) && (1U == RIIC0.ICSR2.BIT.AL))
 {

 //ここでブレークした際の、各レジスタの状態となります。

RIIC0.ICCR1 0x9e
RIIC0.ICCR1.ICE 0x1
RIIC0.ICCR1.IICRST 0x0
RIIC0.ICCR1.CLO 0x0
RIIC0.ICCR1.SOWP 0x1
RIIC0.ICCR1.SCLO 0x1
RIIC0.ICCR1.SDAO 0x1
RIIC0.ICCR1.SCLI 0x1
RIIC0.ICCR1.SDAI 0x0
RIIC0.ICCR2 0x80
RIIC0.ICCR2.BBSY 0x1
RIIC0.ICCR2.MST 0x0
RIIC0.ICCR2.TRS 0x0
RIIC0.ICCR2.SP 0x0
RIIC0.ICCR2.RS 0x0
RIIC0.ICCR2.ST 0x0
RIIC0.ICMR1 0x0f
RIIC0.ICMR1.MTWP 0x0
RIIC0.ICMR1.CKS 0x0
RIIC0.ICMR1.BCWP 0x1
RIIC0.ICMR1.BC 0x7
RIIC0.ICMR2 0x00
RIIC0.ICMR2.DLCS 0x0
RIIC0.ICMR2.SDDL 0x0
RIIC0.ICMR2.TMOH 0x0
RIIC0.ICMR2.TMOL 0x0
RIIC0.ICMR2.TMOS 0x0
RIIC0.ICMR3 0x10
RIIC0.ICMR3.SMBS 0x0
RIIC0.ICMR3.WAIT 0x0
RIIC0.ICMR3.RDRFS 0x0
RIIC0.ICMR3.ACKWP 0x1
RIIC0.ICMR3.ACKBT 0x0
RIIC0.ICMR3.ACKBR 0x0
RIIC0.ICMR3.NF 0x0
RIIC0.ICFER 0xf2
RIIC0.ICFER.FMPE 0x1
RIIC0.ICFER.SCLE 0x1
RIIC0.ICFER.NFE 0x1
RIIC0.ICFER.NACKE 0x1
RIIC0.ICFER.SALE 0x0
RIIC0.ICFER.NALE 0x0
RIIC0.ICFER.MALE 0x1
RIIC0.ICFER.TMOE 0x0
RIIC0.ICSER 0x09
RIIC0.ICSER.HOAE 0x0
RIIC0.ICSER.DIDE 0x0
RIIC0.ICSER.GCAE 0x1
RIIC0.ICSER.SAR2E 0x0
RIIC0.ICSER.SAR1E 0x0
RIIC0.ICSER.SAR0E 0x1
RIIC0.ICIER 0xfa
RIIC0.ICIER.TIE 0x1
RIIC0.ICIER.TEIE 0x1
RIIC0.ICIER.RIE 0x1
RIIC0.ICIER.NAKIE 0x1
RIIC0.ICIER.SPIE 0x1
RIIC0.ICIER.STIE 0x0
RIIC0.ICIER.ALIE 0x1
RIIC0.ICIER.TMOIE 0x0
RIIC0.ICSR1 0x00
RIIC0.ICSR1.HOA 0x0
RIIC0.ICSR1.DID 0x0
RIIC0.ICSR1.GCA 0x0
RIIC0.ICSR1.AAS2 0x0
RIIC0.ICSR1.AAS1 0x0
RIIC0.ICSR1.AAS0 0x0
RIIC0.ICSR2 0x00
RIIC0.ICSR2.TDRE 0x0
RIIC0.ICSR2.TEND 0x0
RIIC0.ICSR2.RDRF 0x0
RIIC0.ICSR2.NACKF 0x0
RIIC0.ICSR2.STOP 0x0
RIIC0.ICSR2.START 0x0
RIIC0.ICSR2.AL 0x0
RIIC0.ICSR2.TMOF 0x0
RIIC0.SARL0 0x00
RIIC0.SARL0.SVA 0x00
RIIC0.SARL0.SVA0 0x0
RIIC0.SARU0 0x00
RIIC0.SARU0.SVA 0x0
RIIC0.SARU0.FS 0x0
RIIC0.SARL1 0x00
RIIC0.SARL1.SVA 0x00
RIIC0.SARL1.SVA0 0x0
RIIC0.SARU1 0x00
RIIC0.SARU1.SVA 0x0
RIIC0.SARU1.FS 0x0
RIIC0.SARL2 0x00
RIIC0.SARL2.SVA 0x00
RIIC0.SARL2.SVA0 0x0
RIIC0.SARU2 0x00
RIIC0.SARU2.SVA 0x0
RIIC0.SARU2.FS 0x0
RIIC0.ICBRL 0xff
RIIC0.ICBRL.BRL 0x1f
RIIC0.ICBRH 0xed
RIIC0.ICBRH.BRH 0x0d
RIIC0.ICDRT 0xc0
RIIC0.ICDRR 0x59

以上、宜しくお願い致します。

  • kukoさん

    バスリセットをしてみてはいかがですか。

  • kukoさん、こんにちは。NoMaYと申します。

    バスリセットという操作が出来て、それにより解決しましたでしょうか?(実は、私ではお役に立てない、とは思っているのですけれども、どういう状況なのか気になりましたので。)

  • IKUZO様

    kukoです。

    アドバイスありがとうございます。

    お返事が遅くなり申し訳ありません。

    まだ試せてはいないのですが、バスリセットとは、RIIC0.ICCR1.IICRSTビットを1にする操作のことでしょうか?

    ご教授のほど、宜しくお願い致します。

  • NoMaY様

    kukoです。

    まだ試せていない状況です。

    以上、宜しくお願い致します。

  • 別CPUの話なので、該当しないかもしれませんが IICRST をしてもストップコンディションはでませんでした。

    IICで使っているポートを無理やり汎用IOにして、ポートをパタパタさせて、

    ストップコンディションを出したことがあります。それでバス開放されます。

  • kukoさん

    この中から見てください

    ///////////////////////////////////////////////////////////////////////
    //RIIC0の初期化 disp
    ///////////////////////////////////////////////////////////////////////
    //SDA0 P13 44
    //SCL0 P12 45
    BOOL RIIC0_init(void)
    {
    SYS_PROTECT_OFF
    MSTP(RIIC0)=0;
    SYS_PROTECT_ON

    //I/Oポート機能
    PORT1.PMR.BIT.B2=0; //P12初期化 SCL1
    PORT1.PMR.BIT.B3=0; //P13初期化 SDA1

    MPC_PROTECT_OFF
    MPC.P12PFS.BYTE=0x0F; //P12 SCL1
    MPC.P13PFS.BYTE=0x0F; //P13 SDA1
    MPC_PROTECT_ON

    PORT1.PDR.BIT.B2=1; //P12 SCL1->W
    PORT1.PDR.BIT.B3=0; //P13 SDA1->R

    PORT1.PMR.BIT.B2=1; //P12 SCL1->peripheral.
    PORT1.PMR.BIT.B3=1; //P13 SDA1->peripheral.

    RIIC0.ICCR1.BIT.ICE=0;//SCLn、SDAn端子非駆動状態
    RIIC0.ICCR1.BIT.IICRST=1;//RIICリセット
    RIIC0.ICCR1.BIT.ICE=1;//内部リセット

    RIIC0.ICSER.BIT.SAR0E=1;//スレーブアドレスレジスタ0有効
    RIIC0.ICSER.BIT.SAR1E=0;//スレーブアドレスレジスタ1無効
    RIIC0.ICSER.BIT.SAR2E=0;//スレーブアドレスレジスタ2無効
    RIIC0.ICSER.BIT.GCAE=1;//ジェネラルコールアドレス有効
    RIIC0.ICSER.BIT.DIDE=0;//デバイスIDアドレス検出無効
    RIIC0.ICSER.BIT.HOAE=0;//ホストアドレス検出は無効

    RIIC0.ICMR1.BIT.BC=0;//9ビットカウンタ
    RIIC0.ICMR1.BIT.BCWP=1;//BCライトプロテクト
    RIIC0.ICMR1.BIT.CKS=2;//PCLK/1クロック
    RIIC0.ICMR1.BIT.MTWP=0;//ICCR2.MST,TRSビット書き込み禁止

    RIIC0.ICBRL.BIT.BRL=0x1F;//SCLクロックのLow幅の値
    RIIC0.ICBRH.BIT.BRH=0x1F;//CLクロックのHigh幅の値

    RIIC0.ICMR2.BIT.TMOS=0;//ロングモードタイムアウト検出時間
    RIIC0.ICMR2.BIT.TMOL=0;//SCLnラインがLowでLカウント禁止
    RIIC0.ICMR2.BIT.TMOH=0;//SCLnラインがHighでHカウント禁止
    RIIC0.ICMR2.BIT.TMWE=0;//カウンタへの書き込み禁止
    RIIC0.ICMR2.BIT.SDDL=0;//SDA出力遅延なし
    RIIC0.ICMR2.BIT.DLCS=0;//SDA出力遅延カウンタのクロックソースは内部基準クロック

    RIIC0.ICMR3.BIT.NF=0;//フィルタは1段
    RIIC0.ICMR3.BIT.ACKBR=0;//R アクノリッジビットに“0”を受信
    RIIC0.ICMR3.BIT.ACKBT=0;//W アクノリッジビットに“0”を送出
    RIIC0.ICMR3.BIT.ACKWP=1;//ACKBTビットへの書き込み許可
    RIIC0.ICMR3.BIT.RDRFS=0;//8クロック目の立ち下がりでSCLnラインをLowにホールドしない
    RIIC0.ICMR3.BIT.WAIT=0;//9クロック目と1クロック目の間をLowにホールドしない
    RIIC0.ICMR3.BIT.SMBS=0;//I2C バス選択

    RIIC0.ICFER.BIT.TMOE=0;//タイムアウト検出機能無効
    RIIC0.ICFER.BIT.MALE=1;//マスタアービトレーションロスト検出許可
    RIIC0.ICFER.BIT.NALE=0;//NACK送信アービトレーションロスト検出禁止
    RIIC0.ICFER.BIT.SALE=0;//スレーブアービトレーションロスト検出禁止
    RIIC0.ICFER.BIT.NACKE=1;//NACK受信時転送を中断する(転送中断許可)
    RIIC0.ICFER.BIT.NFE=1;//デジタルノイズフィルタ回路を使用
    RIIC0.ICFER.BIT.SCLE=1;//SCL同期回路有効
    RIIC0.ICFER.BIT.FMPE=0;//SCLn端子/SDAn端子にfm+用スロープ制御回路を使用しない

    RIIC0.ICIER.BIT.TMOIE=0;//タイムアウト割り込み
    RIIC0.ICIER.BIT.ALIE=0;//アービトレーションロスト割り込み
    RIIC0.ICIER.BIT.STIE=0;//スタートコンディション検出割り込み
    RIIC0.ICIER.BIT.SPIE=0;//ストップコンディション検出割り込み
    RIIC0.ICIER.BIT.NAKIE=0;//NACK受信割り込み
    RIIC0.ICIER.BIT.RIE=0;//受信データフル割り込み
    RIIC0.ICIER.BIT.TEIE=0;//送信終了割り込み
    RIIC0.ICIER.BIT.TIE=0;//送信データエンプティ割り込み

    RIIC0.ICCR1.BIT.IICRST=0;//RIICリセット解除
    return TRUE;
    }
    ///////////////////////////////////////////////////////////////////////
    //RIIC0の初期化 disp
    ///////////////////////////////////////////////////////////////////////

  • kukoさん、こんにちは。NoMaYです。

    私は、ほんの2ヶ月前に初めてI2Cの実際に動くプログラム(といっても初心者プログラム)を作っただけの経験しかないですが、kukoさんの状況というのは、マルチマスタで使っているわけでは無いのだけれども(RX65Nがシングルマスタで他はスレーブデバイスが1つ?)、最初の相談文にあったように、ノイズによりアービトレーションロストが検出されてしまったので、ストップコンディションを発行してスレーブとの通信をいったん終了したい(そうしないとスレーブが通信の続きを待ち続けてしまう)、という状況ですか?(実際にマルチマスタ接続であって、本当のアービトレーションロストが発生したら、次に自分がマスタになるまでは何も送信出来ないものである、そんなような気がしたからです。)

    --------

    自分の経験はここまでですが、、、(しかもRIICは使っていないです、、、)

    TB-RX65N/RX130/RX231+CSplus sample program
    japan.renesasrulz.com/cafe_rene/f/002-2095199602/6870/tb-rx65n-rx130-rx231-csplus-sample-program/36990#36990
     

  • kukoさん、こんにちは。NoMaYです。

    RX65Nのハードウェアマニュアルと睨めっこしているのですが、アービトレーションロストが発生したら(とりあえずマスタアービトレーションロストだと仮定します)スレーブモードに遷移して受信待ちになるようですね。なので、この場合、マスタモードに遷移して送信待ちの状態に切り替える必要はあるのではないかと思うのです。フラグで書けば以下です。その上で、ストップコンディションの発行を要求するとどうなりますでしょうか?

    /* マスタ送信中にマスタアービトレーションロストが検出された⇒スレーブモードで受信モードに遷移している */

    RIIC0.ICCR2.MST = 1; /* マスタモードへ復帰 */
    RIIC0.ICCR2.TRS = 1; /* 送信モードへ復帰 */

    /* I2Cバス占有状態(ICCR2.BBSY == 1)であればストップコンディションを発行出来るのではないか? */

    RIIC0.ICCR2.SP = 1; /* ストップコンディションの発行を要求 */

    /* 果たしてストップコンディションを発行出来るか??? */

    [追記]

    引き続きハードウェアマニュアルと睨めっこしていたのですが、ストップコンディションの発行に必要な条件は、MST == 1 かつ BBSY == 1 のようですね。TRSは切り替えなくても良いのかも知れません。

  • 「ノイズなどによって、マスタ・デバイスが出したつもりの無いデータがバス上に出たりした場合にもアービトレーション・ロストが発生します。 このような場合、I2Cモジュールは、即座に通信を中断し、バスを開放する」ということなので

    RIIC0.ICCR1.BIT.IICRST=1;//RIICリセット

    ですかね

    ついでに

    RIIC0.ICCR1.BIT.ICE=1;//内部リセット

    ?

  • チョコです。

    例によって、RXは使ったことはありませんが、RXがノイズでアービトレーション負けを検出して通信から退避した状態だけであれば、RX側の対応(RIICのリセット)で対策できるかもしれません。しかし、問題は通信の場合には相手(この場合にはスレーブ)があり、スレーブがSDAラインをLowに引いている状態ではRX側は何もできません。ストップコンディションも発行できません。この場合には、SCL信号にダミー・クロックを出力してスレーブがSDA信号を引っ張るのをやめさせる必要があります。