2018-02-02 12:28 PM
\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
2018-02-04 07:57 AM
Large f_read()/f_write() used against the FatFs library will propagate to the DISKIO layer as reads/writes where count>1
Failure can be observed in a file CRC routine if >=1024 byte blocks are read vs 512 byte blocks. Different CRC values will be observed in 512, 1024, 4096-bytes/block, etc, passes of the file.
2018-02-06 06:13 PM
Here is some test code to exercise FatFs. Pick a large file, and have a large enough heap to permit allocations for large block reads.
//******************************************************************************
// CRC File Intergrity Check - sourcer32@gmail.com
//******************************************************************************
uint32_t CRC32(uint32_t Crc, uint32_t Size, uint8_t *Buffer)
{
while(Size--)
{
static const uint32_t CrcTable[] = { // Nibble table for 0xEDB88320 polynomial
0x00000000,0x1DB71064,0x3B6E20C8,0x26D930AC,0x76DC4190,0x6B6B51F4,0x4DB26158,0x5005713C,
0xEDB88320,0xF00F9344,0xD6D6A3E8,0xCB61B38C,0x9B64C2B0,0x86D3D2D4,0xA00AE278,0xBDBDF21C };
Crc = Crc ^ (uint32_t)*Buffer++; // Apply byte
Crc = (Crc >> 4) ^ CrcTable[Crc & 0x0F]; // Two rounds of 4-bits
Crc = (Crc >> 4) ^ CrcTable[Crc & 0x0F];
}
return(Crc);
}
//******************************************************************************
uint32_t CrcFile(char *Filename, uint32_t BufferSize)
{
FRESULT res;
FIL fil;
uint32_t Crc = 0xFFFFFFFF;
uint32_t Align = 32;
uint8_t *p = malloc(BufferSize + Align);
while((p == NULL) && (BufferSize > Align))
{
BufferSize >>= 1;
p = malloc(BufferSize + Align);
}
if (p)
{ // Align IO Buffer
uint8_t *Buffer = (uint8_t *)(((uint32_t)p + (Align - 1)) & ~(Align - 1));
res = f_open(&fil, Filename, FA_READ);
if (res != FR_OK)
printf('res = %d f_open %s
', res, Filename);
if (res == FR_OK)
{
uint32_t Size = f_size(&fil);
while(Size) // Process until all consumed
{
UINT BytesRead;
res = f_read(&fil, Buffer, BufferSize, &BytesRead);
if (res != FR_OK)
{
printf('res = %d f_read %s
', res, Filename);
break;
}
Crc = CRC32(Crc, BytesRead, Buffer);
Size -= BytesRead;
}
res = f_close(&fil);
if (res != FR_OK)
printf('res = %d f_close %s
', res, Filename);
}
printf('CRC32 %08X PKZIP %08X %s
', Crc, ~Crc, Filename);
free(p);
}
return(~Crc);
}
//******************************************************************************
void TestFile(char *Filename)
{
uint32_t Crc;
Crc = CrcFile(Filename, 512);
if (CrcFile(FileName, 1024) != Crc)
puts('!!FAIL!!');
if (CrcFile(FileName, 4096) != Crc)
puts('!!FAIL!!');
if (CrcFile(FileName, 8192) != Crc)
puts('!!FAIL!!');
}
//******************************************************************************
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-03-15 04:18 AM
Hi Clive,
The issue you highlighted was reported internally and confirmed. The fix will be available in coming versions of the STM32CubeL4 package.
-Amel
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2018-07-26 05:51 AM
Hi @Community member ,
Please note that a fix is applied to BSP_SD_ReadBlocks and BSP_SD_WriteBlocks in order to support SDHC cards. Updated stm32_adafruit_sd.c is available in the last version of STM32CubeL4 package (1.12.0) .
-Amel
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-06-04 08:52 AM
There is a problem with sd_spi implementation in stm3210c-eval-bsp/stm3210c_eval_sd.c The fix related to thread is applied only on Drivers/BSP/Adafruit_Shield/stm32_adafruit_sd.c not on evalboard BSP. Please fix this.