SD card initialization fails on custom PCB

I designed my own PCB with a built-in SD card reader, but I'm having trouble reading the SD card. I can’t figure out what’s causing the issue.
Could someone help me identify the problem?

I bought this module on AliExpress to read the SD card, and with the code below it works perfectly:

#include <Arduino.h>
#include <SD.h>
#include <SPI.h>

#define CS 4
#define MOSI 5
#define CLK 18
#define MISO 19

void setup() {
    Serial.begin(115200);
    delay(1000);
    Serial.println("\n--- ESP32 SD Card Test ---");

    pinMode(CS, OUTPUT);
    digitalWrite(CS, HIGH);
    delay(10);

    // Initialize SPI (software SPI)
    SPI.begin(CLK, MISO, MOSI, CS);

    // Initialize SD with a lower clock speed (400 kHz)
    if (!SD.begin(CS, SPI, 400000)) {
        Serial.println("❌ Error: SD card not found or not initialized!");
        return;
    }

    Serial.println("✅ SD card initialized successfully!");

    File file = SD.open("/test.txt", FILE_WRITE);
    if (!file) {
        Serial.println("❌ Error opening or creating test.txt");
        return;
    }

    file.println("Hello, world!");
    file.close();
    Serial.println("✅ File test.txt written successfully.");

    file = SD.open("/test.txt");
    if (file) {
        Serial.println("📂 File content:");
        while (file.available())
            Serial.write(file.read());
        file.close();
        Serial.println("\n✅ Reading completed.");
    } else {
        Serial.println("❌ Error opening test.txt for reading.");
    }
}

void loop() { delay(1000); }

Then I tried running the exact same code on my custom PCB, but it fails during SD.begin(CS, SPI, 400000).

Here’s the schematic of my PCB:

I’ve seen some people recommending not to use a pull-up resistor on the Chip Select (CS) line, while others say only SCLK should have one. I’m completely confused at this point.
Does anyone know what the real issue might be?

I tried to do some reverse engineering on the SD card module I bought from AliExpress, and it seems that MISO, SCLK, and MOSI all have pull-ups, while CS is left floating.
I tested the same configuration on my PCB by removing the pull-up resistor from CS, but it still doesn’t work.

Any ideas?

Hardware:

I'm going to assume that your custom PCB is just a uSD breakout and nothing more. Correct me if I'm wrong, please.

Two questions pop to mind.

  1. Why did you ground both CD lines? I don't think it has anything to do with why it's not working, I just found it odd.
  2. Are you 150% positive that you didn't get the pin numbering backwards on the card socket? Have you had someone else look at your Gerbers? I only ask because been there, done that, got the t-shirt, kicked myself, redid the PCB.

This is what i have and works (on an ESP32)

I started out with something (almost) the same and reverse engineered that to come to what i have

Differences i see is that i have DAT2 Pulled up and CS free-floating. Also don't have the shield Grounded but rather free-floating (there is a copper-fill plane on the bottom side om my PCB that is connected to the shield of the card-holder to complete the shielding.

I assume you are using the same SD card.

Yes we need to have a look. Even just a relevant section of the connections in the PCB editor will do.
Also please check all connections with a DMM from the pins of the card holder to the pins of the ESP.
Cardholders are not that easy to solder. (or did you do PCB assembly ?)

When i built my PCB's i actually first built a complete prototype of the SD connections just on experimentation board and connected that to my ESP32 to make sure it all worked first.

The socket you have has 8 pins, the one in the schematic shows 12 pins and the one on the module you bought has 10 pins. Think you could have made a mistake somewhere?

Thank you for the fast response!

As for the Gerbers, I can upload the EasyEDA pcb file here if that helps.

I’m using EasyEDA, which has the LCSC component library integrated, so it already provides the symbol (for the schematic) and the footprint (for the PCB).
Still, I had the same doubt myself and I’ve already double-checked them, they are correct.

I soldered everything myself, but I double-checked all the connections with a DMM in continuity mode between the pins of the microSD socket and the pins that should go to the ESP32, everything checks out correctly.

I also did some resistance measurements with the DMM, and something strange happened: with everything disconnected (no power and no ESP32), the pull-up resistors on the MISO, MOSI, and CS lines were steady at 10 kΩ, but the SCLK line started around 7 kΩ and slowly increased, as if there were a capacitor charging. I don’t really understand why that happens.

I even desoldered the resistor and measured it separately, it was 10 kΩ as expected. Just to be sure, I replaced it with a new one, but the behavior was exactly the same.

If you need any more information, just ask, I’m quite frustrated at this point. I’ve done countless tests and still can’t find a solution.

I’m not sure which lines you’re referring to. If you mean the ones on the left side of the symbol, I interpreted them as GND. The datasheet doesn’t mention anything about card detection.

There is the extra switch pin (9) which isn't connected on the module either.
The other extra pin is connected to the shielding.
(not even sure what that is for btw, since there is only 8 pins on a Micro-SD)

The footprint from the card holder link shows 8 pins and 4 more for the shield
The difference seems to be that they may not be individually numbered.

A screen shot of the relevant connections is what i was hoping for. Either something in a gerber viewer or just from the PCB editor.

I was as confused about the conflicting info i found. I think it's fine to have an extra pullup on CS, since it's an active LOW pin. (eg. !CS) As i said before i have a pullup on pin 1 of the SD, and if you check the module you have i think you'll find it has one as well.

Does anything on that board work?
Can you make an LED blink?

10mil traces for power and ground will certainly cause problems.

Yes, everything works except the microSD card, which I can’t read.
Anyway, during testing I’m not powering it from the 5V on the PCB, but through the ESP32 via USB.

And you get 3.3v from that i guess, yes that should be ok.

excess flux underneath the resistor ?

Besides the poor layout, the only thing I can see that may cause a problem is that GPIO5 is a strapping pin and outputs some glitches during boot.

Ok, since I’ll be making another version and I’m new to PCB design, what advice can you give me to improve the PCB layout?

Regarding GPIO5, to check if it’s causing the problem, would adding a long delay during setup() , like 10 seconds just for testing, temporarily solve the issue?

Could be, but I’ve soldered it twice, so it seems unlikely that I applied too much both times.
Anyway, thanks for the suggestion, I’ll pay more attention and try using less flux.

No the glitch happens when the chip boots, before any code is executed.
You could apply power the insert the card afterwards.

Ok, thanks! I’ll try that soon and let you know the results.

I use solder that has flux included.

It is hardly an expected issue. Those are the default SPI pins and do not normally cause any issue.
Regardless those issues should have shown up using the SD-module as well.
Alternately you can define your own specific pins if you want to,
GPIO 5 is a strapping pin, but it's function is a little unclear to me. You have it pulled up, but i am fairly sure there is an internal pullup already as well,

Did you also check for shorts between the SD socket pins ?
Do you have a solder pump to remove any excess ?

You say thay it works but I would make the power and ground traces as fat as possible. The ESP can draw several hundred milliamps and also the SD card can draw up to 100mA

I don't know what esle is on the board but 10 mil traces for power and ground is not enough.

Also, why not use the the standard SPI pins, that would eliminate one possible problem.

Ok, thanks for the hint.

Honestly, I didn’t think too much about it because I saw online that the ESP has a pin matrix and almost all pins can be reassigned. I did it this way just to make routing the traces easier, but in the next version I can just use the default SPI pins.

Yes, I’ve checked for shorts between all adjacent pins and there aren’t any shorts on the microSD card socket.

Yes

Yes, I thought the same, because when I tested the module I bought from AliExpress, I obviously connected it to the same pins that are also used on the PCB.
As I mentioned before, the module works perfectly without any problems.

Well not obvious to me.
I would not do anoher PCB without solving this problem.

Sorry for omitting this detail. Anyway, yes, I’m waiting to solve the problem before making another version.
At the moment, however, I don’t know how to connect the socket pins to a breadboard to test custom configurations.

Can you post a schematic of the entire design.