Hi,
I'm playing around with porting SQLite to this board. I'm using Chibi-18.2.1, since there were some changes to make SDMMC2 run smoothly out of the box in the 18.x.y series.
I am noticing that the disk IO keeps getting corrupted. It appears that if I call f_write/f_read with sizes that aren't multiples of block size (512) the data gets written or read incorrectly.
To test, I boiled it down to a simple loop that attempts to write a sequence of bytes that's not a multiple of 512, and read it back verifying that it's the same sequence I wrote.
This doesn't pass.
To be clear I'm not talking about STM32_SDC_SDMMC_UNALIGNED_SUPPORT. The byte buffer is always aligned (and I have DBG checks enabled for that). I am writing/reading non sector size number of bytes in each call to f_write and f_read.
Is this a known bug? Common problem? I'm 99% sure that I didn't see this issue before when I played with disk stuff before, but that was using the SPI MMC driver, different Chibi, and whatever fatfs came with the 16.x.y series.
SDMMC2 on STM32F769NI Discovery
Moderators: RoccoMarco, barthess
- Giovanni
- Site Admin
- Posts: 14444
- Joined: Wed May 27, 2009 8:48 am
- Location: Salerno, Italy
- Has thanked: 1074 times
- Been thanked: 921 times
- Contact:
Re: SDMMC2 on STM32F769NI Discovery
Hi,
Never seen this but I don't use FatFS much, the SDC driver only handles 512 bytes blocks so it could be something in FatFS, it is there that small writes should be buffered.
Corrupted how exactly? data missing, shifted, masked?
Giovanni
Never seen this but I don't use FatFS much, the SDC driver only handles 512 bytes blocks so it could be something in FatFS, it is there that small writes should be buffered.
Corrupted how exactly? data missing, shifted, masked?
Giovanni
- wurstnase
- Posts: 121
- Joined: Tue Oct 17, 2017 2:24 pm
- Has thanked: 43 times
- Been thanked: 30 times
- Contact:
Re: SDMMC2 on STM32F769NI Discovery
Probably I'm wrong, but isn't the write access buffered? AFAIK you need to close file and/or unmount the SD card. Like Windows "secure remove".
When you try to write and read immediately in size smaller then the SD card buffer, you will not read the same, because it hasn't been written finally.
When you try to write and read immediately in size smaller then the SD card buffer, you will not read the same, because it hasn't been written finally.
\o/ Nico
Re: SDMMC2 on STM32F769NI Discovery
Have you considered memory caching in your driver? Unless you can guarantee that data is always in non-cacheable RAM (and I'm not sure that you can), this is necessary.
- Giovanni
- Site Admin
- Posts: 14444
- Joined: Wed May 27, 2009 8:48 am
- Location: Salerno, Italy
- Has thanked: 1074 times
- Been thanked: 921 times
- Contact:
Re: SDMMC2 on STM32F769NI Discovery
steved wrote:Have you considered memory caching in your driver? Unless you can guarantee that data is always in non-cacheable RAM (and I'm not sure that you can), this is necessary.
Good point.
Giovanni
Re: SDMMC2 on STM32F769NI Discovery
Giovanni wrote:
Never seen this but I don't use FatFS much, the SDC driver only handles 512 bytes blocks so it could be something in FatFS, it is there that small writes should be buffered.
Giovanni
I agree, I did a quick inspection of the fatfs code and it seems to only write sectors when they are full, or upon f_sync/f_close and it writes a full sector even if it has not been filled (the filesystem takes care of how much is valid). That being said, it could have a bug.
Giovanni wrote:Corrupted how exactly? data missing, shifted, masked?
Giovanni
It's weird, when I read it in the debugger in-situ, it seems like it is all numbers I wrote, but wrapped around after it fails comparing the 3rd chunk. However, if I unmount the card and read it on my PC with a hex editor, what is on the disk starts with my sequence, then has garbage in it (including a lot of 0x55555555 which looks like it has written memory that the stack filler initialized).
I will attach the shortest example I can come up with. It was based on the LWIP-FATFS-USB demo, and then pared down and modified to run on my F749 discovery. You could easily modify it to run on another board, but would need to change to SDMMC1 probably. If you change #define CHUNKSIZE from 406 to 4096, it works as expected. Just unzip it into the top folder of ChibiOS-18.2.0 (and unzip ext/fatfs as well).
Also note, I have ffconf.h set up for multipartition since my card has a partition table on it. You might need to switch that, and the second argument f_mount call if you have a more traditional non-partitioned sdcard.
Dave
Re: SDMMC2 on STM32F769NI Discovery
wurstnase wrote:Probably I'm wrong, but isn't the write access buffered? AFAIK you need to close file and/or unmount the SD card. Like Windows "secure remove".
When you try to write and read immediately in size smaller then the SD card buffer, you will not read the same, because it hasn't been written finally.
Thanks for the suggestion Nico, but I don't think this is the case. The issue happens even if I just call f_write without reading it back, and then unmount the card properly. When you call f_read, the fatfs layer should be smart enough to take care of what is buffered, and what needs to be read off the disk. Just to be pedantic, I added a f_sync() call between each write/read to no avail either.
Dave
Re: SDMMC2 on STM32F769NI Discovery
Giovanni wrote:steved wrote:Have you considered memory caching in your driver? Unless you can guarantee that data is always in non-cacheable RAM (and I'm not sure that you can), this is necessary.
Good point.
Giovanni
Hmm, steved is on to it!
I noted that in the STM32F76xxI.ld file, that the main stack and BSS are in ram3 which is DTCM ram. The HEAP is in regular SRAM. If I changed the buffer in my main.c from in BSS to be malloc'd, the problem disappears.
Not sure what that totally implies, but it will help Giovanni I'm sure.
- Giovanni
- Site Admin
- Posts: 14444
- Joined: Wed May 27, 2009 8:48 am
- Location: Salerno, Italy
- Has thanked: 1074 times
- Been thanked: 921 times
- Contact:
Re: SDMMC2 on STM32F769NI Discovery
hi,
It is because BSS is allocated (by default) in a non-cached RAM, this way the problem is less impacting on developers but it is there. I cannot put everything in the fast RAM because it is not so big.
There is already a bug opened about FatFS and caching, probably it will get a more general solution at some point.
See the linker script to understand how the various areas are assigned to the various RAMs, there is a lot of space for tweaking.
Giovanni
It is because BSS is allocated (by default) in a non-cached RAM, this way the problem is less impacting on developers but it is there. I cannot put everything in the fast RAM because it is not so big.
There is already a bug opened about FatFS and caching, probably it will get a more general solution at some point.
See the linker script to understand how the various areas are assigned to the various RAMs, there is a lot of space for tweaking.
Giovanni
Re: SDMMC2 on STM32F769NI Discovery
I just modified the FatFs diskio.c file to manage the buffer flushing:
Not sure whether there's any advantage to checking whether the buffer is in cached RAM, but it didn't seem to do any harm.
I've also adjusted my malloc() to assign memory starting on 32-byte boundaries (i.e. cache lines)
Code: Select all
DRESULT disk_read (
BYTE pdrv, /* Physical drive number (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..255) */
)
{
switch (pdrv) {
#if HAL_USE_SDC
case LOGICAL_SDC :
if (blkGetDriverState(&SDCD1) != BLK_READY)
return RES_NOTRDY;
if (buff > (BYTE *)&(__ram3_end__))
dmaBufferInvalidate(buff, count * MMCSD_BLOCK_SIZE);
if (sdcRead(&SDCD1, sector, buff, count))
return RES_ERROR;
return RES_OK;
#endif
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if !FF_FS_READONLY
DRESULT disk_write (
BYTE pdrv, /* Physical drive number (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..255) */
)
{
switch (pdrv) {
#if HAL_USE_SDC
case LOGICAL_SDC :
if (blkGetDriverState(&SDCD1) != BLK_READY)
return RES_NOTRDY;
if (buff > (BYTE *)&(__ram3_end__))
dmaBufferFlush(buff, count * MMCSD_BLOCK_SIZE);
if (sdcWrite(&SDCD1, sector, buff, count))
return RES_ERROR;
return RES_OK;
#endif
}
return RES_PARERR;
}
Not sure whether there's any advantage to checking whether the buffer is in cached RAM, but it didn't seem to do any harm.
I've also adjusted my malloc() to assign memory starting on 32-byte boundaries (i.e. cache lines)
Who is online
Users browsing this forum: No registered users and 26 guests