Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues writing to SPI Flash via SerialFlash library on Teensy Prop Shield #2542

Closed
rfestag opened this issue Mar 5, 2019 · 5 comments
Closed

Comments

@rfestag
Copy link
Contributor

rfestag commented Mar 5, 2019

Hardware:

Board: Adafruit ESP32 Feather
Core Installation version: Git master
IDE name: Arduino IDE
Flash Frequency: 80Mhz
PSRAM enabled: No idea?
Upload Speed: 115200
Computer OS: Manjaro (Arch derivative)

Description:

I am trying to use the Teensy Prop Shield to store files in it's on-board SPI flash (W25Q64FV) using the SerialFlash library (https://github.com/PaulStoffregen/SerialFlash). As far as I can tell, it seems like the least significant bit of the data being written is not being sent to the device by the SerialFlash library. I know lots of people are using this library successfully on other platforms, which makes me think there is an issue with the SPI implementation here. I know in the past there have been issues with I2C (which, coincidentally, I also ran into with this shield, but specifically were related to the motion sensors on board and were resolved a year or so ago).

This library expects a certain magic word (0xFA96554C) to be the first 16 bits of the flash memory. Any attempt to create a file without this (or 0xFFFFFFFF) will cause the write to fail. If it detects 0xFFFFFFFF, it assumes the storage has been wiped, and it will write the magic word, followed by some size information.

In my tests, the first 32 bits of memory should be:
0xFA96554C
0x18F60258

However, upon reading the data immediately after writing, the following is actually written:
0x7DCB2A26
0x0C7B012C

When I compare the binary, the actual written value appears to be bit-shifted:
Expected:
FA 96 - 11111010 10010110
Actual:
7D CB - 01111101 11001011
Fix: left-shift a 0 into each byte
11111010 10010110

Expected:
55 4C - 01010101 01001100
Actual:
02 58 - 00101010 00100110
Fix: left 1 into higher byte, 0 into lower byte
01010101 01001100

This seems to imply that the transfer is somehow missing the the least significant bit on each byte. What is odd is that this doesn't seem to be pervasive (some writes are fine, such as when transferring the command to bulk erase the flash). It seems to be a problem when iteratively writing bytes.

Sketch:

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

#define MEM_CS 12

//These are copied from SerialFlash for illustration. They 
#define DEFAULT_MAXFILES      600
#define DEFAULT_STRINGS_SIZE  25560

static uint32_t check_signature(void)
{
        uint32_t sig[2];
        uint32_t sig2[2];

        SerialFlash.read(0, sig, 8);
        Serial.printf("sig: %08X %08X\n", sig[0], sig[1]);
        if (sig[0] == 0xFA96554C) return sig[1];
        if (sig[0] == 0xFFFFFFFF) {
                sig[0] = 0xFA96554C;
                sig[1] = ((uint32_t)(DEFAULT_STRINGS_SIZE/4) << 16) | DEFAULT_MAXFILES;
                Serial.printf("Writing sig: %08X %08X\n", sig[0], sig[1]);
                SerialFlash.write(0, sig, 8);
                while (!SerialFlash.ready()) ; // TODO: timeout
                SerialFlash.read(0, sig2, 8);
                Serial.printf("Reading sig2: %08X %08X\n", sig2[0], sig2[1]);
                if (sig2[0] == 0xFA96554C) return sig2[1];
        }
        return 0;
}
void setup() {
  Serial.begin(115200);
  Serial.println();

  //Setup Serial Flash
  if (!SerialFlash.begin(MEM_CS)) {
    Serial.println("Unable to access SPI Flash chip");
  }
  
  //These writes actually work. We do it to ensure the first part of
  //the flash storage is 0xFFFFFFFF, forcing it to try to write the magic number
  SerialFlash.eraseAll(); 
  unsigned long dotMillis = millis();
  unsigned char dotcount = 0;
  while (SerialFlash.ready() == false) {
    if (millis() - dotMillis > 1000) {
      dotMillis = dotMillis + 1000;
      Serial.print(".");
      dotcount = dotcount + 1;
      if (dotcount >= 60) {
        Serial.println();
        dotcount = 0;
      }
    }
  }
  //We call the function SerialFlash uses internally to verify
  //that the state of the storage is valid (i.e., it has the magic number)
  check_signature();
}

void loop() {}

Debug Messages:

...................sig: FFFFFFFF FFFFFFFF
Writing sig: FA96554C 18F60258
Reading sig2: 7DCB2A26 0C7B012C
@stickbreaker
Copy link
Contributor

@rfestag look through the library code and see if it set the SPI_MODE. It could be a difference in default modes between the Library and ESP32.

Chuck.

@rfestag
Copy link
Contributor Author

rfestag commented Mar 5, 2019

@stickbreaker: It looks like it does so here:
https://github.com/PaulStoffregen/SerialFlash/blob/master/SerialFlashChip.cpp#L33

#define SPICONFIG SPISettings(50000000, MSBFIRST, SPI_MODE0)

Does that seem appropriate for the ESP32? If not, what makes sense?

@stickbreaker
Copy link
Contributor

@rfestag try changing the SPI_MODE0, to mode 2 SPI_MODE2. The bit shift you are seeing in indicative of a clock polarity problem.

@rfestag
Copy link
Contributor Author

rfestag commented Mar 5, 2019

Using SPI_MODE2 didn't help (actually things completely locked up and it never could erase the flash). However, I tried SPI_MODE1, and it seems to be working. I'll open an issue with SerialFlash to see if we can either make that configurable, or add an ESP32 ifdef to configure it properly. Thanks for the help!

@fa1ke5
Copy link

fa1ke5 commented Mar 19, 2019

it's not an SPI mode problem, i wrote in
PaulStoffregen/SerialFlash#57

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants