255 lines
7.6 KiB
C
255 lines
7.6 KiB
C
#include "test_littlefs_common.h"
|
|
#include "esp_vfs_fat.h"
|
|
|
|
static const char TAG[] = "[littlefs_benchmark]";
|
|
|
|
// Handle of the wear levelling library instance
|
|
wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
|
|
#define MAX_FILES 5
|
|
|
|
static void setup_spiffs(){
|
|
ESP_LOGI(TAG, "Initializing SPIFFS");
|
|
|
|
esp_spiffs_format("spiffs_store");
|
|
|
|
esp_vfs_spiffs_conf_t conf = {
|
|
.base_path = "/spiffs",
|
|
.partition_label = "spiffs_store",
|
|
.max_files = MAX_FILES,
|
|
.format_if_mount_failed = true
|
|
};
|
|
|
|
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
|
|
|
if (ret != ESP_OK) {
|
|
if (ret == ESP_FAIL) {
|
|
ESP_LOGE(TAG, "Failed to mount or format filesystem");
|
|
} else if (ret == ESP_ERR_NOT_FOUND) {
|
|
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
|
|
} else {
|
|
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
|
|
}
|
|
TEST_FAIL();
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void setup_fat(){
|
|
const esp_vfs_fat_mount_config_t conf = {
|
|
.max_files = MAX_FILES,
|
|
.format_if_mount_failed = true,
|
|
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE
|
|
};
|
|
esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl("/fat", "fat_store", &conf, &s_wl_handle);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
|
|
TEST_FAIL();
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void setup_littlefs() {
|
|
esp_vfs_littlefs_conf_t conf = {
|
|
.base_path = "/littlefs",
|
|
.partition_label = "flash_test",
|
|
.format_if_mount_failed = true
|
|
};
|
|
TEST_ESP_OK(esp_vfs_littlefs_register(&conf));
|
|
esp_littlefs_format("flash_test");
|
|
}
|
|
|
|
static void test_benchmark_setup() {
|
|
setup_fat();
|
|
setup_spiffs();
|
|
setup_littlefs();
|
|
printf("Test setup complete.\n");
|
|
}
|
|
|
|
static void test_benchmark_teardown()
|
|
{
|
|
assert(ESP_OK == esp_vfs_fat_spiflash_unmount_rw_wl("/fat", s_wl_handle));
|
|
TEST_ESP_OK(esp_vfs_spiffs_unregister("spiffs_store"));
|
|
TEST_ESP_OK(esp_vfs_littlefs_unregister("flash_test"));
|
|
printf("Test teardown complete.\n");
|
|
}
|
|
|
|
/**
|
|
* @brief Fill partitions with dummy data
|
|
*/
|
|
static void fill_partitions()
|
|
{
|
|
const esp_partition_t* part;
|
|
const char dummy_data[] = {
|
|
'D','U','M','M','Y','D','A','T','A','0','1','2', '3', '4', '5', '6',
|
|
'D','U','M','M','Y','D','A','T','A','0','1','2', '3', '4', '5', '6',
|
|
'D','U','M','M','Y','D','A','T','A','0','1','2', '3', '4', '5', '6',
|
|
'D','U','M','M','Y','D','A','T','A','0','1','2', '3', '4', '5', '6',
|
|
'D','U','M','M','Y','D','A','T','A','0','1','2', '3', '4', '5', '6',
|
|
'D','U','M','M','Y','D','A','T','A','0','1','2', '3', '4', '5', '6',
|
|
'D','U','M','M','Y','D','A','T','A','0','1','2', '3', '4', '5', '6',
|
|
'D','U','M','M','Y','D','A','T','A','0','1','2', '3', '4', '5', '6'
|
|
};
|
|
|
|
ESP_LOGI(TAG, "Filling SPIFFS partition with dummy data");
|
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY,
|
|
"spiffs_store");
|
|
esp_partition_erase_range(part, 0, part->size);
|
|
for(uint32_t i=0; i < part->size; i += sizeof(dummy_data))
|
|
esp_partition_write(part, i, dummy_data, sizeof(dummy_data));
|
|
|
|
ESP_LOGI(TAG, "Filling FAT partition with dummy data");
|
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY,
|
|
"fat_store");
|
|
esp_partition_erase_range(part, 0, part->size);
|
|
for(uint32_t i=0; i < part->size; i += sizeof(dummy_data))
|
|
esp_partition_write(part, i, dummy_data, sizeof(dummy_data));
|
|
|
|
ESP_LOGI(TAG, "Filling LittleFS partition with dummy data");
|
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY,
|
|
"flash_test");
|
|
esp_partition_erase_range(part, 0, part->size);
|
|
for(uint32_t i=0; i < part->size; i += sizeof(dummy_data))
|
|
esp_partition_write(part, i, dummy_data, sizeof(dummy_data));
|
|
}
|
|
|
|
static int get_file_size(const char *fname) {
|
|
struct stat sb;
|
|
|
|
if( 0 != stat(fname, &sb) ) {
|
|
return -1;
|
|
}
|
|
|
|
return sb.st_size;
|
|
}
|
|
|
|
/**
|
|
* @brief Writes and deletes files
|
|
* @param[in] mount_pt
|
|
* @param[in] iter Number of files to write
|
|
*/
|
|
static void read_write_test_1(const char *mount_pt, uint32_t iter) {
|
|
char fmt_fn[64] = { 0 };
|
|
char fname[128] = { 0 };
|
|
uint64_t t_write = 0;
|
|
uint64_t t_read = 0;
|
|
uint64_t t_delete = 0;
|
|
|
|
int n_write = 0;
|
|
int n_read = 0;
|
|
int n_delete = 0;
|
|
|
|
strcat(fmt_fn, mount_pt);
|
|
if(fmt_fn[strlen(fmt_fn)-1] != '/') strcat(fmt_fn, "/");
|
|
strcat(fmt_fn, "%d.txt");
|
|
|
|
/* WRITE */
|
|
for(uint8_t i=0; i < iter; i++){
|
|
snprintf(fname, sizeof(fname), fmt_fn, i);
|
|
uint64_t t_start = esp_timer_get_time();
|
|
FILE* f = fopen(fname, "w");
|
|
if (f == NULL) {
|
|
ESP_LOGE(TAG, "Failed to open file %d for writing", i);
|
|
continue;
|
|
}
|
|
for(uint32_t j=0; j < 2000; j++) {
|
|
fprintf(f, "All work and no play makes Jack a dull boy.\n");
|
|
}
|
|
fclose(f);
|
|
uint64_t t_end = esp_timer_get_time();
|
|
int fsize = get_file_size(fname);
|
|
printf("%d bytes written in %lld us\n", fsize, (t_end - t_start));
|
|
t_write += (t_end - t_start);
|
|
n_write += fsize;
|
|
}
|
|
|
|
printf("------------\n");
|
|
|
|
/* READ */
|
|
for(uint8_t i=0; i < iter; i++){
|
|
int fsize = 0;
|
|
snprintf(fname, sizeof(fname), fmt_fn, i);
|
|
uint64_t t_start = esp_timer_get_time();
|
|
FILE* f = fopen(fname, "r");
|
|
if (f == NULL) {
|
|
ESP_LOGE(TAG, "Failed to open file %d for reading", i);
|
|
continue;
|
|
}
|
|
|
|
while(fgetc(f) != EOF) fsize ++;
|
|
|
|
fclose(f);
|
|
uint64_t t_end = esp_timer_get_time();
|
|
printf("%d bytes read in %lld us\n", fsize, (t_end - t_start));
|
|
t_read += (t_end - t_start);
|
|
n_read += fsize;
|
|
}
|
|
|
|
printf("------------\n");
|
|
|
|
/* DELETE */
|
|
for(uint8_t i=0; i < iter; i++){
|
|
snprintf(fname, sizeof(fname), fmt_fn, i);
|
|
|
|
int fsize = get_file_size(fname);
|
|
if (fsize < 0) {
|
|
continue;
|
|
}
|
|
|
|
uint64_t t_start = esp_timer_get_time();
|
|
snprintf(fname, sizeof(fname), fmt_fn, i);
|
|
unlink(fname);
|
|
uint64_t t_end = esp_timer_get_time();
|
|
printf("deleted file %d in %lld us\n", i, (t_end - t_start));
|
|
t_delete += (t_end - t_start);
|
|
n_delete += fsize;
|
|
}
|
|
|
|
printf("------------\n");
|
|
|
|
printf("Total (%d) Write: %lld us\n", n_write, t_write);
|
|
printf("Total (%d) Read: %lld us\n", n_read, t_read);
|
|
printf("Total (%d) Delete: %lld us\n", n_delete, t_delete);
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
TEST_CASE("Format", TAG){
|
|
uint64_t t_fat, t_spiffs, t_littlefs, t_start;
|
|
|
|
fill_partitions();
|
|
|
|
t_start = esp_timer_get_time();
|
|
esp_spiffs_format(NULL);
|
|
t_spiffs = esp_timer_get_time() - t_start;
|
|
printf("SPIFFS Formatted in %lld us\n", t_spiffs);
|
|
|
|
t_start = esp_timer_get_time();
|
|
setup_fat();
|
|
assert(ESP_OK == esp_vfs_fat_spiflash_unmount("/fat", s_wl_handle));
|
|
t_fat = esp_timer_get_time() - t_start;
|
|
printf("FAT Formatted in %lld us\n", t_fat);
|
|
|
|
t_start = esp_timer_get_time();
|
|
esp_littlefs_format("flash_test");
|
|
t_littlefs = esp_timer_get_time() - t_start;
|
|
printf("LittleFS Formatted in %lld us\n", t_littlefs);
|
|
|
|
}
|
|
|
|
TEST_CASE("Write 5 files, read 5 files, then delete 5 files", TAG){
|
|
test_benchmark_setup();
|
|
|
|
printf("FAT:\n");
|
|
read_write_test_1("/fat", 5);
|
|
printf("\n");
|
|
|
|
printf("SPIFFS:\n");
|
|
read_write_test_1("/spiffs", 5);
|
|
printf("\n");
|
|
|
|
printf("LittleFS:\n");
|
|
read_write_test_1("/littlefs", 5);
|
|
printf("\n");
|
|
|
|
test_benchmark_teardown();
|
|
}
|