Bug in stm32_adafruit_sd.c (SPI SD CARD)
\STM32Cube_FW_L4_V1.0\Drivers\BSP\Adafruit_Shield\stm32_adafruit_sd.c
Issue with ReadBlocks/WriteBlocks on SDHC cards, offset advances in BlockSize!!! ReadAddr should increment by 1. The current routine delivers junk for multi-sector reads/writes. Please, please, test these things, wasted a lot of time chasing this to ground.
Original code
...
response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, (ReadAddr + offset) * (flag_SDHC == 1 ? 1: BlockSize), 0xFF, SD_ANSWER_R1_EXPECTED);
...
/* Set next read address*/
offset += BlockSize;Suggested fix (I'd probably refactor completely)
...
response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, ReadAddr * ((flag_SDHC == 1) ? 1: BlockSize), 0xFF, SD_ANSWER_R1_EXPECTED);
...
/* Set next read address*/
ReadAddr++; // Block Address
offset += BlockSize;Original code formatted
/**
* @brief Reads block(s) from a specified address in the SD card, in polling mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param ReadAddr: Address from where data is to be read. The address is counted
* in blocks of 512bytes
* @param NumOfBlocks: Number of SD blocks to read
* @param Timeout: This parameter is used for compatibility with BSP implementation
* @retval SD status
*/
uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
uint32_t offset = 0;
uint8_t retr = BSP_SD_ERROR;
uint8_t *ptr = NULL;
SD_CmdAnswer_typedef response;
uint16_t BlockSize = 512;
/* Send CMD16 (SD_CMD_SET_BLOCKLEN) to set the size of the block and
Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_SET_BLOCKLEN, BlockSize, 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
if ( response.r1 != SD_R1_NO_ERROR)
{
goto error;
}
ptr = malloc(sizeof(uint8_t)*BlockSize);
if( ptr == NULL )
{
goto error;
}
memset(ptr, SD_DUMMY_BYTE, sizeof(uint8_t)*BlockSize);
/* Data transfer */
while (NumOfBlocks--)
{
/* Send CMD17 (SD_CMD_READ_SINGLE_BLOCK) to read one block */
/* Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, (ReadAddr + offset) * (flag_SDHC == 1 ? 1: BlockSize), 0xFF, SD_ANSWER_R1_EXPECTED);
if ( response.r1 != SD_R1_NO_ERROR)
{
goto error;
}
/* Now look for the data token to signify the start of the data */
if (SD_WaitData(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ) == BSP_SD_OK)
{
/* Read the SD block data : read NumByteToRead data */
SD_IO_WriteReadData(ptr, (uint8_t*)pData + offset, BlockSize);
/* Set next read address*/
offset += BlockSize;
/* get CRC bytes (not really needed by us, but required by SD) */
SD_IO_WriteByte(SD_DUMMY_BYTE);
SD_IO_WriteByte(SD_DUMMY_BYTE);
}
else
{
goto error;
}
/* End the command data read cycle */
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
}
retr = BSP_SD_OK;
error :
/* Send dummy byte: 8 Clock pulses of delay */
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
if(ptr != NULL) free(ptr);
/* Return the reponse */
return retr;
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
Test fixture

