Access SD Card with Raspi Pico SPI blocks usable, but CSn probably not, because SD card SPI protocol requires CE from start to end of command. Some cards are more forgiving, SanDisk is not. Test Setup spi0 and Pins 4 to 7. Pullup for Tx and Rx 47k clock line inverted, data sampling on 2nd edge: spi_set_format(spi, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST); or spi_set_format(spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); works too SD card adapter with Vreg and LVHC245 buffer: does not work. Should retry with 5V!! worked just enough to get CMD0 passed but CMD8 was not properly detected by Intenso and Kingston card which worked as SCSDv1 with 1GB (instead of 4GB) SanDisk didn't respond to CMD0 SD card adapter with just a few R and C: works. Intenso and Kingston fully ok, SanDisk failed at ACMD41 for initialization. Examine the SanDisk Problem I tried a lot and sometimes the SanDisk cards got farther, sometimes stuck already at CMD0. There were a multitude of problems: if a test fails then you should power-cycle the card. always! remove, wait 2sec, insert again. Often the cards go into an erronous or fail-safe state and don't react any more. the SanDisk cards take some time (~5sec) to initialize after insertion. They to respond to commands but the initialization command ACMD41 will not return ready until the power-up initialization was done. So if issued immediately after power-up allow for several seconds before timeout. the SanDisk cards sometimes fail to synchronize their SPI data flow with the CS signal, which should be activated only before the start of a new command. Though the serial stream looks like having a start and a stop bit it is defined to transfer 8-bit bytes and CS is used to synchronize on the byte boundary. But sometimes the SanDisk SD cards fail to do so and this is weird. The commands CMD0 (reset), CMD8 (get IF config), CMD58 (read OCR) and CMD59 (set crc) normally work but when it comes to ACMD41 (initialize) things go wrong. Initially i got weird errors, varying with each modification to the test setup, until i found out, that the card replies with with it's byte boundary shifted by some bits, during the last tests by 4 bit. It also received the commands shifted by 4 bits, which lead to either a CRC error, if CRC was enabled with CMD59 or execution of whatever it saw in this shifted data stream and subsequently to no more reaction to commands sent. The returned result R1 was of course not successfully decoded by the test program which stopped with this error condition. One interesting fact was that the card failed after the 2nd command in ACMD41, which consists of 2 commands (CMD55 and CMD41). This was probably because i had already had implemented a retry for a CRC error: CMD55 was sent, returned CRC error, was sent again, shifting the receiver on the SanDisk SD card by another 4 bit, now it did decode properly, CMD41 was sent and had a CRC error again. Or CRC was not enabled and strange commands were executed and the card went into an illegal state. I wrote an individual ACMD41 handler so that i could make deeper tests. I sent CMD55 + CMD55 + CMD41 without CRC test - and i got a proper reply from the card! But sometimes no reply at all. Or it timed out during initialization. SanDisk ... eject, wait 2sec, insert, wait 5sec, retry. Finally i sent 8 clock cycles (1 dummy byte) before the command while CS was inactive, activated CS and sent the command in the normal way. This worked! It seems the SanDisk cards detect CS change only when they refill their SPI shift register. Then they see the state change and reset the shift register, but at this time the host already started sending the command. So the receiver is de-synchronized. Or however their receiver works. But SanDisk were the only cards so far which exposed this problem and frequently popup in google searches to SPI problems. Initialization Sequence used Work with slow data rate Deselect card Send 80 pulses Select card CMD0 GOTO_IDLE_STATE: CRC must be valid. The SD Card is powered up in SD mode. It enters SPI mode if the CS signal is asserted during the reception of the reset command. Expected response: R1 = 0x01 = IdleState Deselect card Select card CMD8 SEND_IF_COND: CRC must be valid. Activates SDHC++ in card. Without CMD8 card remains in standard capacity mode. Response used by host to distinguish between SD v1 and SD v2. Also used to check 2.7 - 3.6V supply voltage support, but this is required by the standard anyway, so no need to verify. argument: bits [11:8] supply voltage "VHS": 0b0001 = 2.7-3.6V bits [7:0] check pattern = 0xAA Expected response: R7 = R1 + 0x000001AA = same as sent If the card does not understand the command (response R1 = IllegalCommand) then it is a standard capacity SD card, else SDHC or better. Deselect card Select card CRC may be any value with lsb=1 CMD58 READ_OCR: read OCR to check voltage (optional because 3.3V is required) Deselect card Select card CMD59 CRC_ON_OFF: CRC may be any value with lsb=1 Enable CRC This prevented the SanDisk cards from executing commands read while misaligned Deselect card Select card ACMD41 SD_SEND_OP_COND: Argument = 1<<30 Tell card that host supports SDHC mode (bit30=1) and start card initialization. This command must be repeated as long as the car returns R1 = 0x01 = IdleState. This may take several seconds. Deselect card Select card CMD58 READ_OCR: Read OCR again to get CCS "Card Capacity Status". CCS is valid when the card accepted CMD8 and after the completion of initialization. Returns R7 reply. Card is a SDHC card or better if bit30 in reply R7 is set. SDHC cards use block addressing, while standard capacity cards used byte addresses. Deselect card Select card CMD16 SET_BLOCKLEN: Argument = 512 If card is a standard capacity card, then set the block length to 512. Most SCSD cards allow reading parts of a block, but the added code to exploit this feature is large compared to benefit which is little because there are no longer many SCSD cards around. So let's use them in the same way as SDCH cards only. Deselect card Select card CMD9 SEND_CSD: Retrieve the Card Specific Data register. The card sends back a Data Token, 16 byte of data and a CRC16 checksum. The data itself has a CRC7 checksum too. The CSD contains many card metrics and varies from version 1 (SCSD cards) to version 2 (SDCH cards) in many fields. It tells card capacity, block size and max. data rate. Deselect card Select card CMD10 SEND_CID: Retrieve the Card Identification register. The card sends back a Data Token, 16 byte of data and a CRC16 checksum. The data itself has a CRC7 checksum too. The CID contains information about manufacturer, manufacturing date and a card srial number. At least it should. Deselect card Set data rate to supported maximum.