2026-04-07 6:56 AM - last edited on 2026-04-07 7:01 AM by Andrew Neil
Hi,
I am writing firmware to read and write to a MicroSD card in SPI mode using an STM32G051F8P6.
Card initialization, performed in the order of CMD0, CMD8, CMD55 and ACMD41, CMD58, works correctly. However, when I then try to read the first sector with CMD17, incorrect data is read.
The table below extracts the values from bytes 446-461, which contain information about the first partition, from the sector read values with the first byte set to 0.
The top row shows the data written to the MicroSD card as read by FTK, and the bottom row shows the values actually read by CMD17. In both cases, bytes 510-511 are 0x55 and 0xAA, satisfying the data requirements for the first sector.
| Bytes | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 |
| Correct Data | 0x00 | 0x82 | 0x03 | 0x00 | 0x0C | 0xFE | 0xFF | 0xFF | 0x00 | 0x20 | 0x00 | 0x00 | 0x00 | 0xDC | 0xD1 | 0x01 |
| CMD17 Result | 0x00 | 0x02 | 0x04 | 0x00 | 0x06 | 0x18 | 0xD8 | 0xC8 | 0x81 | 0x00 | 0x00 | 0x00 | 0x7F | 0x93 | 0x3B | 0x00 |
The analysis results from the logic analyzer are shown in the following image, and a response to CMD17 has been received.
The source code is fully available on GitHub at nnm-t/stm32g051f8p6-visitor-counter. Here is an excerpt from FATFS/Target/fatfs_sd.c, which sends CMD17.
SD_Status SD_disk_read_blocks(BYTE* buff, DWORD sector, UINT count)
{
if (!count)
{
return SD_ERROR;
}
if (count == 1)
{
if (!sdhc)
{
sector *= 512;
}
SPI_cs_select();
// todo: The retrieved data is corrupted
BYTE cmd17_res = SD_send_cmd(CMD17, sector);
if (cmd17_res != 0x00)
{
SPI_cs_deselect();
return SD_ERROR;
}
uint8_t token;
uint32_t timeout = HAL_GetTick() + 200;
do
{
token = SPI_rx_byte();
if (token == 0xFE)
{
break;
}
}
while (HAL_GetTick() < timeout);
if (token != 0xFE)
{
SPI_cs_deselect();
return SD_ERROR;
}
SPI_rx_buffer(buff, 512);
SPI_rx_byte();
SPI_rx_byte();
SPI_cs_deselect();
SPI_tx_byte(0xFF);
return SD_OK;
}
return SD_disk_read_multi(buff, sector, count);
}
The strange thing is the SPI settings. The SD card specifications state that the SPI mode should be Mode 0, but in reality, communication fails on the first CMD0 if it's not Mode 3. Also, communication is not possible unless the SPI clock is set to 1MHz or higher (in this case, 32MHz (MCU) / 8 = 4MHz (SPI)).
The pin assignments and SPI settings are as shown in the diagram.
The circuit being debugged is as shown in the diagram, and all signal lines on the MicroSD card except SCK (including DAT2 and DAT3, which are not used in SPI mode) are pulled up with 10kΩ resistors.
I've tried adjusting the settings based on the FatFs_uSD_Standalone sample from STMicroelectronics/STM32CubeG0 and stm32g0xx_nucleo.c from STMicroelectronics/stm32g0xx-nucleo-bsp, but I'm still unable to get the MicroSD card to read correctly.
What are some possible causes and solutions?
2026-04-07 7:22 AM
Hello @nnm_t
You should use the SPI mode 0 as stated in SD card specification.
2026-04-08 9:08 PM
@Saket_Om -san,
Hmm, I did try setting the SPI mode to Mode 0 as per the SD card specifications, but the communication failed at the initial CMD0 transmission stage.
2026-04-09 12:13 AM
Have you looked into the low-level communication, were and why exactly the CMD0 transfer fails ?
The schematics look reasonable, and 4MHz SPI clock should not be a problem, assuming the PCB traces are not too long. And since the SPI signals are associated, the PCB traces should have about the same length and characteristic impedance. At 4MHz, series resistors are probably not necessary - although I'm no hardware guy.
And because if somewhat mixed experiences with MCU SD card interfaces in the past, have you tried different SD cards, of different (storage) size ?