Esp32 and Winbond W25Q128JV serial flash memory

Hi,
I want to read/write to W25Q128JV through SPI.
I am using this library:

With an example code(added at the end of message), It works fine with Arduino Nano IoT 33, but with esp32 I can't see the files or write anything to the chip.
It seems to fail on SerialFlash.create() function when returning maxfiles able to write as 0.
Any idea?
Thanks
This is the example code:



#include <SerialFlash.h>
#include <SPI.h>

const int FlashChipSelect = 4; 

void setup(){

  Serial.begin(115200);
  delay(3000);
  Serial.println("SPI Flash");
  
  if (!SerialFlash.begin(FlashChipSelect)) {
    Serial.println("Unable to access SPI Flash chip");
    while(1){}
  }
  
}

void loop(){

  // MAIN MENU
  Serial.println("");
  Serial.println("");
  Serial.println("SerialFlash Read and Write");
  Serial.println("(switch your terminal to no line endings)");
  Serial.println("--------------------------");
  Serial.println("1) Create a new file");
  Serial.println("2) Open a file");
  Serial.println("3) Delete a file");
  Serial.println("--------------------------");
  Serial.println("Select a number");
  while(!Serial.available()){}
  char choice = Serial.read();
  while(Serial.available()){Serial.read();}

  switch(choice){

    case '1':
      newFile();
      break;

    case '2':
      openFile();
      break;

    case '3':
      deleteFile();
      break;

    default:
      Serial.println("Invalid Selection");
    
  }
  
}

/* Create a new file
 * 
 * Request filename up to 20 chars
 * Request a size up to 256 bytes
 * Request some contents
 * Create a file
 */
void newFile(){

  Serial.println("Enter a filename"); // Request filename from user
  while(!Serial.available()){} // Wait for user

  char filename[20] = {}; // buffer to store user filename
  Serial.readBytesUntil(' ', filename, 20);
  while(Serial.available()){Serial.read();}

  Serial.println("Enter a filesize in bytes"); // Request file size from user
  while(!Serial.available()){} // Wait for user

  char sizeArray[3] = {}; // buffer to store requested file size
  Serial.readBytesUntil(' ', sizeArray, 3);
  while(Serial.available()){Serial.read();}
  int filesize = atoi(sizeArray); // Convert char array to int (i.e. "40" to 40) 

  if(SerialFlash.create(filename, filesize)){ // Returns false if file already exists

    SerialFlashFile file; // Open the file we just created for writing
    file = SerialFlash.open(filename);
    Serial.println("Write some file contents:"); // Request file contents from user
    while(!Serial.available()){} // Wait for user

    char contents[256] = {}; // buffer to store file contents
    Serial.readBytesUntil(255, contents, 256);
    while(Serial.available()){Serial.read();} // Empty read buffer
    file.write(contents, filesize); // Write the contents buffer
    Serial.println("");
    Serial.print("New file ");
    Serial.print(filename);
    Serial.print(" created with size ");
    Serial.print(filesize);
    Serial.println(" bytes!");
  }else{
    Serial.println("");
    Serial.println("There was an error creating this file (does it already exist?)");
  }

  return;
  
}

/* Open a file
 * 
 * Print the directory listing
 * Request filename up to 20 chars
 * Open file and display contents
 */
void openFile(){

  printDir(); // Function to print the directory listing

  Serial.println("Enter a filename to OPEN"); // Request file name from user
  Serial.println();
  while(!Serial.available()){} // Wait for user

  char filename[20] = {}; // buffer to store the file name
  Serial.readBytesUntil(' ', filename, 20);
  while(Serial.available()){Serial.read();}

  Serial.println(filename);

  SerialFlashFile file;
  file = SerialFlash.open(filename); // open the file
  if (file) {
    Serial.print("File Name: ");
    Serial.println(filename);
    Serial.println();
    Serial.print("File Size: ");
    Serial.print(file.size());
    Serial.println(" bytes");
    Serial.println();
    Serial.println("File Contents:");
    char buffer[256] = {}; // create a buffer for the file contents
    file.read(buffer, 256); // read file to buffer
    Serial.print(buffer);
  }else{
    Serial.println("File not found!");
  }

  return;
  
}

/* Delete a file
 * 
 * Print the directory listing
 * Request filename up to 20 chars
 * Delete File
 */
void deleteFile(){

  printDir(); // Function to print the directory listing

  Serial.println("Enter a filename to DELETE"); // Request file name from user 
  while(!Serial.available()){} // Wait for user

  char filename[20] = {}; // buffer to store file name
  Serial.readBytesUntil(' ', filename, 20);
  while(Serial.available()){Serial.read();}

  SerialFlash.remove(filename); // Delete the file

  return;
  
}

/* Print Directory
 * 
 * Print a list of all files on the chip
 * Stolen from SerialFlash library example "ListFiles"
 */
void printDir(){

  Serial.println("Directory Listing");
  Serial.println("-----------------");

  SerialFlash.opendir();
  while (1) {
    char filename[64];
    uint32_t filesize;

    if (SerialFlash.readdir(filename, sizeof(filename), filesize)) {
      Serial.print("  ");
      Serial.print(filename);
      spaces(20 - strlen(filename));
      Serial.print("  ");
      Serial.print(filesize);
      Serial.print(" bytes");
      Serial.println();
    } else {
      break; // no more files
    }
  }
}

void spaces(int num) {
  for (int i=0; i < num; i++) {
    Serial.print(" ");
  }
}

As the library is written using the standard SPI library I would expect a hardware error in this case. As you failed to provide a wiring diagram we're unable to check that.

Hi,
Thanks for the reply, The wiring is:
ESP32 W25Q128JV
3V3 --------> 3.3V
PIN4 --------> CS
PIN18 --------> CLK
PIN23 --------> DI
PIN19 --------> DO
3V3 --------> WP
3V3 --------> HOLD
GND --------> GND
Isn't the fact that the library is written for arduino can cause issues?
Thanks!

No, if the library is just written using the common features of all platforms supported by the Arduino IDE this shouldn't be a problem.

I guess you checked the obvious: Not using the same filenames as you did on the Nano IoT 33, not having filled the complete chip in a previous write, etc.

If you setup is on a breadboard it might be good to decrease the SPI speed. The SAMD of the Nano isn't able to provide the configured 50MHz, the ESP32 might reach that. Frequencies above about 4MHz aren't suitable for breadboard setups.
Change the speed in the SerialFlashChip.cpp near the top of the file (SPICONFIG).

1 Like

Hi, I did check the things you mentioned.
Could you please explain the frequencies issues? Are you saying that the esp is faster than 50Mhz, what is the issue caused from that?
What is the recommended frequency on a breadboard and on a PCB?
I am using it right now on a breadboard and will try lower frequencies.
Thanks!

An SPI bus is designed to be used on PCBs with rather short connections. In my experience breadboard setups with SPI frequencies up to about 4MHz work quite reliably given no bigger source of electrical noise (p.e. motor) is polluting the environment. You might be successful with higher frequencies but that might be just luck.
The ESP (usually, you didn't tell us which exact model you use) runs on 240MHz. The SPI frequency is up to 50MHz which is more than the processor clock of the Nano ioT 33 (48MHz).

I'd recommend to stay at or below 4MHz on a breadboard setup (given you use a high quality breadboard).
On PCBs you may go much higher, 50 MHz shouldn't be a problem if you do your trace routing properly.

1 Like

Thanks a lot! I changed to 20Mhz and it worked fine on a breadboard.