Skip to main content
Visitor II
January 22, 2020
Solved

Fatfs DMA transfer skips the end

  • January 22, 2020
  • 2 replies
  • 847 views

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.

    This topic has been closed for replies.
    Best answer by Tesla DeLorean

    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.​

    2 replies

    Graduate II
    January 22, 2020

    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.​

    TGeof.1Author
    Visitor II
    January 22, 2020

    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 !