簡易I2Cについて

stlと申します。

RA2E1マイコンで簡易I2Cの機能を使用しています。デバッグを実行してみると、送信用のAPI関数の戻り値としては「成功」となりますが、オシロスコープでピンの出力を確認すると、SDAとSCLKの出力波形が確認できず、関数の実行タイミングで5Vから0Vに変化するだけでした。 この問題について何かわかることがありますでしょうか?

  • チョコです。

    RL78は日頃使っていますが、RAは使ったことがありませんので、想像になりますが、コメントさせてもらいます。

    おそらく、SCを使ってコード生成されていると思いますが、送信用のAPIは送信処理を起動するだけで戻ってきている

    のではないでしょうか。

    また、「SDAとSCLKの出力波形が確認できず、関数の実行タイミングで5Vから0Vに変化するだけでした。」は、

    スタート・コンディションが発行された状態ではないかと思います。

    つまり、通信が開始した時点までの波形しか確認していないのではないでしょうか。

    通信が完了したことを確認して、そこまでの波形を確認されることをお勧めします。

    以上

  • ご回答ありがとうございます。

    >>通信が完了したことを確認して、そこまでの波形を確認されることをお勧めします。

    送信用のAPIが、通信が完了までいかなくても起動した段階で「成功」を返してきている可能性があるということでしょうか?

  • チョコです。

    >送信用のAPIが、通信が完了までいかなくても起動した段階で「成功」を返してきている可能性があるということでしょうか?

    はい、そうです。通信関係のAPIのこのことがかふぇルネでも結構問題になっていました。

    RAのSCは見たことはありませんが、RL78やRXのSCの通信関係のAPIは通信完了まで待たずに戻ります。

    RL78のSCAPIマニュアルをダウンロードしたところ、いつの間にか戻り値がなくなっていました。

    これだけでは、判らないので、RL78/G15で実際にIIC00で送信APIを生成してみました。

    下のように、スレーブアドレスをIIC00に書き込んだところで戻っています。また、APIマニュアルの記述のように戻り値はなくなっています。

    SCは少なくともベアメタルでのマルチタスクをサポートしているので、通信完了を待つことはありません。

    これは、RAでも同じだと思われます。(出ている症状からも送信完了を待たないのは明らかです。)

    以上

  • APIの戻り値が送信完了を示しているわけではないとしたら、送信が完了していることの確認は、オシロスコープでそこまでの波形を見る以外方法はないということになるのでしょうか?

  • チョコです。

    あくまで、RL78/G15のケースですが、以下に示すIIC00の割り込み処理(Config_IIC00_user.cの「r_Config_IIC00_interrupt関数)の中で、指定した数のデータの送信が完了すると、147行目で r_Config_IIC00_callback_master_sendend関数を呼び出しています。

    このr_Config_IIC00_callback_master_sendend関数で完了したことを示すフラグをセットするような処理を書き込むことができるようになっています。この、74行目と75行目の間にそのような処理を追加することになります。

    ここまで、きちんとサポートするようにずっと訴えているのですが、いまだに対応してもらっていません。

    RAで類似のコールバック関数を探してそこでフラグをセットして、そのフラグがセットされるのを待つようにしてください。

    以上

  • RAの場合だと、コールバック関数の引数に送信完了を示す値が代入されるようになっていました。そちらを確認してみると、そもそも送信が完了しませんでした。原因を探してみます。

    • R_IIC_MASTER_Open
    • R_IIC_MASTER_CallbackSet
    • R_IIC_MASTER_SlaveAddressSet

    SDAとSCLがLowに落ちると書いてあるのでスタートコンディションには入っていそうですが、上の3つはR_IIC_MASTER_Writeの前に実行していますよね? 

  • OpenはAPI関数で実行しています。コールバックとスレーブアドレスセットはプロパティで設定を行っています。

  • チョコです。

    RAはRLやRXとは全く違うようですね。また、RA2E1には、そもそもSCはないようですね。

    どうも、FSPで処理しているようで、APIも全く異なるようです

    もしかするとOpenでスタート・コンディションを発行してI2Cバスを確保しているのですかね。

    APIも全く異なるようなので、これ以上はコメントを控えさせていただきます。

    以上

  • 簡易I2Cと書いてあるので、SCIインタフェースを使用したI2Cという様に考えて書き込みします。

    RA2E1のチップで試してみましたが、特に設定をしなくても、波形がでました。

    hal_entry_c.txt
    #include "hal_data.h"
    
    FSP_CPP_HEADER
    void R_BSP_WarmStart(bsp_warm_start_event_t event);
    FSP_CPP_FOOTER
    
    volatile int g_i2c_tx_flag = 0;
    volatile int g_i2c_rx_flag = 0;
    
    /*******************************************************************************************************************//**
     * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
     * is called by main() when no RTOS is used.
     **********************************************************************************************************************/
    void hal_entry(void)
    {
        /* TODO: add your own code here */
    
        fsp_err_t err;
        unsigned char tx_buffer[10] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10};
    
        R_SCI_I2C_Open(&g_i2c9_ctrl, &g_i2c9_cfg);
    
        g_i2c_tx_flag = 0;
        err = R_SCI_I2C_Write(&g_i2c9_ctrl, &tx_buffer[0], 1, false);
    
        if (err != FSP_SUCCESS)
        {
            __NOP();
        }
    
        while(1)
        {
            //送信完了待ち
            if (g_i2c_tx_flag == 1) break;
        }
    
        while(1)
        {
            __NOP();    //送信完了
        }
    
    #if BSP_TZ_SECURE_BUILD
        /* Enter non-secure code */
        R_BSP_NonSecureEnter();
    #endif
    }
    
    /*******************************************************************************************************************//**
     * This function is called at various points during the startup process.  This implementation uses the event that is
     * called right before main() to set up the pins.
     *
     * @param[in]  event    Where at in the start up process the code is currently at
     **********************************************************************************************************************/
    void R_BSP_WarmStart(bsp_warm_start_event_t event)
    {
        if (BSP_WARM_START_RESET == event)
        {
    #if BSP_FEATURE_FLASH_LP_VERSION != 0
    
            /* Enable reading from data flash. */
            R_FACI_LP->DFLCTL = 1U;
    
            /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
             * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
    #endif
        }
    
        if (BSP_WARM_START_POST_C == event)
        {
            /* C runtime environment and system clocks are setup. */
    
            /* Configure pins. */
            IOPORT_CFG_OPEN (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);
        }
    }
    
    #if BSP_TZ_SECURE_BUILD
    
    FSP_CPP_HEADER
    BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();
    
    /* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
    BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
    {
    
    }
    FSP_CPP_FOOTER
    
    #endif
    
    void sci_i2c_master_callback(i2c_master_callback_args_t * p_args)
    {
        //SLAVEを接続していない場合
        //割り込みには飛んでくるが
        //p_args->event == I2C_MASTER_EVENT_ABORTED
    
        if (p_args->event == I2C_MASTER_EVENT_TX_COMPLETE)
        {
            g_i2c_tx_flag = 1;
        }
        else if (p_args->event == I2C_MASTER_EVENT_RX_COMPLETE)
        {
            g_i2c_rx_flag = 1;
        }
    }
    

    FSPの設定では、I2C_Master(r_sci_i2c)を追加しただけです。動作確認用に使ったhal_entry.cを貼り付けます。

    R_SCI_I2C_Write() は、直ぐにFSP_SUCCESSを返します。(その時点ではデータ転送は行われていません。)

    コールバック関数(sci_i2c_master_callback())が呼ばれて、

    p_args->event == I2C_MASTER_EVENT_TX_COMPLETE

    となっていれば、データ送信が完了しています。

    ・FSPで設定したSLAVEアドレスのデバイスがつながっている場合

    →送信完了と書いてある行まで到達します

    ・FSPで設定したSLAVEアドレスのデバイスがつながっていない場合

    →SCL, SDAから波形は出ます

    →コールバック関数に来ます

    p_args->event == I2C_MASTER_EVENT_ABORTED

    なので、添付したサンプルでは //送信完了待ち のところで無限ループです。

    (添付は送信のサンプルですが、受信の場合は、g_i2c_rx_flag ==1 を待てば、受信データの処理に移って良いです。)

    SCL, SDAのラインに外部でプルアップ抵抗は付けていますか?

    FSPの端子設定のところで、SCL, SDA端子を選択していますか?

    動かないとすれば、その辺りかな?と思いますが。