Wear Levelling API
Overview
Most of flash memory and especially SPI flash that is used in ESP32 has a sector-based organization and also has a limited number of erase/modification cycles per memory sector. The wear levelling component helps to distribute wear and tear among sectors more evenly without requiring any attention from the user.
The wear levelling component provides API functions related to reading, writing, erasing, and memory mapping of data in external SPI flash through the partition component. The component also has higher-level API functions which work with the FAT filesystem defined in FAT filesystem.
The wear levelling component, together with the FAT FS component, uses FAT FS sectors of 4096 bytes, which is a standard size for flash memory. With this size, the component shows the best performance but needs additional memory in RAM.
To save internal memory, the component has two additional modes which both use sectors of 512 bytes:
Performance mode. Erase sector operation data is stored in RAM, the sector is erased, and then data is copied back to flash memory. However, if a device is powered off for any reason, all 4096 bytes of data is lost.
Safety mode. The data is first saved to flash memory, and after the sector is erased, the data is saved back. If a device is powered off, the data can be recovered as soon as the device boots up.
The default settings are as follows:
Sector size is 512 bytes
Performance mode
You can change the settings through the configuration menu.
The wear levelling component does not cache data in RAM. The write and erase functions modify flash directly, and flash contents are consistent when the function returns.
Wear Levelling access API functions
This is the set of API functions for working with data in flash:
wl_mount
- initializes the wear levelling module and mounts the specified partitionwl_unmount
- unmounts the partition and deinitializes the wear levelling modulewl_erase_range
- erases a range of addresses in flashwl_write
- writes data to a partitionwl_read
- reads data from a partitionwl_size
- returns the size of available memory in byteswl_sector_size
- returns the size of one sector
As a rule, try to avoid using raw wear levelling functions and use filesystem-specific functions instead.
Memory Size
The memory size is calculated in the wear levelling module based on partition parameters. The module uses some sectors of flash for internal data.
Application Example
An example which combines the wear levelling driver with the FATFS library is provided in the storage/wear_levelling directory. This example initializes the wear levelling driver, mounts FATFS partition, as well as writes and reads data from it using POSIX and C library APIs. See the storage/wear_levelling/README.md file for more information.
High level API Reference
Header Files
Functions
-
esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char *base_path, const char *partition_label, const esp_vfs_fat_mount_config_t *mount_config, wl_handle_t *wl_handle)
Convenience function to initialize FAT filesystem in SPI flash and register it in VFS.
This is an all-in-one function which does the following:
finds the partition with defined partition_label. Partition label should be configured in the partition table.
initializes flash wear levelling library on top of the given partition
mounts FAT partition using FATFS library on top of flash wear levelling library
registers FATFS library with VFS, with prefix given by base_prefix variable
This function is intended to make example code more compact.
- Parameters
base_path – path where FATFS partition should be mounted (e.g. “/spiflash”)
partition_label – label of the partition which should be used
mount_config – pointer to structure with extra parameters for mounting FATFS
wl_handle – [out] wear levelling driver handle
- Returns
ESP_OK on success
ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label
ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount_rw_wl was already called
ESP_ERR_NO_MEM if memory can not be allocated
ESP_FAIL if partition can not be mounted
other error codes from wear levelling library, SPI flash driver, or FATFS drivers
-
struct esp_vfs_fat_mount_config_t
Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount_rw_wl functions.
Public Members
-
bool format_if_mount_failed
If FAT partition can not be mounted, and this parameter is true, create partition table and format the filesystem.
-
int max_files
Max number of open files.
-
size_t allocation_unit_size
If format_if_mount_failed is set, and mount fails, format the card with given allocation unit size. Must be a power of 2, between sector size and 128 * sector size. For SD cards, sector size is always 512 bytes. For wear_levelling, sector size is determined by CONFIG_WL_SECTOR_SIZE option.
Using larger allocation unit size will result in higher read/write performance and higher overhead when storing small files.
Setting this field to 0 will result in allocation unit set to the sector size.
-
bool disk_status_check_enable
Enables real ff_disk_status function implementation for SD cards (ff_sdmmc_status). Possibly slows down IO performance.
Try to enable if you need to handle situations when SD cards are not unmounted properly before physical removal or you are experiencing issues with SD cards.
Doesn’t do anything for other memory storage media.
-
bool format_if_mount_failed
-
esp_err_t esp_vfs_fat_spiflash_unmount_rw_wl(const char *base_path, wl_handle_t wl_handle)
Unmount FAT filesystem and release resources acquired using esp_vfs_fat_spiflash_mount_rw_wl.
- Parameters
base_path – path where partition should be registered (e.g. “/spiflash”)
wl_handle – wear levelling driver handle returned by esp_vfs_fat_spiflash_mount_rw_wl
- Returns
ESP_OK on success
ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount_rw_wl hasn’t been called
Mid level API Reference
Functions
-
esp_err_t wl_mount(const esp_partition_t *partition, wl_handle_t *out_handle)
Mount WL for defined partition.
- Parameters
partition – that will be used for access
out_handle – handle of the WL instance
- Returns
ESP_OK, if the allocation was successfully;
ESP_ERR_INVALID_ARG, if WL allocation was unsuccessful;
ESP_ERR_NO_MEM, if there was no memory to allocate WL components;
-
esp_err_t wl_unmount(wl_handle_t handle)
Unmount WL for defined partition.
- Parameters
handle – WL partition handle
- Returns
ESP_OK, if the operation completed successfully;
or one of error codes from lower-level flash driver.
-
esp_err_t wl_erase_range(wl_handle_t handle, size_t start_addr, size_t size)
Erase part of the WL storage.
- Parameters
handle – WL handle that are related to the partition
start_addr – Address where erase operation should start. Must be aligned to the result of function wl_sector_size(…).
size – Size of the range which should be erased, in bytes. Must be divisible by result of function wl_sector_size(…)..
- Returns
ESP_OK, if the range was erased successfully;
ESP_ERR_INVALID_ARG, if iterator or dst are NULL;
ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition;
or one of error codes from lower-level flash driver.
-
esp_err_t wl_write(wl_handle_t handle, size_t dest_addr, const void *src, size_t size)
Write data to the WL storage.
Before writing data to flash, corresponding region of flash needs to be erased. This can be done using wl_erase_range function.
Note
Prior to writing to WL storage, make sure it has been erased with wl_erase_range call.
- Parameters
handle – WL handle that are related to the partition
dest_addr – Address where the data should be written, relative to the beginning of the partition.
src – Pointer to the source buffer. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.
size – Size of data to be written, in bytes.
- Returns
ESP_OK, if data was written successfully;
ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size;
ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
or one of error codes from lower-level flash driver.
-
esp_err_t wl_read(wl_handle_t handle, size_t src_addr, void *dest, size_t size)
Read data from the WL storage.
- Parameters
handle – WL module instance that was initialized before
dest – Pointer to the buffer where data should be stored. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.
src_addr – Address of the data to be read, relative to the beginning of the partition.
size – Size of data to be read, in bytes.
- Returns
ESP_OK, if data was read successfully;
ESP_ERR_INVALID_ARG, if src_offset exceeds partition size;
ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition;
or one of error codes from lower-level flash driver.
-
size_t wl_size(wl_handle_t handle)
Get size of the WL storage.
- Parameters
handle – WL module handle that was initialized before
- Returns
usable size, in bytes
-
size_t wl_sector_size(wl_handle_t handle)
Get sector size of the WL instance.
- Parameters
handle – WL module handle that was initialized before
- Returns
sector size, in bytes