皆様,
G13(CCRL)にてチョコさんのIICサンプルプログラムのMD_STATUS put_data_IIC00( uint8_t s_addr, uint8_t buffer1, uint8_t buffer2)を修正し,以下のプログラムを作成しました.
これはEEPROMのByte Writeを行うためのものです.これを5msのインターバルをおいて連続的に書き込むと,非常に不安定で正常に書き込めないことが多発しています.buffer1, buffer2 がEEPROMのアドレス,buffer3がデータです.ストップコンデイション云々の問題でしょうか?
ご指導お願いします.
=======
MD_STATUS put_3byte_IIC00( uint8_t s_addr, uint8_t buffer1, uint8_t buffer2, uint8_t buffer3){ MD_STATUS status; //uint8_t work1, work2; //work1 = (uint8_t) ((buffer2 >>8) & 0x00FF); //work2 = (uint8_t) (buffer2 & 0x00FF); g_write_data[0] = buffer1; /* set data1 */ g_write_data[1] = buffer2; /* set data2 */ g_write_data[2] = buffer3; /* set data3 */ /*-------------------------------------- start transmission --------------------------------------*/ status = R_IIC00_Master_Send(s_addr, (uint8_t *__near)g_write_data, 3); if( IIC_SUCCESS == status ) /* check start successfully */ { /*-------------------------------------- transmit start and wait for transmission end --------------------------------------*/ do { /* wait for transmission end */ status = R_IIC00_check_comstate(); /* get IIC status */ }while( IIC_USING == ( status & IIC_STS_MASK ) ); /* release IIC bus */ R_IIC00_StopCondition(); /* issue stop condition */ } else { /* do nothing */ } return (status); }
(追加)
順番は関係ないようです.EEPROMのアドレスの値に関係するようです.見てみます.
(追加) アドレスも関係ないようです.
チョコです。
先ほどリプライしたように、原因はEEPROM側にあるので、EEPROMへのアクセスに制限を付けるのが一番です。
256kビットのEEPROMに限定して、書き込みアドレスを16バイトごとの先頭にして、書き込むデータ数を16バイト以下に制限すれば、比較的簡単にできると思います。
部品箱にに24FC256と24LC256があったので、少し時間をもらえれば、確認はできるかと思います。
以上
チョコ様
情報ありがとうございます.
page毎のwriteを考えるとデバイスにより対応が違ってくると思いますが,一般的な64kbitあるいが256kbitに対するrandom write,random readではアドレスを2byte指定で1byte書き出し/読み取りで,かなり一般的な処理になると思います.
ご紹介いただいたr01an2828では減算処理によるwaitがありました.RL78ではclockによりその時間は変動すると思います.
10年位前ですが,78k0のKF2ではcode generateのAPIを使用してEEPROM(64Kbit)は動作しました.新しいRL78/G13で,このような問題で手間取っているのは,Renesasさんの問題だとはおもいますが,日の丸プロセッサの可用性を高めるにはこのような問題でトラブルのはよくないと思っております.
>ご紹介いただいたr01an2828では減算処理によるwaitがありました.
細かく見てないので、断定できませんが、R_IICr_SCL_TimeやR_IICr_SCL_highTimeでの処理でしょうか。
それならば、簡易IICでスタートコンディション等をソフトで発生させるための時間測定で、32MHz動作でもクロックの規格(MIN)を満足させるようになっているようです。MINの規格なので、動作クロックが32MHzより低くなってもMIN規格より長くなるだけなので気にしていないのではないでしょうか。ダミークロック出力でも同じものを使っているようですね。
>random write,random readではアドレスを2byte指定で1byte書き出し/読み取りで,かなり一般的な処理になると思います.
これが一般的かどうかは疑問ですが、1バイトの読み書きであれば、EEPROMへのアクセスでのブロックの制限はなくなります。ただし、送信したデータをEEPROMの指定されたアドレスに書き込むためにはEEPROM内でチャージポンプを起動してから書き込むのにそれなりの時間(MAXで5ms)がかかります。その時間が、1バイトごとに許されるかどうかは使い方によっても変わってくるのではないかと思います。
r01an2828を使い動作確認しました(Processorは変更したが,Code generateをしない状態で).
問題は,これを通常のCode Generateを使用しているProjectに移植することです.
Processorを変更し,32MHzからXtalを使用した20MHzに変更するため,Code generateをするとExplorerでは添付画面の左側になります.下のイメージの右側がCode Generateする前です.
Code Generate後の状態でRebuildすると添付のエラーが出ます.InterruptがCode Generateの結果重複したためだと思いますが,どこを修正すべきでしょうか?
それから,オリジナルのr_main.cにある,
R_IICr_Init(); /* initialize IICr */は,Code generate後は,コメントアウトすべきかと思いますがいかがでしょうか?
R_IICr_Initとr_cg_serial.cおよびr_cg_timer.cの内容を眺めてみましたが特にえって位置に違いはないようなので、R_IICr_Initを呼び出さなくても初期化はできそうです。ただし、R_IICr_Initは最後に
R_device_select(R1EX24016A); /* set default EEPROM parameter */
と使用するEEPROMを選択しているので、R_IICr_Initを呼び出しているところをこのEEPROM選択処理に変更することになるかと思います。
エラーが発生している割り込み関係ですが、「r_cg_timer_user.c」と「r_cg_serial_user.c」をプロジェクトから外してみてください。
ご指導ありがとうございます.
「r_cg_timer_user.c」と「r_cg_serial_user.c」をプロジェクトから外しました.Build OKです.
R_IICr_Init(); をコメントアウトせず実行すると動作OKです.
なお,Clockは,20MHzにしたつもりですが,R_IICr_Init();でいろいろ処理しているようなので,よくわかりません.
なお,device指定は,r_main.cにて,R_IICr_Init();の直後
R_device_select(R1EX24256B);
がありますので,これでdeviceが最終的に指定されます.
しかしながら,R_IICr_Init();をコメントアウトすると,
MD_STATUS R_EEPROM_wait_write()
while (g_comstatus & 0b10000000) { NOP(); /* wait for last page */ }
でステータス確認中のようで,ここから先に進みません.
以上から,R_IICr_Init(); はMUSTでしょうか?Code Generateと同じようなことをしていると思っています.IIC00noClockは400Kbpsですので,20MHz Clockが正しければ,この速度が設定されていると思っています.
1か所見落としていました。
R_IICr_Init(); の中に以下の処理があり、これで初期化後に送信可能な状態にしていました。
この処理を「R_device_select」を呼び出す前にでも追加してください。
動きました!!
ありがとうございました!!
Code Generate された,
void R_Systeminit(void){ PIOR = 0x00U; R_CGC_Create(); R_PORT_Create(); R_SAU0_Create(); R_TAU0_Create(); IAWCTL = 0x00U;}
をそのまま使用しています.
R_IICr_Init();はコメントアウト,
さらにご指摘いただいた
SCRmn |= 0b1000000000000000; /* set TxE00 */
を, R_device_selectの前に,追加しました.
この機会にお聞きしたいのですが,書き込みと読み出しの間には,5ms程度のwaitが無いようですが,内部的にはEEPROM書き込み後のチェックは行われているのですね?
まだ、そこまではプログラムを完全には読み切れていません。
今までで読めた範囲では、ブロックの書き込み後にTM02を起動して、100μsのタイマを起動し、INTTM02でスタートコンディションの発行とスレーブアドレスを送信している(これが書き込み完了のポーリング)ようなので、5msの固定時間を待つのではなく、100usごとに書き込み完了をポーリングしているようです。
実際に、INTIICrでのエラー検出時の処理の中でステータス(g_comstatus)がAFT_TX以外でエラー処理をしていることからスピードを追究した処理方法をとっていると思われます。
何しろ、割り込み処理の中で色々と操作しているので完全には追い切れていません。
書き込んだデータそのものであれば、main関数の方でデータの読み出しを行っているので、そこらでわかると思います。
書き込んだデータはその値を読み出しバイト単位に確認しています.問題ない状態です.EEPROMは,ありきたりのATMELの256Kbitのものです.本日の結果を踏まえ,これでアプリケーションの作成に移ることができます.
ありがとうございました.
ご連絡有難うございました。
いよいよ、アプリの作成ですか。頑張ってください。