greiman / SdFat

Arduino FAT16/FAT32 exFAT Library
MIT License
1.09k stars 512 forks source link

Long timeout calling begin() on Teensy 4.1 when no card present #479

Open noisymime opened 7 months ago

noisymime commented 7 months ago

Calling sd.begin() on a Teensy 4.1 without a card present appears to take 2 seconds before it times out and the call returns. Compare this to a Teensy 3.5 where if no card is inserted then the call to .begin() appears to return immediately.

This 2s timeout is nearly double the time the call takes when a card is present (Around 1.1s in my testing).

Is it possible to reduce this time on Teensy 4.1 or otherwise detect in advance whether a card is inserted? I'm currently calling this on startup in a sketch, but having a 2s delay when booting isn't ideal.

greiman commented 7 months ago

The timeout likely occurs in one of two places, here or here.

You can try adjusting them here.

I don't want to change them since some older cards are detected by CMD8 failure and older cards take longer to init by ACMD41. If you only use newer cards, smaller values should be OK.

noisymime commented 7 months ago

Thanks for that, I'll give those a try!

Any idea what the difference is between the Teensy 3.5 and 4.1 is on this front? The 3.5 seems to be nearly instant if no card is present, so it was surprising to see the much longer timeout on the 4.1. I had assumed they would be quite similar.

greiman commented 7 months ago

Any idea what the difference is between the Teensy 3.5 and 4.1 is on this front?

The controllers are very different. Notice all the defined macros in the driver:

    Line   25: #if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__)
    Line   77: #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line   96: #elif defined(__IMXRT1062__)
    Line  119: #endif  // defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  326: #if defined(__IMXRT1062__)
    Line  333: #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  358: #elif defined(__IMXRT1062__)
    Line  372: #if defined(ARDUINO_TEENSY41)
    Line  374: #else   // defined(ARDUINO_TEENSY41)
    Line  376: #endif  // defined(ARDUINO_TEENSY41)
    Line  413: #endif  // defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  426: #if defined(__IMXRT1062__)
    Line  433: #endif  // defined(__IMXRT1062__)
    Line  491: #if defined(__IMXRT1062__)
    Line  595: #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  598: #endif  // defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  612: #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  615: #endif  // defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  866: #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  873: #else   // defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  875: #endif  // defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  968: #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line  974: #endif  // defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line 1010: #if defined(__IMXRT1062__)
    Line 1013: #else   // defined(__IMXRT1062__)
    Line 1016: #endif  // defined(__IMXRT1062__)
    Line 1105: #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line 1112: #endif  // defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Line 1161: #if defined(__IMXRT1062__)
    Line 1164: #else   // defined(__IMXRT1062__)
    Line 1167: #endif  // defined(__IMXRT1062__)
    Line 1175: #endif  // defined(__MK64FX512__)  defined(__MK66FX1M0__) defined(__IMXRT1062__)

Also there are no pull-ups on the SD socket which seems to cause more problems on the 4.1 with no card.

PullUp

noisymime commented 7 months ago

Thanks Bill, really appreciate the reply. I did see there were a lot of differences in the driver itself, but the logic used in the begin() function seemed largely the same between the 2 (ie both use the same number of retries and timeout duration) so I wasn't sure whether the difference amounted to a hardware one or not.

You can try adjusting them here.

Can confirm that this does indeed change the delay. With no card present, the time the begin() call takes is always (CMD8_RETRIES-1)*BUSY_TIMEOUT_MICROSuS on the 4.1, which explains the 2s I'm seeing.

It would be great if these variables were made externally available or were an optional parameter on the begin() function, but understand that's probably not something you'd want to add.

greiman commented 7 months ago

It would be great if these variables were made externally available or were an optional parameter on the begin() function, but understand that's probably not something you'd want to add.

I have installed board support packages for several hundred boards on my development machine. I have a large bookcase with plastic shoe-boxes full of boards that have been sent to me. It is truly impossible to satisfy all the request I get to expose options people ask for.

There are almost 500 forks of SdFat. Many of these are to install special options.