Browse Source

Merge branch 'update/littlefs_demo_example' into 'master'

LittleFS demo example added

See merge request espressif/esp-idf!24472
Sonika Rathi 2 years ago
parent
commit
02f5b9a898

+ 1 - 0
components/esp_partition/include/esp_partition.h

@@ -97,6 +97,7 @@ typedef enum {
     ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80,                               //!< ESPHTTPD partition
     ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80,                               //!< ESPHTTPD partition
     ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition
     ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition
     ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82,                                 //!< SPIFFS partition
     ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82,                                 //!< SPIFFS partition
+    ESP_PARTITION_SUBTYPE_DATA_LITTLEFS = 0x83,                               //!< LITTLEFS partition
 
 
 #if __has_include("extra_partition_subtypes.inc")
 #if __has_include("extra_partition_subtypes.inc")
     #include "extra_partition_subtypes.inc"
     #include "extra_partition_subtypes.inc"

+ 1 - 0
components/partition_table/gen_esp32part.py

@@ -71,6 +71,7 @@ SUBTYPES = {
         'esphttpd': 0x80,
         'esphttpd': 0x80,
         'fat': 0x81,
         'fat': 0x81,
         'spiffs': 0x82,
         'spiffs': 0x82,
+        'littlefs': 0x83,
     },
     },
 }
 }
 
 

+ 6 - 0
examples/storage/littlefs/CMakeLists.txt

@@ -0,0 +1,6 @@
+# The following lines of boilerplate have to be in your project's
+# CMakeLists in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(littlefs_example)

+ 76 - 0
examples/storage/littlefs/README.md

@@ -0,0 +1,76 @@
+| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
+
+# About LittleFS
+
+[LittleFS](https://github.com/littlefs-project/littlefs) is a file system designed for small devices like microcontrollers and embedded systems. It helps these devices manage and store data efficiently.
+- LittleFS is specifically built to be lightweight and requires less storage space and processing power. It takes up very little memory, which is important for small devices with limited resources.
+- It has features that ensure data integrity and reliability, so the files stored on the device are less likely to get corrupted or lost.
+In a nutshell, LittleFS is a specialized file system that helps small devices effectively handle and store data, allowing them to perform tasks efficiently with minimal resources.
+
+# License
+
+The littlefs is provided under the BSD-3-Clause license. Please refer [littlefs license](https://github.com/littlefs-project/littlefs#license) for more details.
+
+
+# LittleFS example
+
+(See the README.md file in the upper level 'examples' directory for more information about examples.)
+
+`littlefs` component is managed in ESP-IDF using IDF component manager. This example uses a littlefs port for [ESP-IDF littlefs](https://components.espressif.com/components/joltwallet/littlefs) for which upstream repository is [esp_littlefs](https://github.com/joltwallet/esp_littlefs).
+
+LittleFS partition generator is invoked from CMake build system. We use `littlefs_create_partition_image` in main/CMakeLists.txt to generate the partition image and flash it to the device at build time.
+
+*Note: Currently Windows does not support `LittleFS partition generation` feature.*
+
+This example demonstrates how to use LittleFS with ESP32. Example does the following steps:
+
+1. Use an "all-in-one" `esp_vfs_littlefs_register` function to:
+    - initialize LittleFS,
+    - mount LittleFS filesystem using LittleFS library (and format, if the filesystem can not be mounted),
+    - register LittleFS filesystem in VFS, enabling C standard library and POSIX functions to be used.
+2. Create a file using `fopen` and write to it using `fprintf`.
+3. Rename the file. Before renaming, check if destination file already exists using `stat` function, and remove it using `unlink` function.
+4. Open renamed file for reading, read back the line, and print it to the terminal.
+
+LittleFS partition size is set in partitions_demo_esp_littlefs.csv file. See [Partition Tables](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html) documentation for more information.
+
+## How to use example
+
+### Hardware required
+
+This example does not require any special hardware, and can be run on any common development board.
+
+### Build and flash
+
+Replace PORT with serial port name:
+
+```
+idf.py -p PORT flash monitor
+```
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
+
+## Example output
+
+Here is an example console output. In this case `format_if_mount_failed` parameter was set to `true` in the source code. LittleFS was unformatted, so the initial mount has failed. LittleFS was then formatted, and mounted again.
+
+```
+I (264) esp_littlefs: Initializing LittleFS
+I (274) esp_littlefs: Partition size: total: 983040, used: 12288
+I (274) esp_littlefs: Opening file
+I (344) esp_littlefs: File written
+I (344) esp_littlefs: Renaming file
+I (354) esp_littlefs: Reading file
+I (354) esp_littlefs: Read from file: 'Hello World!'
+I (354) esp_littlefs: Reading from flashed filesystem example.txt
+I (364) esp_littlefs: Read from file: 'Example text to compile into a LittleFS disk image to be flashed to the ESP device.'
+I (374) esp_littlefs: LittleFS unmounted
+I (374) main_task: Returned from app_main()
+```
+
+To erase the contents of LittleFS partition, run `idf.py erase-flash` command. Then upload the example again as described above.
+
+[Here](https://github.com/joltwallet/esp_littlefs#performance) you can find performance results for LittleFS, SPIFFS and FATFS for your reference.

+ 1 - 0
examples/storage/littlefs/flash_data/example.txt

@@ -0,0 +1 @@
+Example text to compile into a LittleFS disk image to be flashed to the ESP device.

+ 11 - 0
examples/storage/littlefs/main/CMakeLists.txt

@@ -0,0 +1,11 @@
+idf_component_register(SRCS "esp_littlefs_example.c"
+                    INCLUDE_DIRS "."
+                    )
+
+# Note: you must have a partition named the first argument (here it's "littlefs")
+# in your partition table csv file.
+if(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+    littlefs_create_partition_image(storage ../flash_data FLASH_IN_PROJECT)
+else()
+    fail_at_build_time(littlefs "Windows does not support LittleFS partition generation")
+endif()

+ 116 - 0
examples/storage/littlefs/main/esp_littlefs_example.c

@@ -0,0 +1,116 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Brian Pugh
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_system.h"
+#include "esp_littlefs.h"
+
+static const char *TAG = "esp_littlefs";
+
+void app_main(void)
+{
+    ESP_LOGI(TAG, "Initializing LittleFS");
+
+    esp_vfs_littlefs_conf_t conf = {
+        .base_path = "/littlefs",
+        .partition_label = "storage",
+        .format_if_mount_failed = true,
+        .dont_mount = false,
+    };
+
+    // Use settings defined above to initialize and mount LittleFS filesystem.
+    // Note: esp_vfs_littlefs_register is an all-in-one convenience function.
+    esp_err_t ret = esp_vfs_littlefs_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 LittleFS partition");
+        } else {
+            ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
+        }
+        return;
+    }
+
+    size_t total = 0, used = 0;
+    ret = esp_littlefs_info(conf.partition_label, &total, &used);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to get LittleFS partition information (%s)", esp_err_to_name(ret));
+        esp_littlefs_format(conf.partition_label);
+    } else {
+        ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
+    }
+
+    // Use POSIX and C standard library functions to work with files.
+    // First create a file.
+    ESP_LOGI(TAG, "Opening file");
+    FILE *f = fopen("/littlefs/hello.txt", "w");
+    if (f == NULL) {
+        ESP_LOGE(TAG, "Failed to open file for writing");
+        return;
+    }
+    fprintf(f, "Hello World!\n");
+    fclose(f);
+    ESP_LOGI(TAG, "File written");
+
+    // Check if destination file exists before renaming
+    struct stat st;
+    if (stat("/littlefs/foo.txt", &st) == 0) {
+        // Delete it if it exists
+        unlink("/littlefs/foo.txt");
+    }
+
+    // Rename original file
+    ESP_LOGI(TAG, "Renaming file");
+    if (rename("/littlefs/hello.txt", "/littlefs/foo.txt") != 0) {
+        ESP_LOGE(TAG, "Rename failed");
+        return;
+    }
+
+    // Open renamed file for reading
+    ESP_LOGI(TAG, "Reading file");
+    f = fopen("/littlefs/foo.txt", "r");
+    if (f == NULL) {
+        ESP_LOGE(TAG, "Failed to open file for reading");
+        return;
+    }
+
+    char line[128];
+    fgets(line, sizeof(line), f);
+    fclose(f);
+    // strip newline
+    char*pos = strchr(line, '\n');
+    if (pos) {
+        *pos = '\0';
+    }
+    ESP_LOGI(TAG, "Read from file: '%s'", line);
+
+    ESP_LOGI(TAG, "Reading from flashed filesystem example.txt");
+    f = fopen("/littlefs/example.txt", "r");
+    if (f == NULL) {
+        ESP_LOGE(TAG, "Failed to open file for reading");
+        return;
+    }
+    fgets(line, sizeof(line), f);
+    fclose(f);
+    // strip newline
+    pos = strchr(line, '\n');
+    if (pos) {
+        *pos = '\0';
+    }
+    ESP_LOGI(TAG, "Read from file: '%s'", line);
+
+    // All done, unmount partition and disable LittleFS
+    esp_vfs_littlefs_unregister(conf.partition_label);
+    ESP_LOGI(TAG, "LittleFS unmounted");
+}

+ 6 - 0
examples/storage/littlefs/main/idf_component.yml

@@ -0,0 +1,6 @@
+## IDF Component Manager Manifest File
+dependencies:
+  joltwallet/littlefs: "==1.5.5"
+  ## Required IDF version
+  idf:
+    version: ">=5.2.0"

+ 6 - 0
examples/storage/littlefs/partitions_demo_esp_littlefs.csv

@@ -0,0 +1,6 @@
+# Name,   Type, SubType, Offset,  Size, Flags
+# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
+nvs,      data, nvs,     0x9000,  0x6000,
+phy_init, data, phy,     0xf000,  0x1000,
+factory,  app,  factory, 0x10000, 1M,
+storage,  data, littlefs,      ,  0xF0000,

+ 2 - 0
examples/storage/littlefs/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_demo_esp_littlefs.csv"