アプリ版:「スタンプのみでお礼する」機能のリリースについて

組み込み開発に携わってまだ日の浅い者ですので
質問の内容もわかりにくいかと思いますがよろしくお願いいたします。

ルネサス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,
UINTnumWords
)
{
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;
}

A 回答 (6件)

お手持ちの基板の回路図を確認してみて下さい。


FlashのA0がSHのA1に接続されていませんか?

この場合、最初のコマンド発行を例に挙げますと、
リニアアドレス0x555へ書き込んだつもりでも
デバイスにとっては0x2AAにライトアクセスが
発生したとしか受け取ってもらえません。

0xAAAへ書き込むことでデバイスに
対して0x555へのライトアクセスを発行することができます。

データシートにバイトアクセス用のプログラムコマンドが
記述してありますので、そちらのご利用を。

また、連続書き込みの為には、書き込みの完了を待たねばなりません。
デバイスが書き込み中の場合、リードアクセスの度に
トグルするビットがありますので、2度読みして同一の値が取得できたら完了と判断するのが実装が簡単です。
(少々手抜きですが、テストには十分)

とりあえず、最低限直さねばならないトコだけ。
引っかかり易いところなので、確認してみて下さい。

この回答への補足

回答ありがとうございます。
ユーザー先でネットが使えない環境だったので
返答遅れてしまい申し訳ありません。

基板の回路図はみたことがない(^^ゞ
ので見させてもらえるように聞いてみます。

>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などないでしょうか?

>また、連続書き込みの為には、書き込みの完了を
>待たねばなりません。
この件は了解しました。

補足日時:2007/12/12 10:11
    • good
    • 0

#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章の後半辺りが今一番お知りになりたい項目かと思います。

リード・サイクル・タイミング
ライト・サイクル・タイミング
フラッシュ・メモリ・コマンド
フラッシュ・メモリのステータス
    • good
    • 0
この回答へのお礼

ご親切にありがとうございました(ToT)
なんとなくですが、意味が把握できました。
次はEEPROMのコーディングなのでお勧めしていただいた本を早速、
仕事帰りにでも見に行きます。

お礼日時:2007/12/13 10:12

状況が把握しにくいので、何ともいえませんね。


やはり確実なのは、ロジアナか何かで波形を調べた方がよいと思います。

あと、ハードウェアの問題の可能性もあるので、念のため、そちらも調べた方がよいと思います。案外、ライトイネーブルになっていなかっただけとかいう落ちかもしれませんし。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
ユーザー先でネットが使えない環境だったので
返答遅れてしまい申し訳ありません。
あれから、ハード側のエンジニアに見ていただいたところ
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);

お礼日時:2007/12/12 10:06

No.2 ですが、お手上げです。



あとは、マイコン側が確かに、WORD で(データ16本で)アクセスするモードになっているかとか、フラッシュメモリの OE 端子はうまくコントロールできているかとか、そのあたりしか思いつきません。

あと、ICE の併用ですが、もしかしたら、ステップ実行の間に、別のアドレスをアクセスしたりしているかもしれません。
その間、フラッシュメモリの、CE が毎回無効にになるので、フラッシュメモリ側では、一連のシーケンスとして認識していないという可能性はあります。

この場合、ブレークポイントを設定するのではなく、書き込んだ後に無限ループをつくっておいて、フラッシュメモリへの書き込みが充分終わった頃に、手動でブレークさせて様子を見ると良いかもしれません。
    • good
    • 0

「うまく書き込むことができない」という質問をされるときには、


・全く書けない
・変なデータが書ける
・所々正解だが他のところは書けない
などの症状を合わせてお問い合わせになることをお勧めします。

そして、もしも、最後の「所々正解」であれば、データシートにある、DQ7:Data# ポーリング という処理が抜けているからかなと思います。
書き込み完了を待ってから、次のライトコマンドを出さないと、だめなようです。

この回答への補足

回答ありがとうございます。
補足させていただきますと全く書けない状態です。
現在ICEを用いてステップ実行しながらデバッグしているのですが、コマンド送信->データ書き込みのプログラムのあとでブレークで止めた状態でメモリを確認しています。
ですので、とりあえず2バイトデータが書き込むことができるのかだけ確認したかったので、ポーリングはまだ書いていない状況です。
ステップ実行しながら、やってもよいのかよく分かっていないのですが。。。
(^_^;)

補足日時:2007/12/10 16:58
    • good
    • 0

この型版の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までの間隔を全くコントロールしていませんが、大丈夫でしょうか?
おそらく有効な時間間隔が定められているはずですので、仕様書をもう一度よく読みなおしてください。
    • good
    • 0
この回答へのお礼

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

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では普通制御するものなのでしょうか?
ちなみにどのように制御するものなのでしょうか?

お礼日時:2007/12/10 14:52

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!