Open rfestag opened 5 years ago
Is this a bug in ESP32's SPI library? If so, it should be fixed there.
Good question. Because I was told to try using a different mode, I assumed different architectures could define them differently. If there are standard definitions and this flash chip inherently should be mode 0, then you're probably right. This seems like something somebody would have noticed before though on their end. Would you expect this to be an arduino-esp32 issue, or an esp32 core issue?
These modes absolutely are standard definitions (or at least de-facto standards - not necessarily something published by a standards organization like IEEE or JEDEC). SPI_MODE0 is supposed to do the same thing on all microcontrollers. If ESP32 is doing something different from everyone else, that's definitely a bug with ESP32.
However, it's also possible there could be some other subtle problem. Very hard to know without a deep investigation by looking at the actual waveforms.
That definitely makes sense. I submitted a ticket to them. Unfortunately I don't have a way to look at the waveforms (and honestly wouldn't really know what I'm looking at anyways). Hopefully somebody on there can verify whether the handling of the SPI modes is correct.
Hi all, i found the problem, and it no in SPI mode.
...................sig: FFFFFFFF FFFFFFFF Writing sig: FA96554C 18F60258 Reading sig2: 7DCB2A26 0C7B012C
Take first two bytes and an analyse them Writing sig: FA 96 Reading sig2: 7D CB
...now in bin FA 11111010; 96 10010110 7D 01111101; CB 11001011 as you can see in fast SPI speed transaction you hardware miss one first bit of data. CS signal is not accurate..... I make some test and find that critical speed of SPI mode 0 is up to 26 MHz, SPI mode 1 is 39MHz. I think in this topic analogue problem https://github.com/SmingHub/Sming/issues/618 I think you need use software CS signal, but this library dont have optimisation for fast software gpios on esp32, that in SerialFlash_directWrite https://github.com/PaulStoffregen/SerialFlash/blob/71cfa7a738f7ec8ae5e670b0a10e7c9fdd0e8139/util/SerialFlash_directwrite.h#L86 and now i see only esp8266 in it. Sorry for my bad english.... Nice day....
@fa1ke5 - Thanks for the input. I looked at your investigation in #58, and tried changing the maximum speed parameter instead of the SPI mode:
#define SPICONFIG SPISettings(26000000, MSBFIRST, SPI_MODE0)
This appears to be working correctly now. While you may be right that some special definition for ARDUINO_ARCH_ESP32
would be the correct solution, I'm personally not familiar enough with how to make the appropriate changes. I did come across some code that looked relevant in the OneWire library (https://github.com/PaulStoffregen/OneWire/blob/master/util/OneWire_direct_gpio.h#L119), but pulling those defines into SerialFlash (and keeping the old SPICONFIG definition), didn't work.
I think a few questions back to @PaulStoffregen
Did you copy all code of defines with low level functions, like this IO_REG_TYPE directRead(IO_REG_TYPE pin) { if ( pin < 32 ) return (GPIO.in >>
and tried changing the maximum speed parameter instead of the SPI mode:
you are right, 26MHz is critical for MODE0. GPIO matrix on esp32 work on 26MHz.....but if you switch to MODE1 you take up to 39MHz SPI speed, this is wrong setting but it work, black china magic :)
Do you suppose it works reliably across all chips? How about when the temperature changes?
this is not temperature problem, its only esp32 hardware/SDK problem
I think I have found documentation on what @fa1ke5 is referring to as the "critical" speed:
If you scroll down a bit from there, you'll see a chart outlining the following frequency limits:
GPIO matrix | IOMUX pins | Dummy Bits Used By Driver | |
---|---|---|---|
26.6 | 80 | No | |
40 | – | Yes | Half Duplex, no DMA allowed |
I haven't had a chance to go through the pinouts to trace it, but I'm going to assume the MEM_CS pin on Prop Shield isn't mapped to the ESP32 Pin 15 (CS0) through the Adafruit feather adapter (I'll verify this later, but it seems unlikely that we were lucky enough to have it map to the best pin, and the behavior is consistent). That implies we are going through the GPIO matrix, and have a limit of 26.6Mhz when not using the "dummy bit" workaround, and 40Mhz when using it.
I also found this interesting header file: https://github.com/espressif/arduino-esp32/blob/master/tools/sdk/include/driver/driver/spi_master.h
At the top, it describes the SPI frequencies, and mentions that it will round down to the closest frequency. Since SerialFlash hard codes 50Mhz, it is rounded down to 40Mhz and fails. I tried specifying 30Mhz (which would round it down to 26Mhz), and it worked fine.
Because we have a R/W workload with SerialFlash (not write-only), we probably shouldn't use the dummy-bit workaround. As such, I think the best course of action is to make the SPICONFIG configurable. I say this for 2 reasons: 1) If we add an architecture specific define for the max value, we ignore the case where somebody actually does have the flash mapped to the IOMUX CS0 pin on ESP32 and can operate at higher frequencies. For instance, I think there is a way for us to redefine the IOMUX pins, but that shoudn't be a prerequisite for using this library. 2) It is clearly possible that some users will have speed limits based on their architecture, so making it configurable allows SerialFlash to be used by them.
I presume the best place to do this would be to add an overloaded begin() method that allows passing in an SPISettings from the user, and setting SPICONFIG there?
I'd be happy to create a pull request for this if it makes sense.
Description
I am unable to read/write from the Teensy Prop Shield's flash storage on the ESP32. This appears to be because I need to use a different SPI_MODE. I initially reported the issue to arduino-esp32 , and @stickbreaker suggested I change the SPI mode. I found that
SPI_MODE1
worked properly, while SerialFlash'sSPICONFIG
usesSPI_MODE0
. This can be seen here.I'm happy to create a PR for this, but I'm not sure how you would want to see this resolved:
Steps To Reproduce Problem
I am using a Teensy Prop Shield attached to an Adafruit ESP32 Feather. A minimal sketch is provided below
Hardware & Software
Board: Adafruit ESP32 Feather Shields / modules used: Teensy Prop Shield Arduino IDE version: 1.8.8 Version info & package name (from Tools > Boards > Board Manager): arduino-esp32 (latest from git) Operating system & version: Manjaro
Arduino Sketch
Errors or Incorrect Output
Below is the output of the sketch provided above. Note that I copied the check_signature method from SerialFlash, and added some debugginng to it to print out what it is writing and the result of immediately reading that write upon finding an erased flash chip.