2024年6月24日月曜日

spartan3をCPUから「slave serial mode」でconfigする(4)

XC3S50-4VQ100Cのconfigを自分でやる件です.(config ROMを使わずに)

前回は.binの作り方を説明しました.

作業手順的に、次にやるのはSerial FLASH W25Q32に.binを焼く作業です.HDD上の.binをFLASHの先頭からそのまま書きます.
↓現物はこんなです.FLASHはarduinoの下に隠れています.

↓回路図(pdf) Arduino nanoとW25Q32の部分だけです.上の現物写真の右側の基板.to FPGAの先にFPGA基板を取り付けます.FPGAの回路図は次回公開します.

FLASH焼き動作の骨子はこうなってます.
・ArduinoのUSB(COM port)でPCへ接続する
・PCはterminal softのTeraTermをつかう
・TeraTermに.binをbinary送信させる
・Arduinoは受信した.binを256bytes貯まった都度W25Q32にpage writeする
・ArduinoはFLASHを消去したり、FLASHをdumpする機能も持つ

もう少し細かいこと.受信bufferについて.
・256byteの受信bufferを2本用意して交互に切り替えて使う
・COM portて届いたdataを受信bufferに積み積みする
・256byte貯まったらFLASHへpage writeする
・FLASHの256byte page writeに要する時間は2mSec(実測)
・PCとCOM portの接続速度は9600bpsにする
・9600bpsで256byte受信するには250mSecぐらいかかる
・250mSec >> 2mSec なのでFLASH page writeが邪魔されない

Arduino sourceを置きます(zip)

FLASHを焼く操作はこうします.
1)TeraTermで「e」と打つ =FLASH全域消去
2)TeraTermで「f」と打つ =.binをFLASHに焼く
3)20秒以内に.binをバイナリ送信する
4)2分ぐらい待つと終わる

ーーーー
以下はsourceの簡単な説明.

PCコマンドの処理は、いつものloop関数からPCcommand()を読んでます.
void loop() {
  PCcommand();
}

PCcommand()の中で各種コマンド分岐します.fの場合は、、、
switch(c[0]){
  case 'f': // flash write
    Serial.print("flash write mode. .........bin in 20Sec\n");
    mode='f';
    bufsel = 0;  2本のbufferの切り替え
    fileptr = 0;  .binの先頭からのbyte counter
    TIM2cnt_filetrans_start_timeout=20; // 20Sec timer
    break;

flashWrite()で.bin受信とFLASH焼きをやります.
やってることは、256byte溜まったらbuffer切り替えしてFLASHに焼きます.
.bin file末尾では半端なサイズがbufferに残ります.
そこで受信が停まって10秒待ってtimeoutしたら、残をFLASH焼きします.
詳しくはsourceを見てちょ.

ーーーー
次の話題はFLASH W25Q32のコマンドについて.

大雑把にこの3種類の形式です.
 コマンド       例:全域消去
 コマンド+データ   例:status read
 コマンド+アドレス+データ  例:read/write

よく使うコマンドは、、、
 #define WR_EN   6
 #define CHIP_ERASE    0xC7
 #define PAGE_PROG    2
 #define RD_DATA    3

page writeはこんな風にします.
WEN→CS→write command→A[23:0]→data[7:0]→xCS→wait busy
void W25Q_writePage(long adrs, byte *data, int length){
  W25Q_command(WR_EN,0); // write enable command
  digitalWrite(slaveSelectPin, LOW);
  SPI.transfer(PAGE_PROG); // page write command
  SPI.transfer(adrs>>16);
  SPI.transfer(adrs>>8);
  SPI.transfer(adrs);
  byte *d;
  d = data;
  for(int i=0; i<length; i++)  SPI.transfer(*d++);
  digitalWrite(slaveSelectPin, HIGH);
  W25Q_waitBusy(); // loop during busy
}

全域消去はこんなです.
WEN→CS→erase command→xCS→wait busy
void W25Q_eraseChip(void){
  W25Q_command(WR_EN,0); // write enable
  digitalWrite(slaveSelectPin, LOW);
  SPI.transfer(CHIP_ERASE);
  digitalWrite(slaveSelectPin, HIGH);
  W25Q_waitBusy(); // loop during busy
}

詳しくはsourceを見てちょ.

説明ってこんなところかな.今朝はここまでにしとうございます.

3へ    5へ

かしこ

0 件のコメント:

コメントを投稿