diff --git a/cmake/board/tinyvision.cmake b/cmake/board/tinyvision.cmake index 80d3b6bf..f6dcfd6a 100644 --- a/cmake/board/tinyvision.cmake +++ b/cmake/board/tinyvision.cmake @@ -5,8 +5,9 @@ set(CONFIG_CHIP_SUN8IW21 True) set(CONFIG_BOARD_TINYVISION True) set(CONFIG_CHIP_USB True) set(CONFIG_CHIP_GIC True) +set(CONFIG_FATFS_CACHE_SIZE "0xa0000000") -add_definitions(-DCONFIG_CHIP_SUN8IW21 -DCONFIG_CHIP_GIC) +add_definitions(-DCONFIG_CHIP_SUN8IW21 -DCONFIG_CHIP_GIC -DCONFIG_FATFS_CACHE_SIZE=${CONFIG_FATFS_CACHE_SIZE}) # Options diff --git a/lib/fatfs/diskio.c b/lib/fatfs/diskio.c index 42b4bc6c..95552c14 100644 --- a/lib/fatfs/diskio.c +++ b/lib/fatfs/diskio.c @@ -7,6 +7,7 @@ /* storage control modules to the FatFs module with a defined API. */ /*-----------------------------------------------------------------------*/ #include "ff.h" /* Obtains integer types */ + #include "diskio.h" #include @@ -14,10 +15,27 @@ #include static DSTATUS Stat = STA_NOINIT; /* Disk status */ + #ifdef CONFIG_FATFS_CACHE_SIZE -static u8 *const cache = (u8 *)SDRAM_BASE; -static const u32 cache_size = (CONFIG_FATFS_CACHE_SIZE); -static u32 cache_first, cache_last; +/* we can consume up to CONFIG_FATFS_CACHE_SIZE of SDRAM starting at SDRAM_BASE */ +#define FATFS_CACHE_CHUNK_SIZE (32 * 1024) +#define FATFS_CACHE_SECTORS (CONFIG_FATFS_CACHE_SIZE / FF_MIN_SS) +#define FATFS_CACHE_SECTORS_PER_BIT (FATFS_CACHE_CHUNK_SIZE / FF_MIN_SS) +#define FATFS_CACHE_CHUNKS (FATFS_CACHE_SECTORS / FATFS_CACHE_SECTORS_PER_BIT) + +static uint8_t *const cache_data = (uint8_t *) SDRAM_BASE; /* in SDRAM */ +static uint8_t cache_bitmap[FATFS_CACHE_CHUNKS / 8]; /* in SRAM */ +static BYTE cache_pdrv = -1; + +#define CACHE_SECTOR_TO_OFFSET(ss) (((ss) / FATFS_CACHE_SECTORS_PER_BIT) / 8) +#define CACHE_SECTOR_TO_BIT(ss) (((ss) / FATFS_CACHE_SECTORS_PER_BIT) % 8) + +#define CACHE_IS_VALID(ss) ({ __typeof(ss) _ss = (ss); cache_bitmap[CACHE_SECTOR_TO_OFFSET(_ss)] & (1 << CACHE_SECTOR_TO_BIT(_ss)); }) +#define CACHE_SET_VALID(ss) \ + do { \ + __typeof(ss) _ss = (ss); \ + cache_bitmap[CACHE_SECTOR_TO_OFFSET(_ss)] |= (1 << CACHE_SECTOR_TO_BIT(_ss)); \ + } while (0) #endif /*-----------------------------------------------------------------------*/ @@ -30,13 +48,7 @@ DSTATUS disk_status(BYTE pdrv /* Physical drive nmuber to identify the drive */ if (pdrv) return STA_NOINIT; -#ifdef CONFIG_FATFS_CACHE_SIZE - cache_first = 0xFFFFFFFF - - cache_size; // Set to a big sector for a proper init - cache_last = 0xFFFFFFFF; -#endif - - return Stat; + return Stat; } /*-----------------------------------------------------------------------*/ @@ -50,79 +62,66 @@ disk_initialize(BYTE pdrv /* Physical drive nmuber to identify the drive */ if (pdrv) return STA_NOINIT; - Stat &= ~STA_NOINIT; + Stat &= ~STA_NOINIT; - return Stat; + return Stat; } /*-----------------------------------------------------------------------*/ /* Read Sector(s) */ /*-----------------------------------------------------------------------*/ -DRESULT disk_read(BYTE pdrv, /* Physical drive nmuber to identify the drive */ - BYTE *buff, /* Data buffer to store read data */ - LBA_t sector, /* Start sector in LBA */ - UINT count /* Number of sectors to read */ -) -{ - u32 blkread, read_pos, first, last, chunk, bytes; - - if (pdrv || !count) - return RES_PARERR; - if (Stat & STA_NOINIT) - return RES_NOTRDY; - - first = sector; - last = sector + count; - bytes = count * FF_MIN_SS; +DRESULT disk_read(BYTE pdrv, /* Physical drive nmuber to identify the drive */ + BYTE *buff, /* Data buffer to store read data */ + LBA_t sector, /* Start sector in LBA */ + UINT count /* Number of sectors to read */ +) { + if (pdrv || !count) + return RES_PARERR; + if (Stat & STA_NOINIT) + return RES_NOTRDY; - printk(LOG_LEVEL_TRACE, "FATFS: read %u sectors at %u\n", count, - first); + printk(LOG_LEVEL_TRACE, "FATFS: read %u sectors at %llu\r\n", count, sector); #ifdef CONFIG_FATFS_CACHE_SIZE - // Read starts in cache but overflows - if (first >= cache_first && first < cache_last && last > cache_last) { - chunk = (cache_last - first) * FF_MIN_SS; - memcpy(buff, cache + (first - cache_first) * FF_MIN_SS, chunk); - buff += chunk; - first += (cache_last - first); - printk(LOG_LEVEL_TRACE, "FATFS: chunk %u first %u\n", chunk, - first); - } - - // Read is NOT in the cache - if (last > cache_last || first < cache_first) { - printk(LOG_LEVEL_TRACE, "FATFS: if %u > %u || %u < %u\n", - last, cache_last, first, cache_first); - - read_pos = (first / cache_size) * - cache_size; // TODO: check with card max capacity - cache_first = read_pos; - cache_last = read_pos + cache_size; - blkread = sdmmc_blk_read(&card0, cache, read_pos, cache_size); - - if (blkread != cache_size) { - printk(LOG_LEVEL_WARNING, - "FATFS: MMC read %u/%u blocks\n", blkread, - cache_size); - return RES_ERROR; - } - printk(LOG_LEVEL_TRACE, - "FATFS: cached %u sectors (%uKB) at %u/[%u-%u]\n", - blkread, (blkread * FF_MIN_SS) / 1024, first, read_pos, - read_pos + cache_size); - } - - // Copy from read cache to output buffer - printk(LOG_LEVEL_TRACE, "FATFS: copy %u from 0x%x to 0x%x\n", bytes, - (cache + ((first - cache_first) * FF_MIN_SS)), buff); - memcpy(buff, (cache + ((first - cache_first) * FF_MIN_SS)), bytes); - - return RES_OK; + if (pdrv != cache_pdrv) { + printk(LOG_LEVEL_DEBUG, "FATFS: cache: %u bytes in %u chunks\r\n", CONFIG_FATFS_CACHE_SIZE, FATFS_CACHE_CHUNKS); + if (cache_pdrv != -1) + memset(cache_bitmap, 0, sizeof(cache_bitmap)); + cache_pdrv = pdrv; + } + + while (count) { + if (sector >= FATFS_CACHE_SECTORS) { + printk(LOG_LEVEL_TRACE, "FATFS: beyond cache %llu count %u\r\n", sector, count); + /* beyond end of cache, read remaining */ + if (sdmmc_blk_read(&card0, buff, sector, count) != count) { + printk(LOG_LEVEL_WARNING, "FATFS: read failed %llu count %u\r\n", sector, count); + return RES_ERROR; + } + return RES_OK; + } + + if (!CACHE_IS_VALID(sector)) { + LBA_t chunk = sector & ~(FATFS_CACHE_SECTORS_PER_BIT - 1); + printk(LOG_LEVEL_TRACE, "FATFS: cache miss %llu, loading %llu count %u\r\n", sector, chunk, FATFS_CACHE_SECTORS_PER_BIT); + if (sdmmc_blk_read(&card0, &cache_data[chunk * FF_MIN_SS], chunk, FATFS_CACHE_SECTORS_PER_BIT) != FATFS_CACHE_SECTORS_PER_BIT) { + printk(LOG_LEVEL_WARNING, "FATFS: read failed %llu count %u\r\n", sector, FATFS_CACHE_SECTORS_PER_BIT); + return RES_ERROR; + } + CACHE_SET_VALID(sector); + } else { + printk(LOG_LEVEL_TRACE, "FATFS: cache hit %llu\r\n", sector); + } + memcpy(buff, &cache_data[sector * FF_MIN_SS], FF_MIN_SS); + + sector++; + buff += FF_MIN_SS; + count--; + } + return RES_OK; #else - return (sdmmc_blk_read(&card0, buff, sector, count) == count ? - RES_OK : - RES_ERROR); + return (sdmmc_blk_read(&card0, buff, sector, count) == count ? RES_OK : RES_ERROR); #endif } @@ -132,13 +131,12 @@ DRESULT disk_read(BYTE pdrv, /* Physical drive nmuber to identify the drive */ #if FF_FS_READONLY == 0 -DRESULT disk_write(BYTE pdrv, /* Physical drive nmuber to identify the drive */ - const BYTE *buff, /* Data to be written */ - LBA_t sector, /* Start sector in LBA */ - UINT count /* Number of sectors to write */ -) -{ - return RES_ERROR; +DRESULT disk_write(BYTE pdrv, /* Physical drive nmuber to identify the drive */ + const BYTE *buff, /* Data to be written */ + LBA_t sector, /* Start sector in LBA */ + UINT count /* Number of sectors to write */ +) { + return RES_ERROR; } #endif @@ -147,10 +145,9 @@ DRESULT disk_write(BYTE pdrv, /* Physical drive nmuber to identify the drive */ /* Miscellaneous Functions */ /*-----------------------------------------------------------------------*/ -DRESULT disk_ioctl(BYTE pdrv, /* Physical drive nmuber (0..) */ - BYTE cmd, /* Control code */ - void *buff /* Buffer to send/receive control data */ -) -{ - return RES_PARERR; -} +DRESULT disk_ioctl(BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE cmd, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) { + return RES_PARERR; +} \ No newline at end of file