Corruption caused by writes to SD Card using FatFs with TI Starterware

2.1k Views Asked by At

I have test code that starts with a large existing file on SD Card, test.dat, and the test does this:

f_open(&fp, "test.dat", FA_OPEN_ALWAYS|FA_READ|FA_WRITE);
f_write(&fp, bufferOfZeros, 4096, &ioBytes);

Seems straight forward.

The result of the f_write is SD Card corruption.

I've traced the EDMA on my embedded device to watch FatFs read/write requests. The f_open read requests are all healthy, they properly find the file and FAT table.

The f_write starts by reading the first sector into scratch buffer, great. Then it memcpy's the zeros into the scratch buffer, great. After memcpy of 512 zeros, it needs to commit the sector and move to the next one.

It's at this point where the code is confused. It writes that scratch buffer of zeros to the FAT table!!

The offending code in ff.c/f_write() is:

        if (fp->flag & FA__DIRTY) {     /* Write-back sector cache */
            if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
                ABORT(fp->fs, FR_DISK_ERR);
            fp->flag &= ~FA__DIRTY;

Here, fp->buf is the sector buffer of zeros, but fp->dsect is the FAT sector (8318), not the file data sector (10240)! Oops. At disk_write() fp->buf matches fp->sect.

Seems like a basic use case here, I am shocked to see this.

I'm hoping someone in the world has anyone dug into a problem like this before with FatFs?

1

There are 1 best solutions below

1
On

Clifford is correct - it's a problem on my end, and I knew such a simple use case has to work.

I switched the test to

f_open(&fp, "test.dat", FA_OPEN_ALWAYS|FA_READ|FA_WRITE);
f_write(&fp, pattern, 512, &ioBytes);
f_lseek(&fp, 0);
f_read(&fp, zeroedBuffer, 512, &ioBytes);

This revealed a caching problem. The f_read operation succeeded, and the DMA completed fine, but zeroedBuffer remained unmodified because L0 was not flushed. Therefore, FatFs was seeing a mix of correct values and stale values. I fixed EDMA caching and now it all works.

Another learning, TI Starterware comes with R0.4b. I started with that, and it returned FR_RW_ERROR that was perplexing. I moved up to R0.11a and got much better error feedback.

Anyone know of unit tests for FatFs?