Arduino / SPI通信_S25FL_1 by Spresense


Arduino

counter: 618, today: 1, yesterday: 0

■ページ内リンク Link to internal page
1.概要 summary
1-1.ハードウェアセットアップ(hard ware set up)
1-2.タイミングチャート timing chart
1-3.ピン一覧 pin assigned table
1-4.ソースコード source code by arduino(prossecing)
1-5.シリアルモニタプロット displayed serial monitor prompt

1.概要(summary)

SpresenseからSPI I/Fによって記憶素子デバイスの制御を可能とする。
SpresenseとはSonyから発売されたIT向けの高性能エッジデバイスである。
Arduino互換SPI I/F(Supresense上はSPI4(D13:D10))を使う場合、拡張ボードが必須となる。

I will get possible to control the device which is NOR-FLASH using Supresense
Spresense is made by Sony, which is the highest performance "Edge device" which has ever seen before.
Spresense has SPI I/F with Arduino compatible, we can use it with both the main-board and the extended board.

主要デバイス(Main devices)
(1)Spresense Main-board CXD5602PWBMAIN1 CortexM4F x6cores 156 MHz
(2)Spresense Extended-board CXD5602PWBEXT1
(Arduino互換I/FのSPIの場合は40Mhzまでに制限されている。)
(3)S25FL032P0XNFI010 NOR-FLASH
(SPI I/Fのものなら何でも可だがNORが良い)

(1)Spresense Main-board CXD5602PWBMAIN1 CortexM4F x6cores 156 MHz
(2)Spresense Extended-board CXD5602PWBEXT1
(limited SPI I/F(Arduino compatible) is up to 40MHz)
(3)S25FL032P0XNFI010 NOR-FLASH
(Any SPI-interfaced devices available ,but the type "NOR" is better)

1-1.ハードウェアセットアップ(hard ware set up)

下図のような構成を考える。
(I consider the following structure by putting it into practice.)

添付ファイルの画像

Figure1.Spresense SPI diagram

添付ファイルの画像

Figure2.Spresense SPI diagram

1-2.タイミングチャート


Omitted.
Please reffer the datasheet "S25FL032P0XNFI010"
The Clock rate is 20MHz(DIV4).
(doesn't work at 40MHz)
The reason is unclear, I've not investigateing.

1-3.ピン一覧(pins assigned table)

Spresense extended-board <---->S25FL032P0XNF010 (WSON package 8pin)
CS:8pin*--->CS#:1pin
SCK:13pin--->SCK:6pin
MIS:12pin<---SO:2pin
MOS:11pin--->SI:5pin
*CS is assigned 8pin (not default 10pin),because the 10pin is executed by a byte.
Read data is not limitted by only a byte.
The possibility of 2 bytes and more exists.  

1-4.ソースコード(source code)

 #include <SPI.h>       //to use SPI I/F
 #define FLASH_CS 8    //set the pin to cs spre 8 only using Supresense made by Sony
 uint8_t data_id;      //ID data
 uint8_t data_conf;    //CONFIGURATION data
 uint8_t data_str;     //Status Register data
 uint8_t data_write;   //Write data
 boolean exe_at_once = true;
 
 //////////////////spi_initialize //////////////////
 void spi_init() {
   SPI.begin();
   pinMode(FLASH_CS, OUTPUT);
   SPI.setBitOrder(MSBFIRST);           //send from MSB .Not LSB
   SPI.setClockDivider(SPI_CLOCK_DIV4); //20MHz
   // DIV"2" means "2"/16 divided internal clock(worked by 40MHz) but the target device "25FL" works up to DIV4(20MHz)
   SPI.setDataMode(SPI_MODE0); //MODE0
   spi_set_cs(0x1);
 }
 //////////////////spi_set_cs //////////////////
 void spi_set_cs(uint8_t cs_high) {
   digitalWrite(FLASH_CS, cs_high & 0x1);
 }
 //////////////////watch Write In Progress(the subsequent cycle has to wait this flag"0") //////////////////
 uint8_t flash_is_wip() {
   spi_set_cs(0x0);
   SPI.transfer(0x05);
   data_str = (uint8_t)SPI.transfer(0x00);
   return (data_str & 0x1);
   spi_set_cs(0x1);
 }
 
 void setup() {
   spi_init();
   Serial.begin(9600);
 
 //////////////////RDID ///////////////////////
   Serial.print("RDID(0x9f)_ReaD_Idtification_register\n");
   spi_set_cs(0x0);
   //RDID(0x9f) are excuting
   data_id = SPI.transfer(0x9f);
 
   for (uint16_t i = 0 ; i <= 80; ++i) { //80d stands for 50h which is the end of ID register
     char cnt[80];                       //cnt array defined
     sprintf(cnt, "%2x", i); 
     //change Type to char to display as character(column gets to be the same vertical positon)
     Serial.print(cnt);
     Serial.print(" ");
   }
   Serial.print("\n");
   for (uint16_t i = 0 ; i <= 80; ++i) { //80d stands for 50h which is the end of ID register
     data_id  = (uint8_t)SPI.transfer(0x00) ; //send dummy data to output clocks by 8 times
     char data_cnt[80];                       //cnt array defined
     sprintf(data_cnt, "%2x", data_id);
     Serial.print(data_cnt);
     Serial.print(" ");
   }
   Serial.print("\n");
   // Set cs to High
   spi_set_cs(0x1);
   SPI.endTransaction();
   spi_init();
 
   //////////////////RCR //////////////////
   Serial.print("RCR(0x35)_Read_Configuration_Register\n");
   spi_set_cs(0x0);
   // RCR(0x35) are excuting
   // data_conf = SPI.transfer(0x35);
   SPI.transfer(0x35);
   for (uint16_t i = 0 ; i <= 0; ++i) {
     char cnt[1];
     sprintf(cnt, "%2x", i);
     Serial.print(cnt);
     Serial.print(" ");
   }
   Serial.print("\n");
   for (uint16_t i = 0 ; i <= 0; ++i) {
     data_conf  = (uint8_t)SPI.transfer(0x00) ;
     char data_ccnt[1];
     sprintf(data_ccnt, "%2x", data_conf);
     Serial.print(data_ccnt);
     Serial.print(" ");
   }
   Serial.print("\n");
   spi_set_cs(0x1);
 
   SPI.endTransaction();
   spi_init();
   //WRITE STATUS RESISTER_check & initialize to "0x00"
   Serial.print("WEN(0x06)--->WRR(0x01**)_Write Enabled & Write Status Register \n");
   Serial.print("Initialized to 0x00. All areas are Write Enabled\n");
   spi_set_cs(0x0);
   SPI.transfer(0x06);
   spi_set_cs(0x1);
 
   spi_set_cs(0x0);
   SPI.transfer(0x01);
   SPI.transfer(0x00);
   spi_set_cs(0x1);
 
   delay(100);
   Serial.print("Write_in_progress_check");
   while (flash_is_wip()) { //消去待ち
     Serial.print(".");
   }
   Serial.print(" Clear\n");
   Serial.print(" \n");
   SPI.endTransaction();
   spi_init();
 
   //READ STATUS RESISTER
   Serial.print("RDSR(0x05)_STATUS_REGISTER\n");
   spi_set_cs(0x0);
   // CMD_RDSR(0x05) are excuting
   SPI.transfer(0x05);
   data_str = (uint8_t)SPI.transfer(0x00);
   Serial.print(data_str, HEX);
   Serial.print("\n");
   spi_set_cs(0x1);
 
   SPI.endTransaction();
   spi_init();
   }
 /*
   //////////////////COMMAND_TABLE //////////////////
   RDID(ReaD Identification Data)   0x9F ---Correct response are 4D 15 02 01
   RCR(Read Configuration Register) 0x35
   SE(Sector Erase)                 0xD8
   READ(READ)                       0x03
   RDSR(ReaD Status Register)       0x05
   WEN(Write Eanable)               0x06
   WRR(WRite Register)              0x01** (**are 10,0C,08,04 etc)
 */
 
 void loop() {
   if (exe_at_once) {
     exe_at_once = false;
     //  exe_at_once= true;
     for (uint16_t k = 0 ; k <= 0 ; ++k) { 
       SPI.endTransaction();
       spi_init();
    delay(200);
       Serial.print("---Loop is stating--- \n");
       /////////Sector Erase/////////
       Serial.print("SE(0xD8)_Sector_Erase(only enable bit to change 0 to 1 1111...stands for 0xff)\n");
       spi_set_cs(0x0);
       SPI.transfer(0x06);
       spi_set_cs(0x1);
 
       spi_set_cs(0x0);
       SPI.transfer(0xd8);
       SPI.transfer(0x21);
       SPI.transfer(0x00);
       SPI.transfer(0x00);
       spi_set_cs(0x1);
   
       Serial.print("Write_in_progress_check");
       while (flash_is_wip()) { //消去待ち
         Serial.print(".");
       }
       Serial.print(" Clear\n");
       Serial.print(" \n");
       SPI.endTransaction();
       spi_init();
 
       //////////////////READ //////////////////
       Serial.print("READ(0x03)\n");
       spi_set_cs(0x0);
       SPI.transfer(0x03);
       SPI.transfer(0x21);
       SPI.transfer(0x00);
       SPI.transfer(0x00);
   
       for (uint16_t i = 0 ; i <= 15; ++i) {
         char cnt[16];
         sprintf(cnt, "%2x", i);
         Serial.print(cnt);
         Serial.print(" ");
       }
       Serial.print("\n");
       for (uint16_t i = 0 ; i <= 15; ++i) {
         uint8_t data;
         data  = (uint8_t)SPI.transfer(0x00) ;
         char data_cnt[16];
         sprintf(data_cnt, "%2x", data);
         Serial.print(data_cnt);
         Serial.print(" ");
       }
       spi_set_cs(0x1);
       Serial.print("\n");
       SPI.endTransaction();
       spi_init();
 
       //////////////////WRITE//////////////////
       Serial.print("WRITE(0x02) Terget to fixed address 0x210000 \n");
       
       spi_set_cs(0x0);
       SPI.transfer(0x06);
       spi_set_cs(0x1);
 
       spi_set_cs(0x0);
       SPI.transfer(0x02);
       SPI.transfer(0x21);
       SPI.transfer(0x00);
       SPI.transfer(0x00);
       
        for (uint16_t i = 0 ; i <= 15; ++i) {
         char cnt[16];
         sprintf(cnt, "%2x", i);
         Serial.print(cnt);
         Serial.print(" ");
       }
         Serial.print(" \n");
       for (uint16_t i = 0 ; i <= 15; ++i) {
         //data_write = (uint8_t)SPI.transfer(i + 1 ) ;
         data_write = i + 1  ;
         SPI.transfer(i +1 ) ;
         char data_count[16];
         sprintf(data_count,"%2x",data_write);
         Serial.print(data_count);
         Serial.print(" ");
        }
       Serial.print(" \n");
       spi_set_cs(0x1);
   
       Serial.print("Write_in_progress_check");
       while (flash_is_wip()) { //消去待ち
       Serial.print(".");
       }
       Serial.print(" Clear\n");
       Serial.print(" \n");
       SPI.endTransaction();
       spi_init();
   
       //////////////////READ //////////////////
       Serial.print("READ(0x03)\n");
       spi_set_cs(0x0);
       SPI.transfer(0x03);
       SPI.transfer(0x21);
       SPI.transfer(0x00);
       SPI.transfer(0x00);
      
       for (uint16_t i = 0 ; i <= 15; ++i) {
         char cnt[16];
         sprintf(cnt, "%2x", i);
         Serial.print(cnt);
         Serial.print(" ");
       }
       Serial.print("\n");
       for (uint16_t i = 0 ; i <= 15; ++i) {
         uint8_t data;
         data  = (uint8_t)SPI.transfer(0x00) ;
         char data_cnt[16];
         sprintf(data_cnt, "%2x", data);
         Serial.print(data_cnt);
         Serial.print(" ");
       }
       spi_set_cs(0x1);
       Serial.print("\n");
 
       /////////WRITE STATUS RESISTER_check & chage the value to "0x1C"/////////
       Serial.print("WEN(0x06)--->WRR(0x01**)_Write Enabled & Write Status Register \n");
       Serial.print("Changed data to 0x1C \n");
       spi_set_cs(0x0);
       SPI.transfer(0x06);
       spi_set_cs(0x1);
 
       spi_set_cs(0x0);
       SPI.transfer(0x01);
       SPI.transfer(0x1C);
       spi_set_cs(0x1);
        
       Serial.print("Write_in_progress_check");
       while (flash_is_wip()) { //消去待ち
         Serial.print(".");
       }
       Serial.print(" Clear\n");
       Serial.print(" \n");
       SPI.endTransaction();
       spi_init();
 
       /////////READ STATUS RESISTER/////////
       Serial.print("RDSR(0x05)_STATUS_REGISTER\n");
       spi_set_cs(0x0);
       // CMD_RDSR(0x05) are excuting
       SPI.transfer(0x05);
       data_str = (uint8_t)SPI.transfer(0x00);
       Serial.print(data_str, HEX);
       Serial.print("\n");
       spi_set_cs(0x1);
       Serial.print("WEN_COMMAND cycles are 3 times + 1\n");
 
       SPI.endTransaction();
       spi_init();
       //////////////////READ CONFIGURATION REGISTER //////////////////
       Serial.print("RCR(0x35)_Read_Configuration_Register\n");
       spi_set_cs(0x0);
       // RCR(0x35) are excuting
       // data_conf = SPI.transfer(0x35);
       SPI.transfer(0x35);
       for (uint16_t i = 0 ; i <= 0; ++i) {
         char cnt[1];
         sprintf(cnt, "%2x", i);
         Serial.print(cnt);
         Serial.print(" ");
       }
       Serial.print("\n");
       for (uint16_t i = 0 ; i <= 0; ++i) {
         data_conf  = (uint8_t)SPI.transfer(0x00) ;
         char data_ccnt[1];
         sprintf(data_ccnt, "%2x", data_conf);
         Serial.print(data_ccnt);
         Serial.print(" ");
       }
       Serial.print("\n");
       spi_set_cs(0x1);
   
       /////////Ended up SPI transfer,and initialization/////////
       SPI.endTransaction();
     }
   }
 }

1-5.シリアルモニタプロット(serial monitor prompt displayed)

RDID(0x9f)_ReaD_Idtification_register
 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 
 1  2 15 4d  0  0  0 ff ff ff ff ff ff ff ff ff 51 52 59  2  0 40  0  0  0  0  0 27 36  0  0  b  b  9  f  1  1  2  1 16  5  5  8  0  2 1f  0 10  0 3d  0  0  1  0  0  0  0  0  0  0  0 ff ff ff 50 52 49 31 33 15  0  1  0  5  0  1  3 85 95  7  0 
RCR(0x35)_Read_Configuration_Register
 0 
 0 
WEN(0x06)--->WRR(0x01**)_Write Enabled & Write Status Register 
Initialized to 0x00. All areas are Write Enabled
Write_in_progress_check Clear
 
RDSR(0x05)_STATUS_REGISTER
0
---Loop is stating--- 
SE(0xD8)_Sector_Erase(only enable bit to change 0 to 1 1111...stands for 0xff)
Write_in_progress_check................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. Clear
 
READ(0x03)
 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
WRITE(0x02) Terget to fixed address 0x210000 
 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  
 1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 10  
Write_in_progress_check Clear
 
READ(0x03)
 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 
 1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 10 
WEN(0x06)--->WRR(0x01**)_Write Enabled & Write Status Register 
Changed data to 0x1C 
Write_in_progress_check.................. Clear
 
RDSR(0x05)_STATUS_REGISTER
1C
WEN_COMMAND cycles are 3 times + 1
RCR(0x35)_Read_Configuration_Register
 0 
 0