greiman / SdFat

Arduino FAT16/FAT32 exFAT Library
MIT License
1.08k stars 509 forks source link

SdFat::begin() improvement suggestion #111

Open SapientHetero opened 6 years ago

SapientHetero commented 6 years ago

Over the weekend I got a Class 10 SD card to work with the Metro M4 and Adafruit WINC1500 shield by slowing the SPI clock down to 12 MHz. This week I integrated the Seeed Ethernet 5500 shield with my sketch.

My sketch initialized a 2GB card with the Seeed shield mounted on an Arduino Mega with the SPI clock reduced to 4MHz, but wouldn't initialize the same card in the same shield on a Metro M4 at any clock speed. The Seeed shield advertises that it supports SPI MODE 0, 3.

The sketch works with the same 2GB SD card using an Adafruit WINC1500 shield and Metro M4, with SPI clock set to 12 MHz.

I noticed that SdFat's SdSpiCard::begin initially sets the SPI clock to 250K [m_spiDriver->setSpiSettings(SD_SCK_HZ(250000));] regardless of the clock rate requested. When I removed a zero from this setting, thus making it 25K, my sketch worked. I'm sure there's room for refinement there (it takes a long time to time out if no card is present at this setting), but it allows the Metro M4/Seeed Ethernet shield combination to successfully initialize a card.

I suspect the clock settings used in the library don't translate well to the 120MHz ATSAMD51G19A used on the Metro M4. The speed settings in SdInfo.h translate as follows on the M4:

SPI_DIV3_SPEED = 40,000,000 SPI_HALF_SPEED = 30,000,000 SPI_DIV6_SPEED = 20,000,000 SPI_QUARTER_SPEED = 15,000,000 SPI_EIGHTH_SPEED = 7,500,000 SPI_SIXTEENTH_SPEED = 3,750,000

greiman commented 6 years ago

I don't want to slow the clock that much for initialization since the standard specifies that the clock must be in the range 100-400 kHz for initialization.

Issue continuous clock in the frequency range of 100 kHz-400 kHz.

Some SD cards will not initialize with very slow clock. I picked 250 kHz since it is the middle of the range.

I have tried various values over the years and 250 kHz works best.

I can't make the default settings match just some old SD cards and very slow shields.

Many people use much faster processors than your Metro M4. I use Teensy 3.6 at 240 MHz with no problems. With SDIO, I get transfer rates of about 20 MB/sec.

I may put a symbol in SdFatConfig.h for initialization speed. For now you will need to set it to a value that will work for your shield in the source.

Symbols like SPI_DIV3_SPEED , HALF_SPEED originated before SPISettings was added to the SPI library. I defined them for backward compatibility. I have removed them from the examples and will soon remove them from in SdInfo.h.

SPISetting is nice since you can set a SCK speed and it will work for all boards. All modern SD cards support 50 MHz SPI clock. SPISetting at 50MHz chooses the highest speed <= 50MHz that is also supported by the CPU. This will be 8MHz on an Uno, 48 MHz on a Due.

I looked at the Metro M4 SPI driver. Looks like it may have a bug in the baud generator associated with SPISettings. It may be unreliable if you request an SPI rate greater than 24 MHz.

SapientHetero commented 6 years ago

All good points. Yet, I need a reliable system with whatever card happens to be used. So I'm going to try cycling through a range of init frequencies during startup and record what works for the current SD card. That will then be used in subsequent accesses.

I can't get my Class 10 card to initialize at any frequency so far with the Seeed shield, but if I start the system with an old 2GB card at the slow freq, I can swap them and the C10 card works fine. Seems like a solvable problem.

I'll share whatever I learn. Your suggestions are welcome.

On Sat, Aug 18, 2018, 3:08 PM Bill Greiman notifications@github.com wrote:

I don't want to slow the clock that much for initialization since the standard specifies that the clock must be in the range 100-400 kHz for initialization.

Issue continuous clock in the frequency range of 100 kHz-400 kHz.

Some SD cards will not initialize with very slow clock. I picked 250 kHz since it is the middle of the range.

I have tried various values over the years and 250 kHz works best.

I can't make the default settings match just some old SD cards and very slow shields.

Many people use much faster processors than your Metro M4. I use Teensy 3.6 at 240 MHz with no problems. With SDIO, I get transfer rates of about 20 MB/sec.

I may put a symbol in SdFatConfig.h for initialization speed. For now you will need to set it to a value that will work for your shield in the source.

Symbols like SPI_DIV3_SPEED , HALF_SPEED originated before SPISettings was added to the SPI library. I defined them for backward compatibility. I have removed them from the examples and will soon remove them from in SdInfo.h.

SPISetting is nice since you can set a SCK speed and it will work for all boards. All modern SD cards support 50 MHz SPI clock. SPISetting at 50MHz chooses the highest speed <= 50MHz that is also supported by the CPU. This will be 8MHz on an Uno, 48 MHz on a Due.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/greiman/SdFat/issues/111#issuecomment-414080030, or mute the thread https://github.com/notifications/unsubscribe-auth/AlmII4lt5IwBgyF3MyG3-sNMF1ojABLJks5uSGYWgaJpZM4WCn1_ .

SapientHetero commented 6 years ago

I’m baffled. If you have any suggestions I'd be grateful.

I ran the test described earlier, starting with the 32GB Class 10 SD card. I modified SdSpiCard::begin as shown below. sd.begin failed for the 32GB card at every clock rate from 25KHz to 400KHz. I removed it, inserted a 2GB Class 4 card, hit the reset button once, closed & opened the Serial Monitor and reran the test. sd.begin succeeded at every rate.

I then changed the clock rate range to run from 25KHz to 1MHz. Again, the 2GB card worked at every rate.

I removed it, reinserted the 32GB card, repeated the same steps and it too worked at every clock rate.

I wondered if this could be an artifact of how I ran the test so I disconnected & reconnected the USB cable to the Metro M4, closed and opened the Serial Monitor and again got success at every clock rate. I reloaded the test program, repeated with the 32GB card and again it passed at every clock rate.

Then, without removing the SD card, I restored the original version of SdSpiCard::begin and started my software as usual and upon reaching this code, failed:

if (!sd.begin(SD_CONFIG)) {

ERROR_PRINTLN(F("Error initializing SD card reader"));

SD_CONFIG is defined as SDCARD_SS_PIN,SD_SCK_MHZ(4).

Here’s my modified version of SdSpiCard::begin:

bool SdSpiCard::begin(SdSpiDriver* spi, uint8_t csPin, SPISettings settings) {

m_spiActive = false;

m_errorCode = SD_CARD_ERROR_NONE;

m_type = 0;

m_spiDriver = spi;

uint16_t t0 = curTimeMS();

uint32_t arg;

unsigned long i;

for (i=25; i<=1000; i+=25) {

m_spiDriver->begin(csPin);

m_spiDriver->setSpiSettings(SPISettings(i*1000, MSBFIRST, SPI_MODE0));

spiStart();

… No changes in middle section

// Discard rest of ocr - contains allowed voltage range.

for (uint8_t i = 0; i < 3; i++) {

  spiReceive();

}

}

spiStop();

m_spiDriver->setSpiSettings(settings);

Serial.print("SD card init succeeded at ");

Serial.print(i*1000);

Serial.println(" HZ");

goto next;

fail:

Serial.print("SD card init failed at ");

Serial.print(i*1000);

Serial.println(" HZ");

next:

spiStop();

}

return false;

}

On Sat, Aug 18, 2018, 3:08 PM Bill Greiman notifications@github.com wrote:

I don't want to slow the clock that much for initialization since the standard specifies that the clock must be in the range 100-400 kHz for initialization.

Issue continuous clock in the frequency range of 100 kHz-400 kHz.

Some SD cards will not initialize with very slow clock. I picked 250 kHz since it is the middle of the range.

I have tried various values over the years and 250 kHz works best.

I can't make the default settings match just some old SD cards and very slow shields.

Many people use much faster processors than your Metro M4. I use Teensy 3.6 at 240 MHz with no problems. With SDIO, I get transfer rates of about 20 MB/sec.

I may put a symbol in SdFatConfig.h for initialization speed. For now you will need to set it to a value that will work for your shield in the source.

Symbols like SPI_DIV3_SPEED , HALF_SPEED originated before SPISettings was added to the SPI library. I defined them for backward compatibility. I have removed them from the examples and will soon remove them from in SdInfo.h.

SPISetting is nice since you can set a SCK speed and it will work for all boards. All modern SD cards support 50 MHz SPI clock. SPISetting at 50MHz chooses the highest speed <= 50MHz that is also supported by the CPU. This will be 8MHz on an Uno, 48 MHz on a Due.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/greiman/SdFat/issues/111#issuecomment-414080030, or mute the thread https://github.com/notifications/unsubscribe-auth/AlmII4lt5IwBgyF3MyG3-sNMF1ojABLJks5uSGYWgaJpZM4WCn1_ .

greiman commented 6 years ago

The most common problems I see in cases like this are:

Multiple devices on the SPI bus and one or more devices is not disabled before initializing a device.

Be sure you have code like this for all devices not being initialize, the WiFi in your case.

  pinMode(CS_WIFI, OUTPUT);
  digitalWrite(CS_WIFI, HIGH);

The second one is to use the wrong CS_PIN for the SD so the correct pin is floating. On some SD shields this sort of works. I suspect this is not your problem.

I don't have much confidence in the Adafruit SPI driver.

In SPI mode the SERCOM BAUD rate register is 8-bits. See the ATSAMD51G19A data sheet Table 33-2. Baud Rate Equations.

The SPI clock, f, must satisfy these equations. F_REF is 48 Mhz for the Metro board, not F_CPU.

f <= F_REF/2 so the max SPI rate is 24 MHz.

f = F_REF/(2*(BAUD + 1)) so the min SPI rate is 93750 Hz for BAUD = 255.

I can't find a test for rates that are too low so who knows what you get.

Here is a buggy line that tests for high frequencies. this->clockFreq = (clock >= (F_CPU / SPI_MIN_CLOCK_DIVIDER) ? F_CPU / SPI_MIN_CLOCK_DIVIDER : clock);

F_CPU should be SERCOM_FREQ_REF. The max SPI frequency for SERCOM on ATSAMD51G19A is 24 MHz. This tests for 60 MHz since F_CPU is 120 MHz. Who knows what happens at higher frequencies.

I really can't help you when I can't trust the Adafruit driver. If trash is on the SPI bus, a card can lockup in the wrong mode and can only be reset by cycling power.

Edit: If you select a rate below 100 kHz or above 24 MHz you may have unstable results.

You may have unstable results in other cases since this driver was written for SAM21 not SAM51. Who know what other problems exist. Looks like there are minimal mods for SAM51.

greiman commented 6 years ago

I noticed one more thing. Your test is not valid unless you cycle power before each rate test. If a card is initialized, it goes through different initialization steps internally.

A power cycled card may take almost a second to initialize. To reinitialize a card may take only a few milliseconds if power is not cycled.

One more note. The standard SD.h library uses a 10 year old version of SdFat. Here is the code for initialization speed.

  SDCARD_SPI.begin();
  settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
  // ...
  SDCARD_SPI.beginTransaction(settings);

SD card are initialized at 250 kHz for every user of the standard SD.h library.

The actual SPI rate will be 24 Mhz divided by an integer. 24, 12, 8, 6, 4.8, 4.0 ... MHz.

SapientHetero commented 6 years ago

Got a hw debugger and stepped through the code and I think my Class 10 SDHC UHS-I card is being incorrectly identified as a type 2 card. I say "think" because I can't get the debugger to display registers, but line 164 in SdSpiDriver is executed [type(SD_CARD_TYPE_SD2);] while line 189 [type(SD_CARD_TYPE_SDHC);] is not.

On Aug 28, 2018 12:18 PM, "Bill Greiman" notifications@github.com wrote:

I noticed one more thing. Your test is not valid unless you cycle power before each rate test. If a card is initialized, it goes through different initialization steps internally.

A power cycled card may take almost a second to initialize. To reinitialize a card may take only a few milliseconds if power is not cycled.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/greiman/SdFat/issues/111#issuecomment-416647774, or mute the thread https://github.com/notifications/unsubscribe-auth/AlmII2aTk-jkC4fQ4MgUm_zKg8R6ctyGks5uVW1fgaJpZM4WCn1_ .

greiman commented 6 years ago

Anything could be happening since who knows what SPI frequency you have been using with the broken SPI driver and trying SPI frequencies that can not be generated by the ATSAMD51G19A .

With the poor level shifters on the SD socket, which distort the SPI signal, I can believe the SDHC test failed at the actual frequency if it is too high.

Also, using a software debugger to breakpoint a driver gives meaningless results since it totally changes timing and timeouts. Use a scope/logic analyzer on the SPI bus.

By the way, a SDHC card is also a type 2 card so that statement should be executed.

If you specify a frequency lower than 100 kHz, the BAUD rate register will be calculated to be greater than 8-bits and the low 8-bits will be loaded into the BAUD rate register so you will get a random result.

If your card won't run at 250 kHz it does not satisfy the SD standard so you need a new card. I have no interest in trying to find some magic SPI rate other than 250 kHz.

I can't help you with this mess.

greiman commented 6 years ago

My last post on this subject.

You have a SPI driver and or SD socket/ level shifter problem.

Only old type 1 SD cards actually require the 100 - 400 kHz range. Most Type 2 cards initialize at speed up to 25 MHz.

A modern UHS-I card will initialize at any SPI speed up to 50 MHz.

Here is proof.

I am using a Due and a SD socket with no level shifters connected with short wires to the SPI pins.

I selected a Samsung 32 GB UHS-I SD and formatted it with the SD Association Formatter since the SD Association Formatter produces the correct standard SD format. Linux, Windows, and Mac OSes may not produce the optimum format.

I made this mod to SdFat at line 132 of SdSpiCard.cpp.

  m_spiDriver->begin(csPin);
//  m_spiDriver->setSpiSettings(SD_SCK_HZ(250000));
m_spiDriver->setSpiSettings(SD_SCK_MHZ(50));
  spiStart();

The Due driver will run at 48 MHz when I select 50 MHz.

I ran the SdInfo example. At 48 MHz my card initialized in 1 ms or less after power cycle. I tried the test a number of times and it never failed.

I removed the card, waited 10 seconds, and reinserted it before each test.

Here is the output.

SdFat version: 1.0.7

Assuming the SD is the only SPI device. Edit DISABLE_CHIP_SELECT to disable another device.

Assuming the SD chip select pin is: 10 Edit SD_CHIP_SELECT to change the SD chip select pin.

type any character to start

init time: 1 ms

Card type: SDHC

Manufacturer ID: 0X1B OEM ID: SM Product: 00000 Version: 1.0 Serial number: 0X16309620 Manufacturing date: 6/2014

cardSize: 32009.36 MB (MB = 1,000,000 bytes) flashEraseSize: 128 blocks eraseSingleBlock: true OCR: 0XC0FF8000

SD Partition Table part,boot,type,start,length 1,0X0,0XC,8192,62510080 2,0X0,0X0,0,0 3,0X0,0X0,0,0 4,0X0,0X0,0,0

Volume is FAT32 blocksPerCluster: 64 clusterCount: 976464 freeClusters: 976461 freeSpace: 31996.67 MB (MB = 1,000,000 bytes) fatStartBlock: 9318 fatCount: 2 blocksPerFat: 7629 rootDirStart: 2 dataStartBlock: 24576

SapientHetero commented 6 years ago

I appreciate the time you've taken to help me. I'm an experienced software guy just getting into this and trying to understand why hardware and software that have been in wide use for quite a while, other than the Metro M4, are behaving in an unexpected way. It will be a big problem for me if my system won't work with currently available SD cards, so I've got to find an answer. I'll continue to work on it and share anything useful that I learn.

The version of SdFat I'm using is your unmodified library, except that the begin() clock rate is set to 125K because I can't get any of my modest supply of SD cards to init otherwise.

Thanks.

On Thu, Aug 30, 2018, 6:53 AM Bill Greiman notifications@github.com wrote:

My last post on this subject.

You have a SPI driver and or SD socket/ level shifter problem.

A modern UHS-I card will initialize at any SPI speed up to 50 MHZ.

Here is proof.

I am using a Due and a SD socket with no level shifters connected with short wires to the SPI pins.

I selected a Samsung 32 GB UHS-I SD and formatted it with the SD Association Formatter https://www.sdcard.org/downloads/formatter_4/ since the SD Association Formatter produces the correct standard SD format. Linux, Windows, and Mac OSes may not produce the optimum format.

I made this mod to SdFat at line 132 of SdSpiCard.cpp.

m_spiDriver->begin(csPin); // m_spiDriver->setSpiSettings(SD_SCK_HZ(250000)); m_spiDriver->setSpiSettings(SD_SCK_MHZ(50)); spiStart();

The Due driver will run at 48 MHz when I select 50 MHz.

I ran the SdInfo example. At 48 MHz my card initialize in 1 ms or less after power cycle. I tried the test a number of time and it never failed.

I removed the card, waited 10 seconds, and reinserted it before each test.

Here is the output.

SdFat version: 1.0.7

Assuming the SD is the only SPI device. Edit DISABLE_CHIP_SELECT to disable another device.

Assuming the SD chip select pin is: 10 Edit SD_CHIP_SELECT to change the SD chip select pin.

type any character to start

init time: 1 ms

Card type: SDHC

Manufacturer ID: 0X1B OEM ID: SM Product: 00000 Version: 1.0 Serial number: 0X16309620 Manufacturing date: 6/2014

cardSize: 32009.36 MB (MB = 1,000,000 bytes) flashEraseSize: 128 blocks eraseSingleBlock: true OCR: 0XC0FF8000

SD Partition Table part,boot,type,start,length 1,0X0,0XC,8192,62510080 2,0X0,0X0,0,0 3,0X0,0X0,0,0 4,0X0,0X0,0,0

Volume is FAT32 blocksPerCluster: 64 clusterCount: 976464 freeClusters: 976461 freeSpace: 31996.67 MB (MB = 1,000,000 bytes) fatStartBlock: 9318 fatCount: 2 blocksPerFat: 7629 rootDirStart: 2 dataStartBlock: 24576

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/greiman/SdFat/issues/111#issuecomment-417277454, or mute the thread https://github.com/notifications/unsubscribe-auth/AlmIIy8VSFC6-pclrDoKLN2Kp7HYdcPOks5uV8Q4gaJpZM4WCn1_ .

greiman commented 6 years ago

I have no idea if any of your tests were meaningful. Did you ever run the SdInfo example?

Warning: Don't try to use the SdInfo code in your apps. It is designed to diagnose problems.

To try the SdInfo example. Use a fresh unmodified version of SdFat. Only make the following mods.

Edit the following. For the AdaFruit WINC1500 shield, the default SD chip select pin is 4 and the default WiFi chip select pin is 10.

Change SS to the SD chip select pin on your shield at line 18. const uint8_t SD_CHIP_SELECT = SS;

Disable the WiFi SPI access. It may interfere since it won't be initialize. Replace the -1 with the WiFi chip select pin in at line 24. const int8_t DISABLE_CHIP_SELECT = -1;

Limit the SPI rate to 4 MHz max by editing line 194 of the example. Replace the 50 with 4. if (!sd.cardBegin(SD_CHIP_SELECT, SD_SCK_MHZ(50))) {

This should work on the Metro since it uses the same initialization and operating rates as the old SD.h library. You should not hit the Metro SPI driver bugs.

SD cards are reliable, that's not your problem. Many billions of devices use modern SD cards. I have the code for Samsung smart phones and other devices. These devices all are reliable because the modern SD card and phone hardware/software conforms to the SD standard and are reliable.

SD shields have been a problem with Arduino since I wrote the first libraries over ten years ago. The 5V to 3.3V signal conversion was first implemented with resistor dividers. I put a scope on the SD card pins and the SPI signals were terrible. I sent traces to Limor Fried at Adafruit and she finally redesigned her shield with semiconductor buffers.

This was fine for AVR boards with a max rate of 8MHz. She tried to design the shield so it would work with 3.3V processors like the Due. This worked because the SPI rate was limited to 4 MHz in the old version of SdFat in SD.h

The Due is capable of 48 MHz and the Metro can run at 24 MHz. The rise time of the buffers on shields with an SD socket are too long for these speeds. These shields must run at slow SPI speeds.

Never use an SPI rate over 12 MHz on the WINC1500. 4 MHz would be better. If you need faster rates get better hardware. Software workarounds never fix bad hardware.

I never use buffered SD sockets on 3.3V boards.

SapientHetero commented 6 years ago

[ Did you ever run the SdInfo example?] Great question, as it turns out. I had run it with every combination of processor, SD card and SD shield on hand. I did the same with "bench" and this was how I first found I had an issue to resolve with the 32GB card. But since doing that I've combed through your library and both the WINC1500 and Wiznet5500 libraries in some depth, so I decided to take another look.

The first thing I noticed is that bench doesn't have a built-in mechanism to disable other SPI devices like SdInfo does. So I added one at the end of setup() like this:

// disable Ethernet or WiFi SPI pinMode(10, OUTPUT); digitalWrite(10, HIGH);

With this in place, the 32GB card works fine. I added the same code to my application and it also works with the 32GB card.

Not only that, your bench sketch was able to run the card at up to 8MHz on the SEEED W5500 Ethernet Shield. I was only able to get it to run at 4MHz before (and that's probably where I'll leave it since my application doesn't benefit much from higher SD speed).

Thanks again for your time, suggestions & patience. I'll repay you in-kind with contributions to the community as I develop useful tools.

Type any character to start FreeStack: 192128 Type is FAT32 Card size: 31.91 GB (GB = 1E9 bytes)

Manufacturer ID: 0X3 OEM ID: SD Product: SC32G Version: 8.0 Serial number: 0X111A0968 Manufacturing date: 2/2012

File size 5 MB Buffer size 512 bytes Starting write test, please wait.

write speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 320.88,27386,1419,1594 319.10,58408,1418,1603

Starting read test, please wait.

read speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 558.37,1834,908,916 558.37,1835,908,916

Done

On Sat, Sep 1, 2018 at 9:08 AM Bill Greiman notifications@github.com wrote:

I have no idea if any of your tests were meaningful. Did you ever run the SdInfo example?

Warning: Don't try to use the SdInfo code in your apps. It is designed to diagnose problems.

To try the SdInfo example. Use a fresh unmodified version of SdFat. Only make the following mods.

Edit the following. For the AdaFruit WINC1500 shield, the default SD chip select pin is 4 and the default WiFi chip select pin is 10.

Change SS to the SD chip select pin on your shield at line 18. const uint8_t SD_CHIP_SELECT = SS;

Disable the WiFi SPI access. It may interfere since it won't be initialize. Replace the -1 with the WiFi chip select pin in at line 24. const int8_t DISABLE_CHIP_SELECT = -1;

Limit the SPI rate to 4 MHz max by editing line 194 of the example. Replace the 50 with 4. if (!sd.cardBegin(SD_CHIP_SELECT, SD_SCK_MHZ(50))) {

This should work on the Metro since it uses the same initialization and operating rates as the old SD.h library. You should not hit the Metro SPI driver bugs.

SD cards are reliable, that's not your problem. Many billions of devices use modern SD cards. I have the code for Samsung smart phones and other devices. These devices all are reliable because the modern SD card and phone hardware/software conforms to the SD standard and are reliable.

SD shields have been a problem with Arduino since I wrote the first libraries over ten years ago. The 5V to 3.3V signal conversion was first implemented with resistor dividers. I put a scope on the SD card pins and the SPI signals were terrible. I sent traces to Limor Fried at Adafruit and she finally redesigned her shield with semiconductor buffers.

This was fine for AVR boards with a max rate of 8MHz. She tried to design the shield so it would work with 3.3V processors like the Due. This worked because the SPI rate was limited to 4 MHz in the old version of SdFat in SD.h

The Due is capable of 48 MHz and the Metro can run at 24 MHz. The rise time of the buffers on shields with an SD socket are too long for these speeds. These shields must run at slow SPI speeds.

Never use an SPI rate over 12 MHz on the WINC1500. 4 MHz would be better. If you need faster rates get better hardware. Software workarounds never fix bad hardware.

I never use buffered SD sockets on 3.3V boards.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/greiman/SdFat/issues/111#issuecomment-417858555, or mute the thread https://github.com/notifications/unsubscribe-auth/AlmII4ZyHIfQxa9t5IK9MSqNvSH0u7EOks5uWobHgaJpZM4WCn1_ .

SapientHetero commented 6 years ago

Incidentally, my app uses the network libraries before accessing the SD card, so I should not be experiencing the obvious case of having a floating CS line.

On Tue, Sep 4, 2018, 6:08 PM Ron Sutton rongithub@gmail.com wrote:

[ Did you ever run the SdInfo example?] Great question, as it turns out. I had run it with every combination of processor, SD card and SD shield on hand and it . But since then I've combed through your library and both the WINC1500 and Wiznet5500 libraries in some depth, so I d

On Sat, Sep 1, 2018 at 9:08 AM Bill Greiman notifications@github.com wrote:

I have no idea if any of your tests were meaningful. Did you ever run the SdInfo example?

Warning: Don't try to use the SdInfo code in your apps. It is designed to diagnose problems.

To try the SdInfo example. Use a fresh unmodified version of SdFat. Only make the following mods.

Edit the following. For the AdaFruit WINC1500 shield, the default SD chip select pin is 4 and the default WiFi chip select pin is 10.

Change SS to the SD chip select pin on your shield at line 18. const uint8_t SD_CHIP_SELECT = SS;

Disable the WiFi SPI access. It may interfere since it won't be initialize. Replace the -1 with the WiFi chip select pin in at line 24. const int8_t DISABLE_CHIP_SELECT = -1;

Limit the SPI rate to 4 MHz max by editing line 194 of the example. Replace the 50 with 4. if (!sd.cardBegin(SD_CHIP_SELECT, SD_SCK_MHZ(50))) {

This should work on the Metro since it uses the same initialization and operating rates as the old SD.h library. You should not hit the Metro SPI driver bugs.

SD cards are reliable, that's not your problem. Many billions of devices use modern SD cards. I have the code for Samsung smart phones and other devices. These devices all are reliable because the modern SD card and phone hardware/software conforms to the SD standard and are reliable.

SD shields have been a problem with Arduino since I wrote the first libraries over ten years ago. The 5V to 3.3V signal conversion was first implemented with resistor dividers. I put a scope on the SD card pins and the SPI signals were terrible. I sent traces to Limor Fried at Adafruit and she finally redesigned her shield with semiconductor buffers.

This was fine for AVR boards with a max rate of 8MHz. She tried to design the shield so it would work with 3.3V processors like the Due. This worked because the SPI rate was limited to 4 MHz in the old version of SdFat in SD.h

The Due is capable of 48 MHz and the Metro can run at 24 MHz. The rise time of the buffers on shields with an SD socket are too long for these speeds. These shields must run at slow SPI speeds.

Never use an SPI rate over 12 MHz on the WINC1500. 4 MHz would be better. If you need faster rates get better hardware. Software workarounds never fix bad hardware.

I never use buffered SD sockets on 3.3V boards.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/greiman/SdFat/issues/111#issuecomment-417858555, or mute the thread https://github.com/notifications/unsubscribe-auth/AlmII4ZyHIfQxa9t5IK9MSqNvSH0u7EOks5uWobHgaJpZM4WCn1_ .

greiman commented 6 years ago

If you use SPI you must disable all devices on the SPI bus other than the first to be initialized.

So disable the SD if you initialize the WiFi/net first. Some SD card may interfere with the WiFi if SD chip select floats low.

paultanner commented 5 years ago

I'd like to make a further suggestion that there be a simple way of choosing nonstandard pins for all 4 SPI lines. This is useful where the Arduino is a slave to another subsystem and a master to the SD card. This was easy enough to do on the old SD library by adding parameters to begin(). Not sure how best to do it on this one.

greiman commented 5 years ago

I don't support parameters to begin() since this is very slow using software SPI.

There is a faster template version of software SPI. See this example.

This is the key line.

// SdFat software SPI template
SdFatSoftSpi<SOFT_MISO_PIN, SOFT_MOSI_PIN, SOFT_SCK_PIN> sd;

You must edit SdFatConfig.h to enable Software SPI and it will increase the size of the hardware version of SdFat since virtual classes will be used.

The SD chips select is defined in the begin call.