Data corrupted when STM32G051 communicates to MicroSD in SPI mode
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?
