ルネサス製EEPROMのRandom Read方法について

はじめまして、しんと申します。

現在I2C(簡易版ではない)を利用してのEEPROMのRandom Readを行い、EEPROMの先頭アドレスからReadするプログラムを作成しているのですがうまく行かず困っています。

iica0_master_handler()をデバッグする限り、IICA0にEEPROMアドレスを書く→ACK0割り込み受信→先頭アドレス0x00を書く→ACK0割り込み受信→正常終了(r_iica0_callback_master_sendend())となっているのですが、ウォッチでは読めていないのか0x00となっており(ただ読むと0xFFです)困っています。

よろしければアドバイスをお願い致します。

使用統合開発環境 CS+ for CC

使用製品 RL78/G13

使用EEPROM型名 R1EX24016ASAS0I#S0

Random Readについては、下記データシートのP.13になります。

R1EX24016ASAS0I/R1EX24016ATAS0I データシート (renesas.com)

作成している処理は以下です。

unsigned char  eeprom_adr = 0xA0;

unsigned char dummy_write = 0x00;    //先頭アドレスから読みたい

nsigned char g_buff[256]={0x00};

//ダミーwrite

i2c_access_end_flag = 0;
R_IICA0_Master_Send(eeprom_adr, &dummy_write[0], 1, 1000);
while (i2c_access_end_flag == 0) ;

//256バイトRead

i2c_access_end_flag = 0;
R_IICA0_Master_Receive(eeprom_adr, &g_buff[0], 256, 1000);
while (i2c_access_end_flag == 0);
R_IICA0_StopCondition();

※ダミーWrite後、STOPコンディションを発生しないようにするため、自動生成コード(r_iica0_callback_master_sendend)のSPT0 = 1U;はマスクしています。

i2c_access_end_flagは自動生成コード(r_iica0_callback_master_sendend)で1セットしており、処理完了まで待っています。

  • チョコです。

    シリアル関係のコード生成されたコードには問題があり過ぎてもう何年も自前のライブラリしか使っていません。

    Renesasのサンプルコード「RL78/G13 シリアル・インタフェースIICA(マスタ送受信)(R01AN2759JJ0201 Rev. 2.01)」でもコード生成されたAPI関数ではなく、以下のような独自のライブラリで処理していますよ。

    さて、問い合わせの中身についてみていきます。

    >//ダミーwrite

    これは正しくありません。ここは、「EEPROMへのアクセスするアドレスの設定」が正しい表現です。

    >iica0_master_handler()をデバッグする限り、IICA0にEEPROMアドレスを書く→ACK0割り込み受信→先頭アドレス0x00を書く→ACK0割り込み受信→正常終了(r_iica0_callback_master_sendend())となっているのですが、ウォッチでは読めていないのか0x00となっており(ただ読むと0xFFです)困っています。

    この段階では、単にEEPROMに対して、EEPROMのアドレスを送信しただけです。何もEEPROMからは読み出していません。何をウォッチしているのでしょうか。

    データが受信できているとすると、「//256バイトRead」の処理の後になります。

    ご確認ください。

    以上

  • チョコ様

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

    質問内容に不備があり申し訳ございません。以下訂正いたします。

    ①ダミーWriteについて

         チョコ様に記載いただいた認識はあります。

          EEPROMデータシートでそのような記載だったのでそう書いておりました。

    ②ウォッチ内容

        質問の記述が紛らわしくすみません。

         256バイトRead後のg_buff[]をウォッチしています。

          256バイトRead処理のみですと0xFFを読み出せているのですが、EEPROMへのアクセスするアドレスの設定後だと、変数の初期値のままになります。

    ご紹介いただいたr_iic_libはどこでダウンロードできるかご教示いただけないでしょうか。
    ルネサスのホームから検索等しましたが見つけられませんでした。

  • チョコです。

    >①ダミーWriteについて      チョコ様に記載いただいた認識はあります。

    IICA0での受信動作で、次のデータの受信の時に、IICA0に0xFFを書き込むことでクロック・ストレッチを解除することをダミー・データ書き込みとよんでいます。ここで、書き込んでいるデータはその値自体に意味はありません。だからこそ、ダミー・データと呼んでいます。

    今回の「dummy_writeの書き込み」は全く別の動作で、これはきちんとしたデータの送信で、より具体的には、EEPROMのメモリ・セルのアドレスの指定です。決して、ダミーなんかではありません。

    >256バイトRead処理のみですと0xFFを読み出せているのですが、EEPROMへのアクセスするアドレスの設定後だと、変数の初期値のままになります。

    それは、EEPROMに書き込まれているデータがそのようになっているのではないでしょうか。g_buff[256]の初期値を0x00以外のデータ(例えば、0x00~0xFFのようなインクリメントデータ)にしておけば、書き換わったことは分かります。

    >ご紹介いただいたr_iic_libはどこでダウンロードできるかご教示いただけないでしょうか。

    RenesasのHPで、前回の書き込みで紹介した「R01AN2759JJ0201」をキーワードにして検索すれば、以下のようなアプリケーション・ノートが出てきます。そのサンプル・コードのプロジェクトの中にあります。

    ダウンロードしたzipファイルを解凍してください。

    アプリケーション・ノートに説明が記載されているので、参考にしてください。

    以上

  • 本件、自己解決しました。
    デバッグ環境が変な状態になっていたようで、全て再起動することで所望の動作ができました。

    ダミーデータの定義の件、勉強になりました。
    ありがとうございます。

    サンプルコードはこの後見てみます。
    ありがとうございました。

  • チョコです。

    解決してよかったですね。

    以上

  • 再起動したら解決したとなると・・・

    I2Cは気をつける点があります。I2C使用中、マイコンがリセットした場合、スレーブがSDAを引っ張った状態でい続けることがあります。ご使用されているルネサスの生成コードで初期化時にそれをハンドリングすることができるかわかりませんが、I2Cバスを使う前にSCLとSDAがHighレベルになっているかを確認して、SDAがLowになっている場合のハンドリングをしてくれない場合は以下のようなことをすると解決できます。

    SCLとSDAピンをGPIOとしてHighであることを確認する。この時にSDAがLowならスレーブ側はマイコンがリセットされる直前の処理の途中で止まっています。SCLとSDAをGPIOに切り替えて

    ・SDA=Low

    ・SCL=Low

    ・SDA=High(High出力はオープンドレイン、もしくはGPIO入力モードに切り替える)

    for (9回) {

    ・SCL=Low

    ・SCL=High

    }

    ・SDA=Low

    ・SCL=Low

    ・SCL=High

    ・SDA=High

    ・生成コードのI2Cマスタ初期化

    ※SCLとSDAの出力変更後はソフトウェアdelayを使ってI2Cクロックに準拠させること

  • チョコです。

    >I2Cは気をつける点があります。I2C使用中、マイコンがリセットした場合、スレーブがSDAを引っ張った状態でい続けることがあります。ご使用されているルネサスの生成コードで初期化時にそれをハンドリングすることができるかわかりませんが、

    コード生成では、そのような処理を行うことは考えられていません。

    そんなことを追加するよりは、電源をきちんと入れ直すことをお勧めします。

    EEPROMの初期化は基本的にパワー・オン・リセットだけですから。(EEPROMだけではないですが。)

    以上

  • 現状で起こっている事象としてバスをロックしたままということだと、I2Cデバイスはリセットや投入電源シーケンスに初期化状態に戻るということができていないということになります。回路が対応できて無いならソフトウェアで対応する必要があると思います(装置の”お守り”人間が一緒にシステムに組み込まれるの嫌だな)。

    I2CデバイスのVccをハイサイドスイッチを作って電源をGPIOで投入する仕組みなどがあればマイコンGPIOでI2Cデバイスの「電源をきちんと入れ直す」ができるのでしょうけど( EEPROMくらいならGPIOでVccを供給しても良いですし、複数デバイスならPMOSを使うとか)。I2CのIOエキスパンダICの品番によってはリセット入力があるのに。

  • 書き込みについても注意ですね。


    EEPROMは書き込み命令後実際にデータが保存されるのは5ms経過後です。書き換え中に電源が落ちた時を考えて、直前の値に戻せる仕組みなども必要だと思います。

    方法の1つとしては、メイン+バックアップの二面のエリアを用意して電源投入後に

    1)メインのデータ整合性のチェック(CRCなど)

    2)バックアップのデータ整合性のチェック

    ・両方のエリアが正常なら:メインをバックアップにコピー(毎回やるのは無駄なので書き換え回数カウンタなどで同じかどうかを比較して違う時に行う)

    ・メインのエリアが正常じゃない:バックアップをメインにコピー

    と処理しメイン=バックアップ状態になった後、アプリケーション処理に移るというのが良いのかなと思います。もし、メインもバックアップも異常な状態ならファームウェアデフォルト値を適用する(実装基板の最初の状態の対応のため)。などです。

  • チョコです。

    各メーカのI2CシリアルEEPROMによって、推奨されている復旧の手順が異なるようです。

    しかも、EEPROM(スレーブ)からの読み出し時に発生する問題であり、EEPROM内部の動きとして書き込みはおこなっていないので、電源制御で十分です。

    EEPROMの動作電流は、下に示すように書き換え時でも3mA(max)です。これは十分にポートで制御可能です。

    以上