- ベストアンサー
FlashROMにデータを書き込むには?(組み込み開発初心者)
組み込み開発に携わってまだ日の浅い者ですので 質問の内容もわかりにくいかと思いますがよろしくお願いいたします。 ルネサスMPU(sh)でFlashROM(S29JL064H) http://www.spansion.com/jp/products/S29JL064H.html にデータを書き込むための以下の関数を作成したのですが うまく書き込むことができず困っています。 FlashROMのデータシートでは0xAA、0x55、0xA0のWriteコマンドを 送ってからデータを2バイト書き込むことができるとあったので そのようにしたつもりなのですが、書き込むことができません。 この場合、どのような対処をするものなのでしょうか? また、サンプルや参考になるHPがあれば教えてください。 #define FRM_START_ADDRS (0x02000000) #define FRM_WRITE_CMD(address,data) *((WORD16*)(address)) = (data) INT hFRM_Write( WORD16 *srcAddr, WORD16 *dstAddr, UINT numWords ) { UINT count; for(count=0; count < numWords; count++) { if( *dstAddr != 0xFFFF) // 領域がクリアされていることを確認する return FRM_NOT_ERASED; FRM_WRITE_CMD(FRM_START_ADDRS + 0x555,0xAA); FRM_WRITE_CMD(FRM_START_ADDRS + 0x2AA,0x55); FRM_WRITE_CMD(FRM_START_ADDRS + 0x555,0xA0); *dstAddr = *srcAddr; dstAddr++; srcAddr++; } return FRM_OK; }
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
お手持ちの基板の回路図を確認してみて下さい。 FlashのA0がSHのA1に接続されていませんか? この場合、最初のコマンド発行を例に挙げますと、 リニアアドレス0x555へ書き込んだつもりでも デバイスにとっては0x2AAにライトアクセスが 発生したとしか受け取ってもらえません。 0xAAAへ書き込むことでデバイスに 対して0x555へのライトアクセスを発行することができます。 データシートにバイトアクセス用のプログラムコマンドが 記述してありますので、そちらのご利用を。 また、連続書き込みの為には、書き込みの完了を待たねばなりません。 デバイスが書き込み中の場合、リードアクセスの度に トグルするビットがありますので、2度読みして同一の値が取得できたら完了と判断するのが実装が簡単です。 (少々手抜きですが、テストには十分) とりあえず、最低限直さねばならないトコだけ。 引っかかり易いところなので、確認してみて下さい。
その他の回答 (5)
- bug_bug
- ベストアンサー率78% (36/46)
#5 です。 > だから、以下のようにビットシフトしなければいけないということなのでしょうか? 正解です。 デバイスのマッピングされているベースアドレスは無視して考えてみると、 (1)ファームウェアでアドレスを1ビットシフトしてあげます。 (2)その結果、A11-A0に乗ってた0x555というアドレス指定がA12-A1にスライドされます。 (3)CPUのA12-A1はデバイスのA11-A0に物理的に接続されています。 (4)最終的にデバイスは0x555というアドレス指定を受け付けることができます。 という話の流れです。 HPはなかなか見つからないかと思いますので 一番自分の力になった覚えのある本を紹介します。 桑野 雅彦 著 メモリICの実践活用法 http://www.cqpub.co.jp/hanbai/books/32/32701.htm おそらく、2章の後半辺りが今一番お知りになりたい項目かと思います。 リード・サイクル・タイミング ライト・サイクル・タイミング フラッシュ・メモリ・コマンド フラッシュ・メモリのステータス
お礼
ご親切にありがとうございました(ToT) なんとなくですが、意味が把握できました。 次はEEPROMのコーディングなのでお勧めしていただいた本を早速、 仕事帰りにでも見に行きます。
- jacta
- ベストアンサー率26% (845/3158)
状況が把握しにくいので、何ともいえませんね。 やはり確実なのは、ロジアナか何かで波形を調べた方がよいと思います。 あと、ハードウェアの問題の可能性もあるので、念のため、そちらも調べた方がよいと思います。案外、ライトイネーブルになっていなかっただけとかいう落ちかもしれませんし。
お礼
回答ありがとうございます。 ユーザー先でネットが使えない環境だったので 返答遅れてしまい申し訳ありません。 あれから、ハード側のエンジニアに見ていただいたところ MPUレジスタの設定に間違いがあったとのことでした。 (すいません、詳細わからなくて。。。) それで書き込みはできるようになったのですが、 ハード側のエンジニアの方からFROMは16ビットモードで 使用するので、0x555だと奇数アドレスなのでコマンドを 送るアドレスをビットシフトしなければならないといわれました。 その為、コードを以下のように書き直すことになったのですが なぜビットシフトしないといけないのでしょうか? FRM_WRITE_CMD(FRM_START_ADDRS + ((0x555)<<1),0xAA); FRM_WRITE_CMD(FRM_START_ADDRS + ((0x2AA)<<1),0x55); FRM_WRITE_CMD(FRM_START_ADDRS + ((0x555)<<1),0xA0);
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
No.2 ですが、お手上げです。 あとは、マイコン側が確かに、WORD で(データ16本で)アクセスするモードになっているかとか、フラッシュメモリの OE 端子はうまくコントロールできているかとか、そのあたりしか思いつきません。 あと、ICE の併用ですが、もしかしたら、ステップ実行の間に、別のアドレスをアクセスしたりしているかもしれません。 その間、フラッシュメモリの、CE が毎回無効にになるので、フラッシュメモリ側では、一連のシーケンスとして認識していないという可能性はあります。 この場合、ブレークポイントを設定するのではなく、書き込んだ後に無限ループをつくっておいて、フラッシュメモリへの書き込みが充分終わった頃に、手動でブレークさせて様子を見ると良いかもしれません。
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
「うまく書き込むことができない」という質問をされるときには、 ・全く書けない ・変なデータが書ける ・所々正解だが他のところは書けない などの症状を合わせてお問い合わせになることをお勧めします。 そして、もしも、最後の「所々正解」であれば、データシートにある、DQ7:Data# ポーリング という処理が抜けているからかなと思います。 書き込み完了を待ってから、次のライトコマンドを出さないと、だめなようです。
補足
回答ありがとうございます。 補足させていただきますと全く書けない状態です。 現在ICEを用いてステップ実行しながらデバッグしているのですが、コマンド送信->データ書き込みのプログラムのあとでブレークで止めた状態でメモリを確認しています。 ですので、とりあえず2バイトデータが書き込むことができるのかだけ確認したかったので、ポーリングはまだ書いていない状況です。 ステップ実行しながら、やってもよいのかよく分かっていないのですが。。。 (^_^;)
- jacta
- ベストアンサー率26% (845/3158)
この型版のFlashROMは直接触ったことがありませんし、ご提示の処理以外の部分に問題がないともいえないのですが... > #define FRM_WRITE_CMD(address,data) *((WORD16*)(address)) = (data) > WORD16 *dstAddr, 少なくとも上記二箇所には問題があります(多分)。 というのも、型を単なるWORD16ではなくvolatile WORD16にする必要があります。(WORD16の定義にvolatile修飾が含まれていれば話は別です) volatileがないと、3回実行しているFRM_WRITE_CMDは、最適化によって1回になってしまうかもしれませんし、*destAddrへの書き込みとFRM_WRITE_CMDの順序が入れ替わる可能性もあります。 もう一点、FRM_WRITE_CMDの間隔とFRM_WRITE_CMDから*destまでの間隔を全くコントロールしていませんが、大丈夫でしょうか? おそらく有効な時間間隔が定められているはずですので、仕様書をもう一度よく読みなおしてください。
お礼
早速、回答ありがとうございます。 volatileをいれてませんでしたので、以下のようにして実行しましたがダメでした。 typedef volatile unsigned short WORD16; // 2 bytes >もう一点、FRM_WRITE_CMDの間隔とFRM_WRITE_CMDから*destまでの間隔 FRM_WRITE_CMDの間隔とは FRM_WRITE_CMD(FRM_START_ADDRS + 0x555,0xAA); ★ここ FRM_WRITE_CMD(FRM_START_ADDRS + 0x2AA,0x55); ★ここ FRM_WRITE_CMD(FRM_START_ADDRS + 0x555,0xA0); ★の部分にタイミングを計るコードを書くということでしょうか? FRM_WRITE_CMDから*destまでの間隔とは FRM_WRITE_CMD(FRM_START_ADDRS + 0x555,0xA0); ★ここ *dstAddr = *srcAddr; ★の部分にタイミングを計るコードを書くということでしょうか? 一応、参考にするように言われた前のソースを 元にコーディングしていたのですが そちらの方でも間隔を制御するようなことはしてなかったのですが FROMでは普通制御するものなのでしょうか? ちなみにどのように制御するものなのでしょうか?
補足
回答ありがとうございます。 ユーザー先でネットが使えない環境だったので 返答遅れてしまい申し訳ありません。 基板の回路図はみたことがない(^^ゞ ので見させてもらえるように聞いてみます。 >0xAAAへ書き込むことでデバイスに >対して0x555へのライトアクセスを発行することができます。 回答No4の返答で書かせていただきましたが、 だから、以下のようにビットシフトしなければいけないということなのでしょうか? FRM_WRITE_CMD(FRM_START_ADDRS + ((0x555)<<1),0xAA); FRM_WRITE_CMD(FRM_START_ADDRS + ((0x2AA)<<1),0x55); FRM_WRITE_CMD(FRM_START_ADDRS + ((0x555)<<1),0xA0); こんなことも知らないのか?と怒られそうですが このリニアアドレス、ライトアクセスがよくわかってません。 もし、ご存知でしたら参考になるようなHPなどないでしょうか? >また、連続書き込みの為には、書き込みの完了を >待たねばなりません。 この件は了解しました。