Skip to content

Commit

Permalink
[driver] disk use cache
Browse files Browse the repository at this point in the history
  • Loading branch information
YuzukiTsuru committed Feb 4, 2024
1 parent 83fdf23 commit 032ee0a
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 87 deletions.
3 changes: 2 additions & 1 deletion cmake/board/tinyvision.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
169 changes: 83 additions & 86 deletions lib/fatfs/diskio.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,35 @@
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include "ff.h" /* Obtains integer types */

#include "diskio.h"

#include <sys-dma.h>
#include <sys-dram.h>
#include <sys-sdcard.h>

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

/*-----------------------------------------------------------------------*/
Expand All @@ -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;
}

/*-----------------------------------------------------------------------*/
Expand All @@ -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
}

Expand All @@ -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
Expand All @@ -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;
}

0 comments on commit 032ee0a

Please sign in to comment.