// removes the oldest accessed cached page static s32_t ICACHE_FLASH_ATTR spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask, u8_t flags) { s32_t res = SPIFFS_OK; spiffs_cache *cache = spiffs_get_cache(fs); if ((cache->cpage_use_map & cache->cpage_use_mask) != cache->cpage_use_mask) { // at least one free cpage return SPIFFS_OK; } // all busy, scan thru all to find the cpage which has oldest access int i; int cand_ix = -1; u32_t oldest_val = 0; for (i = 0; i < cache->cpage_count; i++) { spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i); if ((cache->last_access - cp->last_access) > oldest_val && (cp->flags & flag_mask) == flags) { oldest_val = cache->last_access - cp->last_access; cand_ix = i; } } if (cand_ix >= 0) { res = spiffs_cache_page_free(fs, cand_ix, 1); } return res; }
// frees cached page static s32_t ICACHE_FLASH_ATTR spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) { s32_t res = SPIFFS_OK; spiffs_cache *cache = spiffs_get_cache(fs); spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, ix); if (cache->cpage_use_map & (1<<ix)) { if (write_back && (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 && (cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) { u8_t *mem = spiffs_get_cache_page(fs, cache, ix); res = fs->cfg.hal_write_f(SPIFFS_PAGE_TO_PADDR(fs, cp->pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem); } cp->flags = 0; cache->cpage_use_map &= ~(1 << ix); if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) { SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %d objid %04x\n", ix, cp->obj_id); } else { SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %d pix %04x\n", ix, cp->pix); } } return res; }
// initializes the cache void ICACHE_FLASH_ATTR spiffs_cache_init(spiffs *fs) { if (fs->cache == 0) return; u32_t sz = fs->cache_size; u32_t cache_mask = 0; int i; int cache_entries = (sz - sizeof(spiffs_cache)) / (SPIFFS_CACHE_PAGE_SIZE(fs)); if (cache_entries <= 0) return; for (i = 0; i < cache_entries; i++) { cache_mask <<= 1; cache_mask |= 1; } spiffs_cache cache; memset(&cache, 0, sizeof(spiffs_cache)); cache.cpage_count = cache_entries; cache.cpages = (u8_t *)((u8_t *)fs->cache + sizeof(spiffs_cache)); cache.cpage_use_map = 0xffffffff; cache.cpage_use_mask = cache_mask; memcpy(fs->cache, &cache, sizeof(spiffs_cache)); spiffs_cache *c = spiffs_get_cache(fs); memset(c->cpages, 0, c->cpage_count * SPIFFS_CACHE_PAGE_SIZE(fs)); c->cpage_use_map &= ~(c->cpage_use_mask); for (i = 0; i < cache.cpage_count; i++) { spiffs_get_cache_page_hdr(fs, c, i)->ix = i; } }
// returns cached page for give page index, or null if no such cached page static spiffs_cache_page *ICACHE_FLASH_ATTR spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix) { spiffs_cache *cache = spiffs_get_cache(fs); if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) return 0; int i; for (i = 0; i < cache->cpage_count; i++) { spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i); if ((cache->cpage_use_map & (1<<i)) && (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 && cp->pix == pix ) { SPIFFS_CACHE_DBG("CACHE_GET: have cache page %i for %04x\n", i, pix); cp->last_access = cache->last_access; return cp; } } //SPIFFS_CACHE_DBG("CACHE_GET: no cache for %04x\n", pix); return 0; }
// allocates a new cached page and returns it, or null if all cache pages are busy static spiffs_cache_page *ICACHE_FLASH_ATTR spiffs_cache_page_allocate(spiffs *fs) { spiffs_cache *cache = spiffs_get_cache(fs); if (cache->cpage_use_map == 0xffffffff) { // out of cache memory return 0; } int i; for (i = 0; i < cache->cpage_count; i++) { if ((cache->cpage_use_map & (1<<i)) == 0) { spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i); cache->cpage_use_map |= (1<<i); cp->last_access = cache->last_access; SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page %i\n", i); return cp; } } // out of cache entries return 0; }
// returns the cache page that this fd refers, or null if no cache page spiffs_cache_page *ICACHE_FLASH_ATTR spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) { spiffs_cache *cache = spiffs_get_cache(fs); if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) { // all cpages free, no cpage cannot be assigned to obj_id return 0; } int i; for (i = 0; i < cache->cpage_count; i++) { spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i); if ((cache->cpage_use_map & (1<<i)) && (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) && cp->obj_id == fd->obj_id) { return cp; } } return 0; }