Using Volume Cache

File accesses often incur repeated reading of the same volume sectors. On a FAT volume, these may be sectors in the root directory, the area of the file allocation table (FAT) from which clusters are being allocated or data from important (often-read) files. A cache wedged between the system driver and volume layers (as shown in Figure - Volume cache architecture) will eliminate many unnecessary device accesses. Sector data is stored upon first read or write. Further reads return the cached data; further writes update the cache entry and, possibly, the data on the volume (depending on the cache mode).

Figure - Volume cache architecture

A cache is defined by three parameters: size, sector type allocation and mode. The size of the cache is the number of sectors that will fit into it at any time. Every sector is classified according to its type, either management, directory or file; the sector type allocation determines the percentage of the cache that will be devoted to each type. The mode determines when cache entries are created (i.e., when sectors are cached) and what happens upon write.

Table - Cache types

Cache Mode

Description

Cache Mode #define

Read cache

Sectors cached upon read; never cached upon write.

FS_VOL_CACHE_MODE_RD

Write-through cache

Sectors cached upon read and write; data on volume always updated upon write.

FS_VOL_CACHE_MODE_WR_THROUGH

Write-back cache

Sectors cached upon read and write; data on volume never updated upon write.

FS_VOL_CACHE_MODE_WR_BACK

Choosing Cache Parameters

Listing - Cache is an example using the cache for the volume “sdcard:0:”. The cache is used in write back mode, and the cache parameters are:

25% of cache size is used for management sector, 15% is used for directories sectors and the remaining (60%) is used for file sectors.

Listing - Cache
FSVol_CacheAssign ((CPU_CHAR         *)"sdcard:0:",                /* <-- volume name              */
                   (FS_VOL_CACHE_API *) NULL,                      /* <-- pointer to vol cache API */
                   (void             *)&CACHE_BUF[0],  	           /* <-- pointer to the cache buf */
                   (CPU_INT32U        ) CACHE_BUF_LEN,	           /* <-- cache buf size in bytes  */
                   (CPU_INT08U        ) 25,			               (1)
                   (CPU_INT08U        ) 15,			               (2)	
                   (FS_FLAGS          ) FS_VOL_CACHE_MODE_WR_BACK, /* <-- cache mode               */
                   (FS_ERR           *)&err);		               /* <-- used for error code      */
              
if (err != FS_ERR_NONE) {
    APP_TRACE_INFO ((" Error : could not assign Volume cache"));
    return;    
}
 
pfile = FSFile_Open("sdcard:0:\\file.txt", 
                     FS_FILE_ACCESS_MODE_WR |
                     FS_FILE_ACCESS_MODE_CACHED,
                    &err);
if (pFile == (FS_FILE *)0) {
    return;		
}
 
/* 
   DO THE WRITE OPERATIONS TO THE FILE		
*/
 
FSFile_Close (pFile, &err);
 
FSVol_CacheFlush ("sdcard:0:", &err);				                /* <-- Flush volume cache.     */


Cache
(1) Percent of cache buffer dedicated to management sectors.

(2) Percent of cache buffer dedicated to directory sectors.


The application using μC/FS volume cache should vary the third and fourth parameters passed to FSVol_CacheAssign(), and select the values that give the best performance.

For an efficient cache usage, it is better to do not allocate space in the cache for sectors of type file when the write size is greater than sector size.

When the cache is used in write back mode, all cache dirty sectors will be updated on the media storage only when the cache is flushed.

Other Caching and Buffering Mechanisms

Volume cache is just one of several important caching mechanisms, which should be balanced for optimal performance within the bounds of platform resources. The second important software mechanism is the file buffer (see Configuring a File Buffer), which makes file accesses more efficient by buffering data so a full sector’s worth will be read or written.

Individual devices or drivers may also integrate a cache. Standard hard drives overcome long seek times by buffering extra data upon read (in anticipation of future requests) or clumping writes to eliminate unnecessary movement. The latter action can be particularly powerful, but since it may involve re-ordering the sequence of sector writes will eliminate any guarantee of fail-safety of most file systems. For that reason, write cache in most storage devices should be disabled.

A driver may implement a buffer to reduce apparent write latency. Before a write can occur to a flash medium, the driver must find a free (erased) area of a block; occasionally, a block will need to be erased to make room for the next write. Incoming data can be buffered while the long erase occurs in the background, thereby uncoupling the application’s wait time from the real maximum flash write time.

The ideal system might use both volume cache and file buffers. A volume cache is most powerful when confined to the sector types most subject to repeated reads: management and directory. Caching of files, if enabled, should be limited to important (often-read) files. File buffers are more flexible, since they cater to the many applications that find small reads and writes more convenient than those of full sectors.