Middleware for the LittleFS File System control using external SPI Flash on RA6W1/RA6W2. This module implements the LittleFS Interface.
This module provides the hardware port layer for the LittleFS file system. After initializing this module, refer to the LittleFS documentation to use the file system: https://github.com/ARMmbed/littlefs
The following build time configurations are defined in fsp_cfg/rm_littlefs_spi_flash_w_cfg.h:
| Configuration | Options | Default | Description |
| Name | Name must be a valid C symbol | g_rm_littlefs0 | Module name. |
| Read Size | Must be a non-negative integer | 1 | Minimum size of a block read. All read operations will be a multiple of this value. |
| Program Size | Must be a non-negative integer | 8 | Minimum size of a block program. All program operations will be a multiple of this value. |
| Memory Start Address | Manual Entry | 0x24170000 | Start address of the memory allocated for the LittleFS Volume. |
| Total Memory Size (bytes) | Manual Entry | 0x10000 | Total memory available for LittleFS storage. For NVMC platforms, this defaults to the S-BUS alias window expected by the NVMC address checks. Users can override this value for custom memory layouts or external storage partitions. |
| Block Size (bytes) | Must be a multiple of 64 or 8 on NVMC_W MCUs | 128 | Size of an erasable block. This does not impact RAM consumption and may be larger than the physical erase size. However, non-inlined files take up at minimum one block. Must be a multiple of the read and program sizes. |
| Block Count | Manual Entry | 512 | Number of erasable blocks on the device. Should equal Total Memory Size divided by Block Size. Default: 0x10000 / 128 = 512. Ensure this value remains correct if Total Memory Size or Block Size are modified. |
| Block Cycles | Must be an integer | 1024 | Number of erase cycles before LittleFS evicts metadata logs and moves the metadata to another block. Suggested values are in the range 100-1000, with large values having better performance at the cost of less consistent wear distribution. Set to -1 to disable block-level wear-leveling. |
| Cache Size | Must be a non-negative integer | 64 | Size of block caches. Each cache buffers a portion of a block in RAM. The LittleFS needs a read cache, a program cache, and one additional cache per file. Larger caches can improve performance by storing more data and reducing the number of disk accesses. Must be a multiple of the read and program sizes, and a factor of the block size. |
| Lookahead Size | Must be a non-negative multiple of 8 | 16 | Size of the lookahead buffer in bytes. A larger lookahead buffer increases the number of blocks found during an allocation pass. The lookahead buffer is stored as a compact bitmap, so each byte of RAM can track 8 blocks. Must be a multiple of 8. |
The following build time configurations are defined in arm/littlefs/lfs_util.h:
The LittleFS port blocks on Read/Write/Erase calls until the operation has completed.
Ensure that the flash page size, sector size, and total capacity configured in the driver match the connected SPI flash device.
This module is not thread safe.
This is a basic example of LittleFS on external SPI Flash in an application.
#ifdef LFS_NO_MALLOC
static uint8_t g_file_buffer[LFS_CACHE_SIZE];
static struct lfs_file_config g_file_cfg =
{
.buffer = g_file_buffer
};
#endif
void rm_littlefs_example (void)
{
uint8_t buffer[30];
lfs_file_t file;
if (FSP_SUCCESS != err)
{
handle_lfs_error(err);
}
assert(FSP_SUCCESS == err);
int lfs_err = lfs_format(&g_rm_littlefs_spi_flash_w0_lfs, &g_rm_littlefs_spi_flash_w0_lfs_cfg);
handle_lfs_error(lfs_err);
lfs_err = lfs_mount(&g_rm_littlefs_spi_flash_w0_lfs, &g_rm_littlefs_spi_flash_w0_lfs_cfg);
handle_lfs_error(lfs_err);
lfs_err = lfs_mkdir(&g_rm_littlefs_spi_flash_w0_lfs, "breakfast");
handle_lfs_error(lfs_err);
const char * path = "breakfast/toast";
#ifdef LFS_NO_MALLOC
lfs_err = lfs_file_opencfg(&g_rm_littlefs_spi_flash_w0_lfs,
&file,
path,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND,
&g_file_cfg);
handle_lfs_error(lfs_err);
#else
lfs_err = lfs_file_open(&g_rm_littlefs_spi_flash_w0_lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND);
handle_lfs_error(lfs_err);
#endif
const char * contents = "butter";
lfs_size_t len = strlen(contents);
for (uint32_t i = 0; i < 10; i++)
{
lfs_err = lfs_file_write(&g_rm_littlefs_spi_flash_w0_lfs, &file, contents, len);
if (lfs_err < 0)
{
handle_lfs_error(lfs_err);
}
}
lfs_err = lfs_file_close(&g_rm_littlefs_spi_flash_w0_lfs, &file);
handle_lfs_error(lfs_err);
lfs_err = lfs_unmount(&g_rm_littlefs_spi_flash_w0_lfs);
handle_lfs_error(lfs_err);
lfs_err = lfs_mount(&g_rm_littlefs_spi_flash_w0_lfs, &g_rm_littlefs_spi_flash_w0_lfs_cfg);
handle_lfs_error(lfs_err);
#ifdef LFS_NO_MALLOC
lfs_err = lfs_file_opencfg(&g_rm_littlefs_spi_flash_w0_lfs, &file, path, LFS_O_RDONLY, &g_file_cfg);
handle_lfs_error(lfs_err);
#else
lfs_err = lfs_file_open(&g_rm_littlefs_spi_flash_w0_lfs, &file, path, LFS_O_RDONLY);
handle_lfs_error(lfs_err);
#endif
for (uint32_t i = 0; i < 10; i++)
{
lfs_err = lfs_file_read(&g_rm_littlefs_spi_flash_w0_lfs, &file, buffer, len);
if (lfs_err < 0)
{
handle_lfs_error(lfs_err);
}
assert(0 == memcmp(buffer, contents, len));
}
lfs_err = lfs_file_close(&g_rm_littlefs_spi_flash_w0_lfs, &file);
handle_lfs_error(lfs_err);
}