SSTフラッシュメモリー

Microchip社のSSTフラッシュメモリー 
型番:SST25VF032B
容量:32MBit

・インターフェースはSPI
・Microchip社のSPI EEPROM 25XXシリーズと比べて
  -書き込み速度は非常に高速
   25XXシリーズは書き込み時に5msもWaitが必要になるがこれは10μs
  -書き込みのシーケンスはだいぶ異なる
   複数バイトまとめて書き込むときの手順がかなり変則的
  -ピン配列は完全互換
  -寿命は1桁小さい
  -容量が大きく価格は安い
   容量32Mビット(=4Mバイト)で約¥200
   64Mビットの物が最大
  -データを上書きする場合は一旦消去してから上書きする必要がある
   消去しなくても書き込みシーケンスは実行できるが正しく書き込めない
   消去に時間がかかるのが欠点。約25ms必要
  -8MbitのSST25VF080BのみDIPパッケージがある
   他は足ピッチ1.27mmのSOICパッケージ(これ以外のパッケージもあるがSOICでないと半田付け困難)
・SDカードは電力大食いだがこれは低消費電力
 arduinoFT232の3.3Vで動作可能
・電源電圧は3.3Vなので5Vの回路で使用するときはレベル変換が必要
 3.3Vの回路ならMPUと直結で良い
・消去はチップ全体、4Kバイトセクター、32K,64Kブロックで可能
 消去によりデータは0xFFに初期化される
 書き込みによりビットのクリヤは出来るがセットが出来ないので消去により全ビットをセットする必要がある
・このメモリーはSilicon Storage Technology社の技術が使用されている。データシートの体裁も他のMicrochip社製品と異なる。
・購入はMicrochipDirectやDigi-Key


2013-10-24

レベル変換に東芝74LCX32を使用。

R0018857.jpg

arduinoでのテスト

R0018868.jpg

SOICパッケージ

実験回路の回路図。74LCX32のピン番号は正しくない。変換基板を使用している都合上ずれているので注意!!
左下のP$7,P$16は74LCX32の電源ピン。回路図上の「7432AE」は特に意味なし
フラッシュメモリーのSO(2番ピン)はarduinoと直結で良いが(たぶん)OR回路が余っているので使っている
OR回路を使用しているがバッファーの方がシンプルになる。ANDを使用したりインバーターを2段直列にしても良い。部品の入手性や価格で判断する。

kairozu.PNG
テストプログラム
0001  //----------------------------------------------------------------- 2013-10-24 ------------
0002 // Microchip SST25VF032B 32Mbitフラッシュメモリーテストプログラム
0003 //
0004 // SSTMem arduino pin No
0005 // -------- --------------
0006 // 1 CS 10
0007 // 2 SO 12 MISO
0008 // 3 WP 3.3V
0009 // 4 GND GND
0010 // 5 SI 11 MOSI
0011 // 6 SCK 13 SCK
0012 // 7 HOLD 3.3V
0013 // 8 VCC 3.3V
0014 //-------------------------------------------------------- written by iizuka --------------
0015 #include <SPI.h>
0016
0017 // EEPROM関連
0018 #define SST_CS 10 // SSTメモリーのCSピン番号
0019 #define SST_SO 12 // SSTメモリーのCSピン番号
0020
0021 //--------------- 型変換の共用体定義 -----------------------------
0022 typedef union {
0023 unsigned long long_val;
0024 struct {
0025 byte LL; // Lower address
0026 byte ML;
0027 byte MH;
0028 byte HH; // Higher address
0029 } byte_val;
0030 } type_convert_long_byte;
0031
0032 //------------------------------------------------------------------------------------------
0033 // SST Memory write enable
0034 //------------------------------------------------------------------------------------------
0035 void WREN( void )
0036 {
0037 digitalWrite( SST_CS , LOW );
0038 SPI.transfer( 0x06 );
0039 digitalWrite( SST_CS , HIGH );
0040 }
0041
0042 //------------------------------------------------------------------------------------------
0043 // SST Memory write disable
0044 //------------------------------------------------------------------------------------------
0045 void WRDI( void )
0046 {
0047 digitalWrite( SST_CS , LOW );
0048 SPI.transfer( 0x04 );
0049 digitalWrite( SST_CS , HIGH );
0050 }
0051
0052 //------------------------------------------------------------------------------------------
0053 // Chip-Erase メモリーの内容は 0xFF に初期化される
0054 //------------------------------------------------------------------------------------------
0055 void chip_erase( void )
0056 {
0057 Serial.println("Chip-Erase start");
0058 WREN();
0059 digitalWrite( SST_CS , LOW );
0060 SPI.transfer( 0x60 );
0061 digitalWrite( SST_CS , HIGH );
0062 WRDI();
0063 while( device_busy() ) {}
0064 Serial.println("Chip-Erase end");
0065 }
0066
0067 //------------------------------------------------------------------------------------------
0068 // 4kbyte(=0x1000) Sector-Erase
0069 //------------------------------------------------------------------------------------------
0070 void sector_erase( unsigned long addr )
0071 {
0072 type_convert_long_byte sst_addr;
0073 sst_addr.long_val = addr;
0074
0075 Serial.println("Sector-Erase start");
0076 WREN();
0077 digitalWrite( SST_CS , LOW );
0078 SPI.transfer( 0x20 );
0079 SPI.transfer( sst_addr.byte_val.MH );
0080 SPI.transfer( sst_addr.byte_val.ML );
0081 SPI.transfer( sst_addr.byte_val.LL );
0082 digitalWrite( SST_CS , HIGH );
0083 WRDI();
0084 while( device_busy() ) {}
0085 Serial.println("Sector-Erase end");
0086 }
0087
0088 //------------------------------------------------------------------------------------------
0089 // 32kbyte(=0x8000) Block-Erase
0090 //------------------------------------------------------------------------------------------
0091 void blockr_erase_32k( unsigned long addr )
0092 {
0093 type_convert_long_byte sst_addr;
0094 sst_addr.long_val = addr;
0095
0096 Serial.println("Block-Erase 32k start");
0097 WREN();
0098 digitalWrite( SST_CS , LOW );
0099 SPI.transfer( 0x52 );
0100 SPI.transfer( sst_addr.byte_val.MH );
0101 SPI.transfer( sst_addr.byte_val.ML );
0102 SPI.transfer( sst_addr.byte_val.LL );
0103 digitalWrite( SST_CS , HIGH );
0104 WRDI();
0105 while( device_busy() ) {}
0106 Serial.println("Block-Erase 32k end");
0107 }
0108
0109 //------------------------------------------------------------------------------------------
0110 // 64kbyte(=0x10000) Block-Erase
0111 //------------------------------------------------------------------------------------------
0112 void blockr_erase_64k( unsigned long addr )
0113 {
0114 type_convert_long_byte sst_addr;
0115 sst_addr.long_val = addr;
0116
0117 Serial.println("Block-Erase 64k start");
0118 WREN();
0119 digitalWrite( SST_CS , LOW );
0120 SPI.transfer( 0xD8 );
0121 SPI.transfer( sst_addr.byte_val.MH );
0122 SPI.transfer( sst_addr.byte_val.ML );
0123 SPI.transfer( sst_addr.byte_val.LL );
0124 digitalWrite( SST_CS , HIGH );
0125 WRDI();
0126 while( device_busy() ) {}
0127 Serial.println("Block-Erase 64k end");
0128 }
0129
0130 //------------------------------------------------------------------------------------------
0131 // SST Memoryから読み出す 
0132 //------------------------------------------------------------------------------------------
0133 void sst_read( unsigned long addr, byte data[], byte len )
0134 {
0135 byte index;
0136 type_convert_long_byte sst_addr;
0137
0138 digitalWrite( SST_CS , LOW );
0139 SPI.transfer( 0x03 ); // 25MHz Read
0140 sst_addr.long_val = addr;
0141
0142 SPI.transfer( sst_addr.byte_val.MH );
0143 SPI.transfer( sst_addr.byte_val.ML );
0144 SPI.transfer( sst_addr.byte_val.LL );
0145 for( index = 0 ; index < len ; index++ ) {
0146 data[index] = SPI.transfer(0);
0147 }
0148 digitalWrite( SST_CS , HIGH );
0149 }
0150
0151 //------------------------------------------------------------------------------------------
0152 // SST Memoryから1バイト読み出す 
0153 //------------------------------------------------------------------------------------------
0154 byte sst_read_byte( unsigned long addr )
0155 {
0156 type_convert_long_byte sst_addr;
0157 byte data;
0158
0159 digitalWrite( SST_CS , LOW );
0160 SPI.transfer( 0x03 ); // 25MHz Read
0161 sst_addr.long_val = addr;
0162
0163 SPI.transfer( sst_addr.byte_val.MH );
0164 SPI.transfer( sst_addr.byte_val.ML );
0165 SPI.transfer( sst_addr.byte_val.LL );
0166 data = SPI.transfer(0);
0167 digitalWrite( SST_CS , HIGH );
0168
0169 return data;
0170 }
0171
0172 //------------------------------------------------------------------------------------------
0173 // SST Memoryに1バイト書き込む 
0174 //------------------------------------------------------------------------------------------
0175 void sst_write_byte( unsigned long addr, byte data )
0176 {
0177 unsigned long index;
0178 type_convert_long_byte sst_addr;
0179
0180 WREN();
0181 digitalWrite( SST_CS , LOW );
0182 SPI.transfer( 0x02 );
0183 sst_addr.long_val = addr;
0184 SPI.transfer( sst_addr.byte_val.MH );
0185 SPI.transfer( sst_addr.byte_val.ML );
0186 SPI.transfer( sst_addr.byte_val.LL );
0187 SPI.transfer( data );
0188 digitalWrite( SST_CS , HIGH );
0189 WRDI();
0190 while( device_busy() ) {}
0191 }
0192
0193 //------------------------------------------------------------------------------------------
0194 // SST Memoryに書き込む
0195 // arduinoでは実効速度が遅く通信速度がネックにならないためこの方法は速くならない
0196 //------------------------------------------------------------------------------------------
0197 void sst_write_word_HW( unsigned long addr, byte data[], byte len )
0198 {
0199 byte index;
0200 byte index_ad;
0201 type_convert_long_byte sst_addr;
0202
0203 EBSY();
0204 WREN();
0205 digitalWrite( SST_CS , LOW );
0206 SPI.transfer( 0xAD );
0207 sst_addr.long_val = addr;
0208 SPI.transfer( sst_addr.byte_val.MH );
0209 SPI.transfer( sst_addr.byte_val.ML );
0210 SPI.transfer( sst_addr.byte_val.LL );
0211 index_ad = 0;
0212 for( index = 0 ; index < len ; index++ ) {
0213 if( index_ad == 2 ) {
0214 digitalWrite( SST_CS , HIGH );
0215 digitalWrite( SST_CS , LOW );
0216 while( digitalRead( SST_SO ) == LOW ) {}
0217 digitalWrite( SST_CS , HIGH );
0218 digitalWrite( SST_CS , LOW );
0219 SPI.transfer( 0xAD );
0220 index_ad = 0;
0221 }
0222 SPI.transfer( data[index] );
0223 index_ad++;
0224 }
0225 digitalWrite( SST_CS , HIGH );
0226 digitalWrite( SST_CS , LOW );
0227 while( digitalRead( SST_SO ) == LOW ) {}
0228 digitalWrite( SST_CS , HIGH );
0229 digitalWrite( SST_CS , LOW );
0230 WRDI();
0231 DBSY();
0232 while( device_busy() ) {}
0233 }
0234
0235 //------------------------------------------------------------------------------------------
0236 // SST Memoryに書き込む 
0237 //------------------------------------------------------------------------------------------
0238 void sst_write_word_SW( unsigned long addr, byte data[], byte len )
0239 {
0240 byte index;
0241 byte index_ad;
0242 type_convert_long_byte sst_addr;
0243
0244 WREN();
0245 digitalWrite( SST_CS , LOW );
0246 SPI.transfer( 0xAD );
0247 sst_addr.long_val = addr;
0248 SPI.transfer( sst_addr.byte_val.MH );
0249 SPI.transfer( sst_addr.byte_val.ML );
0250 SPI.transfer( sst_addr.byte_val.LL );
0251 index_ad = 0;
0252 for( index = 0 ; index < len ; index++ ) {
0253 if( index_ad == 2 ) {
0254 digitalWrite( SST_CS , HIGH );
0255 while( device_busy() ) {}
0256 digitalWrite( SST_CS , LOW );
0257 SPI.transfer( 0xAD );
0258 index_ad = 0;
0259 }
0260 SPI.transfer( data[index] );
0261 index_ad++;
0262 }
0263 digitalWrite( SST_CS , HIGH );
0264 while( device_busy() ) {}
0265 WRDI();
0266 while( device_busy() ) {}
0267 }
0268
0269 //------------------------------------------------------------------------------------------
0270 // AAI書き込みのためSOピンによるステータス出力を可能にする
0271 //------------------------------------------------------------------------------------------
0272 void EBSY(void)
0273 {
0274 digitalWrite( SST_CS , LOW );
0275 SPI.transfer( 0x70 );
0276 digitalWrite( SST_CS , HIGH );
0277 }
0278
0279 //------------------------------------------------------------------------------------------
0280 // AAI書き込みのためSOピンによるステータス不可にする
0281 //------------------------------------------------------------------------------------------
0282 void DBSY(void)
0283 {
0284 digitalWrite( SST_CS , LOW );
0285 SPI.transfer( 0x80 );
0286 digitalWrite( SST_CS , HIGH );
0287 }
0288
0289 //------------------------------------------------------------------------------------------
0290 // status registerを読み出す
0291 //------------------------------------------------------------------------------------------
0292 byte RDSR(void)
0293 {
0294 byte data;
0295
0296 digitalWrite( SST_CS , LOW );
0297 SPI.transfer( 0x05 );
0298 data = SPI.transfer( 0x00 );
0299 digitalWrite( SST_CS , HIGH );
0300
0301 return data;
0302 }
0303
0304 //------------------------------------------------------------------------------------------
0305 // device busy検査
0306 //------------------------------------------------------------------------------------------
0307 boolean device_busy(void)
0308 {
0309 if( (RDSR() & 0x01) == 0x01 ) {
0310 // Serial.println("BUSY");
0311 return true;
0312 } else {
0313 return false;
0314 }
0315 }
0316
0317 //------------------------------------------------------------------------------------------
0318 // status registerに書き込む
0319 //------------------------------------------------------------------------------------------
0320 void WRSR(byte reg_data)
0321 {
0322 WREN();
0323 digitalWrite( SST_CS , LOW );
0324 SPI.transfer( 0x01 );
0325 SPI.transfer( reg_data );
0326 digitalWrite( SST_CS , HIGH );
0327 }
0328
0329 //------------------------------------------------------------------------------------------
0330 // SST Memoryの WriteProtect を解除する
0331 //------------------------------------------------------------------------------------------
0332 void device_protect_disable()
0333 {
0334 WRSR( 0b00000000 );
0335 }
0336
0337 //------------------------------------------------------------------------------------------
0338 // SST Memoryの WriteProtect を設定する
0339 //------------------------------------------------------------------------------------------
0340 void device_protect_enable()
0341 {
0342 WRSR( 0b10111100 );
0343 }
0344
0345 //------------------------------------------------------------------------------------------
0346 // arduino setup
0347 //------------------------------------------------------------------------------------------
0348 void setup()
0349 {
0350 pinMode(SST_CS, OUTPUT);
0351 pinMode(SST_SO, INPUT );
0352 digitalWrite( SST_CS , HIGH ); // disable SST Memory
0353
0354 delay(1000);
0355
0356 SPI.begin();
0357 // SPI.setClockDivider( SPI_CLOCK_DIV128 ); // オシロスコープで波形を見るときはクロックを遅くすると良い
0358 // SPI.setBitOrder( MSBFIRST ); // デフォルトでMSBFIRSTなので無くてもあっても良い
0359 // SPI.setDataMode( SPI_MODE0 ); // これもデフォルト設定なのであっても無くても良い
0360
0361 Serial.begin(57600);
0362
0363 Serial.println("--------- TEST START ------------");
0364 device_protect_disable();
0365 chip_erase();
0366 }
0367
0368 //------------------------------------------------------------------------------------------
0369 // arduino loop
0370 //------------------------------------------------------------------------------------------
0371 void loop()
0372 {
0373 byte data_w;
0374 byte data_r;
0375 unsigned long addr;
0376 byte data_array_w[16];
0377 byte data_array_r[16];
0378 unsigned long tm;
0379
0380 randomSeed(analogRead(0));
0381
0382 //------ 1バイト単位の読み書き ------------------------------------------
0383 Serial.println("--------- TEST 1 ---------------");
0384 Serial.println("byte write/read start");
0385 tm = millis();
0386 for( addr = 0x0 ; addr < 0x20000 ; addr++ ) { // 約30秒かかる
0387 data_w = random(0,255); // この処理は遅い
0388 sst_write_byte( addr, data_w );
0389 data_r = sst_read_byte(addr);
0390 if( data_w != data_r ) {
0391 Serial.print("error addr="); Serial.print(addr,HEX);
0392 Serial.print(" write data="); Serial.print(data_w,HEX);
0393 Serial.print(" read data=" ); Serial.print(data_r,HEX); Serial.println("");
0394 }
0395 }
0396 Serial.print("byte write/read end");
0397 Serial.print(" Time:"); Serial.print((millis() - tm )/1000); Serial.println("sec");
0398
0399 //------ AAIモード書き込み ソフトウェアによるBUSY判定 -------------------
0400 Serial.println("--------- TEST 2 ---------------");
0401 Serial.println("S/W array write/read start");
0402 for( byte i = 0 ; i < 16 ; i++ ) {
0403 data_array_w[i] = random(0,255);
0404 }
0405 tm = millis();
0406 for( addr = 0x20000 ; addr < 0x40000 ; addr += 16 ) {
0407 sst_write_word_HW( addr, data_array_w, 16 );
0408 sst_read( addr, data_array_r, 16 );
0409 for( byte i = 0 ; i < 16 ; i++ ) {
0410 if( data_array_w[i] != data_array_r[i] ) {
0411 Serial.print("error addr="); Serial.print(addr,HEX);
0412 Serial.print(" index="); Serial.print(i);
0413 Serial.print(" write data="); Serial.print(data_array_w[i],HEX);
0414 Serial.print(" read data=" ); Serial.print(data_array_r[i],HEX); Serial.println("");
0415 }
0416 }
0417 }
0418 Serial.print("S/W array write/read end");
0419 Serial.print(" Time:"); Serial.print((millis() - tm )/1000); Serial.println("sec");
0420
0421 //------ AAIモード書き込み ハードウェアによるBUSY判定 -------------------
0422 Serial.println("--------- TEST 3 ---------------");
0423 Serial.println("H/W array write/read start");
0424 for( byte i = 0 ; i < 16 ; i++ ) {
0425 data_array_w[i] = random(0,255);
0426 }
0427 tm = millis();
0428 for( addr = 0x40000 ; addr < 0x60000 ; addr += 16 ) {
0429 sst_write_word_SW( addr, data_array_w, 16 );
0430 sst_read( addr, data_array_r, 16 );
0431 for( byte i = 0 ; i < 16 ; i++ ) {
0432 if( data_array_w[i] != data_array_r[i] ) {
0433 Serial.print("error addr="); Serial.print(addr,HEX);
0434 Serial.print(" index="); Serial.print(i);
0435 Serial.print(" write data="); Serial.print(data_array_w[i],HEX);
0436 Serial.print(" read data=" ); Serial.print(data_array_r[i],HEX); Serial.println("");
0437 }
0438 }
0439 }
0440 Serial.print("H/W array write/read end");
0441 Serial.print(" Time:"); Serial.print((millis() - tm )/1000); Serial.println("sec");
0442
0443 //------ 1バイト単位の読み書き ------------------------------------------
0444 // ERASEしないで上書きするとエラーになる
0445 Serial.println("--------- TEST 4 ---------------");
0446 Serial.println("byte write/read start");
0447 tm = millis();
0448 for( addr = 0x0 ; addr < 0x5 ; addr++ ) {
0449 data_w = random(0,255);
0450 sst_write_byte( addr, data_w );
0451 data_r = sst_read_byte(addr);
0452 if( data_w != data_r ) {
0453 Serial.print("error addr="); Serial.print(addr,HEX);
0454 Serial.print(" write data="); Serial.print(data_w,HEX);
0455 Serial.print(" read data=" ); Serial.print(data_r,HEX); Serial.println("");
0456 }
0457 }
0458 Serial.print("byte write/read end");
0459 Serial.print(" Time:"); Serial.print((millis() - tm )/1000); Serial.println("sec");
0460
0461 //------ 1バイト単位の読み書き ------------------------------------------
0462 // ERASEしてから書き込む必要がある
0463 Serial.println("--------- TEST 5 ---------------");
0464 sector_erase( 0x0 );
0465 Serial.println("byte write/read start");
0466 tm = millis();
0467 for( addr = 0x0 ; addr < 0x5 ; addr++ ) {
0468 data_w = random(0,255);
0469 sst_write_byte( addr, data_w );
0470 data_r = sst_read_byte(addr);
0471 if( data_w != data_r ) {
0472 Serial.print("error addr="); Serial.print(addr,HEX);
0473 Serial.print(" write data="); Serial.print(data_w,HEX);
0474 Serial.print(" read data=" ); Serial.print(data_r,HEX); Serial.println("");
0475 }
0476 }
0477 Serial.print("byte write/read end");
0478 Serial.print(" Time:"); Serial.print((millis() - tm )/1000); Serial.println("sec");
0479
0480 //------ 1バイト単位の読み書き ------------------------------------------
0481 // 強引に上書きするとどうなるかテスト
0482 // 消去しないで上書きするとANDが取られる
0483 // 消去は全ビットセット 書き込みによりビットクリヤは出来るがビットセットが出来ない
0484 Serial.println("--------- TEST 6 ---------------");
0485 sector_erase( 0x0 );
0486 Serial.println("write BIN 11111100");
0487 sst_write_byte( 0x0, 0b11111100 );
0488 Serial.println("write BIN 11001111");
0489 sst_write_byte( 0x0, 0b11001111 );
0490 data_r = sst_read_byte( 0x0 );
0491 Serial.print("read data=" ); Serial.print(data_r,BIN); Serial.println("");
0492
0493 Serial.println("--------- TEST END -------------");
0494 device_protect_enable();
0495 while(true) {}
0496 }
0497
0498 //------- E N D ------------------------------------------------------------------------
行番号
解説
全行
ソース内のコメントを参照。使われていない関数もある。

テストプログラムの実行結果。シリアルモニターの表示結果。TEST 4 は TEST 1 の書き込み後に消去せずに上書きしているのでエラーになるのが正しい。

--------- TEST START ------------
Chip-Erase start
Chip-Erase end
--------- TEST 1 ---------------
byte write/read start
byte write/read end Time:30sec
--------- TEST 2 ---------------
S/W array write/read start
S/W array write/read end Time:3sec
--------- TEST 3 ---------------
H/W array write/read start
H/W array write/read end Time:3sec
--------- TEST 4 ---------------
byte write/read start
error addr=0 write data=FE read data=32
error addr=1 write data=73 read data=20
error addr=2 write data=52 read data=0
error addr=3 write data=E3 read data=E0
error addr=4 write data=71 read data=41
byte write/read end Time:0sec
--------- TEST 5 ---------------
Sector-Erase start
Sector-Erase end
byte write/read start
byte write/read end Time:0sec
--------- TEST 6 ---------------
Sector-Erase start
Sector-Erase end
write BIN 11111100
write BIN 11001111
read data=11001100
--------- TEST END -------------

サンプルスケッチ現物
ファイル ファイルタイプ 添付ファイルの解説
SSTMEM.zip arduino 上のサンプルスケッチ現物