SmingHub / Sming

Sming - powerful open source framework simplifying the creation of embedded C++ applications.
https://sming.readthedocs.io
GNU Lesser General Public License v3.0
1.48k stars 347 forks source link

SDCard only with software SPI? #1428

Open tius2000 opened 6 years ago

tius2000 commented 6 years ago

There might be problem with hardware SPI and SDCard. The SDCard sample compiles fine, but does only work (slow) when I replace

SDCardSPI = new SPIClass();

with

SDCardSPI = new SPISoft(PIN_CARD_DO, PIN_CARD_DI, PIN_CARD_CK, 0);

The error message (with some additional debugging enabled) is:

SPIClass::setClock(prediv 10, cntdiv 2) for target 4000000
disk_initialize (send 80 0xFF cycles)
disk_initialize (send n send_cmd(CMD0, 0)
disk_initialize (until n = 5 && ret != 1
SDCard ERROR: ff
SDCard init FAIL

Could that be hardware related? I checked it with two different cards and cardreaders.

slaff commented 6 years ago

@ADiea you are our SDCard expert. Can you help here?

ADiea commented 6 years ago

Hi sorry for late reply I think software sp[i differs from hardware arduino class. If I remember correctly the main difference is related to who sets the chip select i guess hardware spi relies on the user to select the chip. The SDCard class needs to to chip select by itself you should investigate if the chip select is done correctly using the hardware spi class.

harry-boe commented 6 years ago

Try using lower speeds for HW SPI.

We used the samples in a training class and figured out that only 4 out of 10 boards did work. The issue was that it became unstable with higher speeds than approx. 20 MHz.

Change the initializer (in the Sample) and try again

// overwrite default SPI Speed
    SDCardSPI->beginTransaction(SPISettings(40000000, MSBFIRST, SPI_MODE0));

// Change to 

    SDCardSPI->beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));

About the comment above. True you cant use the HW chip select. This is due to the fact that the initializer sequence of the SD card hat to have that signal set for some time - without sending date.

Unfortunately, you can't do that when using HW SPI

slaff commented 5 years ago

@tius2000 Is the problem that you were having solved? If yes, we will change the default speed in the sample to 20000000 as recommended by @harry-boe.

mopac commented 4 years ago

I was trying to get SDCard sample running on Wemos D1 mini with an added SD card. Same fault as the original post. When I got down to analysing the SPI packets send to the SDcard, I discovered the byte order was incorrect. CMD0 is meant to be 40 00 00 00 00 95. What was being sent was 00 00 00 40 95 00. Seems the SPI was shifting the bytes in the wrong order on a 32 bit boundary. So in SPI setting I changed MSBFIRST to LSBFIRST and it all works now. ( changed in both app.cpp and SDcard.cpp)

I can only guess that softSPI works because it doesn't use a 32 bit register for shifting bytes

slaff commented 4 years ago

So in SPI setting I changed MSBFIRST to LSBFIRST and it all works now. ( changed in both app.cpp and SDcard.cpp)

@mopac Can you submit a PR with your changes so that we can merge them in the develop branch?

mopac commented 4 years ago

@slaff Certainly can. Not done that before so I might need a bit of hand holding! Is there a guide? What concerns is that someone who wrote the original SDcard sample, must have made it work on hardware. So without understanding exactly why their hardware worked and mine didn't until I changed it, just means that with my changes, it now won't work on their hardware. Which feels like a bodge!

slaff commented 4 years ago

Is there a guide?

https://sming.readthedocs.io/en/latest/_inc/CONTRIBUTING.html

mikee47 commented 2 years ago

@slaff @mopac It makes little sense to have byte order set to anything other than LSBFIRST since this corresponds to the native CPU byte ordering.

Also note that the byte order flag bit is absent from the ESP32-C3; doesn't necessarily mean the hardware doesn't support it but the implication is it's not helpful. And the ESP-IDF driver exposes only the bit-order setting, not byte order.

I propose that we modify Sming to be consistent with Arduino and change the byteOrder parameter to bitOrder. Default bit order is MSBFIRST.

https://github.com/SmingHub/Sming/blob/develop/Sming/Core/SPISettings.h

/** @brief constructor for SPISettings
 *
 * Settings are applied to SPI::beginTransaction(SPISettings) and are valid until
 * next beginTransaction()
 *
 * @param   byteOrder: MSBFIRST or LSBFIRST
 *
 * byteOrder's are:
 *
 *      MSBFIRST    Data is sent out starting with Bit31 and down to Bit0
 *      LSBFIRST    Data is sent out starting with the lowest BYTE, from MSB to LSB.
 *                      0xABCDEFGH would be sent as 0xGHEFCDAB
 *
 */
SPISettings(int speed, uint8 byteOrder, uint8 dataMode)

https://github.com/esp8266/Arduino/blob/master/libraries/SPI/SPI.h#L46

SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)