2020-01-22 03:48 AM
Hi,
I'm having a very strange issue loading bytes from an SD card into an array in RAM, on a STM32F722RE.
In general, it works nicely, but I have several files where the transfer skips some bytes, leaving zeroes in the destination array.
In debug, I have found the following clues:
1. I'm calling f_read:
if (f_read(file, raw_bytes_buffer.data() + write_offset_in_bytes, bytes_to_read, &bytesread) != FR_OK) return;
2. In f_read, the array is correctly filled up until the index 473.
3. At index 474, the FIL->fptr is exactly 512. This triggers a particular branch in f_read:
// ff.c
if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
This particular branch seems to be the culprit in all cases of this "missing bytes" bug.
4. A function pointer is used to read the disk:
// ff.c
if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
5. disk_read points to the following function
// bsp_driver_sd.cpp
uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
6. This function in turn calls the following:
HAL_SD_ReadBlocks_DMA(&_HSD, (uint8_t *) pData, ReadAddr, NumOfBlocks)
7. After completion of the transfer in DMA, indices from 474 to 983 are filled, however indices 984 and 985 are still zeroed (note: After checking manually, the file does *not* have zeroes at this position, obviously)
8. f_read increments the write pointer, and now points to index 986.
TL;DR: f_read tries to read a whole SD sector with DMA, and does not write the last two bytes of said sector to the destination array.
Solved! Go to Solution.
2020-01-22 05:36 AM
Make sure memory used by DMA is aligned.
If not using DTCMRAM for DMA buffering make sure you correctly handle cache coherency.
Watch for the 32-byte alignment of By_Addr cache coherency functions.
2020-01-22 05:36 AM
Make sure memory used by DMA is aligned.
If not using DTCMRAM for DMA buffering make sure you correctly handle cache coherency.
Watch for the 32-byte alignment of By_Addr cache coherency functions.
2020-01-22 08:39 AM
It was an alignment issue. The destination pointer pointed to
raw_bytes_buffer.data() + write_offset_in_bytes
And write_offset_in_bytes was not a multiple of 8. Changing the code so that it always is fixed the problem.
Thanks !