ESP32文件系统esp_littlefs实例

本文介绍ESP32上的LittleFS文件系统的使用方法及优势。通过示例代码展示如何进行文件的创建、重命名、读取等操作,并提供配置指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

陈拓 2021/11/24-2021/11/25

1. 概述

https://github.com/joltwallet/esp_littlefs

LittleFS是一个用于微控制器的小型故障安全文件系统。我们将LittleFS移植到esp-idf(特别是ESP32),因为SPIFFS速度太慢,“臃肿”且脆弱。

2. 用法

有两种方法可以将此组件添加到项目中。

  • 作为ESP-IDF托管组件:在项目目录中运行

idf.py add-dependency joltwallet/littlefs==1.0.0

  • 作为子模块:在项目中,将其作为子模块添加到components/目录中

git submodule add https://github.com/joltwallet/esp_littlefs.git

git submodule update --init --recursive

mv esp_littlefs components/

现在就可以在项目中通过idf.py menuconfig下面的 Component config-> LittleFS配置库了。

3. 实例

User@wreyford提供了一份演示报告https://github.com/wreyford/demo_esp_littlefs

展示了esp_littlefs的使用。 在example/目录中有修改后的副本。

  • 克隆demo

git clone https://github.com/wreyford/demo_esp_littlefs.git

  • 文件夹内容

  • 配置

idf.py menuconfig

1)  设置定制分区表文件partitions_demo_esp_littlefs.csv

分区表文件partitions_demo_esp_littlefs.csv的内容:

2) 设置LittleFS文件系统

  • 编译项目

cd demo_esp_littlefs

idf.py build

如果出现:

刷新esp-idf环境:

get_idf

再编译。

对比之前的分区表:

  • 烧写项目

idf.py -p /dev/ttyS3 -b 115200 flash

  • 运行结果

文件操作示范,创建文件,写文件,文件改名,读文件。

程序流程:

  1. 初始化LittelFS
  2. 创建文件Opening file -> fopen("/littlefs/hello.txt", "w");
  3. 向文件写入字符串File written -> fprintf(f, "LittleFS Rocks!\n");
  4. 改文件名Renaming file -> rename("/littlefs/hello.txt", "/littlefs/foo.txt")
  5. 读文件Reading file -> fopen("/littlefs/foo.txt", "r");
  6. 读一行Read from file -> fgets(line, sizeof(line), f);
  7. 显示读结果 -> ESP_LOGI(TAG, "Read from file: '%s'", line);
  8. 卸载文件系统 -> esp_vfs_littlefs_unregister(conf.partition_label);

对应的C程序:

        printf("Now we are starting the LittleFs Demo ...\n");

        ESP_LOGI(TAG, "Initializing LittelFS");

        esp_vfs_littlefs_conf_t conf = {
            .base_path = "/littlefs",
            .partition_label = "littlefs",
            .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));
        }
        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, "LittleFS Rocks!\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[64];
        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);

        // All done, unmount partition and disable LittleFS
        esp_vfs_littlefs_unregister(conf.partition_label);
        ESP_LOGI(TAG, "LittleFS unmounted");
  • LittleFS在块上运行,在ESP32上块的大小为4096字节
  • 一个新格式化的LittleFS将有2个块在使用中,使它看起来像8KB在使用中。

### PlatformIO 中 ESP32 使用 SPI 接口操作 Flash 存储器 在 PlatformIO 开发环境中,ESP32 的 SPI 接口可以用于访问外部 Flash 存储器。以下是关于如何配置和实现这一功能的具体说明。 #### 配置环境 为了支持 SPI 操作 Flash 存储器,在 `platformio.ini` 文件中需要指定以下参数: ```ini [env:esp32dev] platform = espressif32@5.4.0 board = esp32dev framework = arduino monitor_speed = 115200 lib_deps = ArduinoEsp32SpiFlash ``` 上述配置指定了开发板为 `esp32dev` 并加载了 `ArduinoEsp32SpiFlash` 库来简化对 Flash 存储器的操作[^1]。 #### 示例代码 下面是一个简单的示例程序,演示如何通过 SPI 接口读取和写入 Flash 存储器的内容。 ```cpp #include <SPI.h> #include <FS.h> // Include the filesystem library #include <LittleFS.h> // Use LittleFS for flash memory operations void setup() { Serial.begin(115200); // Initialize LittleFS (or another file system you prefer) if (!LittleFS.begin()) { Serial.println("Failed to mount file system"); return; } // Write data to a file on the flash storage File file = LittleFS.open("/test.txt", "w"); if (!file) { Serial.println("Failed to open file for writing"); return; } file.println("Hello, Flash!"); file.close(); Serial.println("Data written to flash"); // Read data from the same file file = LittleFS.open("/test.txt", "r"); if (!file) { Serial.println("Failed to open file for reading"); return; } while (file.available()) { Serial.write(file.read()); } file.close(); } void loop() {} ``` 此代码片段展示了如何利用 `LittleFS` 文件系统库完成对 Flash 存储器的简单读/写操作。注意,这里使用的是内部 Flash 而不是外接 Flash 设备。如果目标设备是外接 Flash,则需进一步调整 SPI 初始化设置并手动管理地址映射[^2]。 #### 外部 Flash 支持 对于连接到 SPI 总线上的外部 Flash 芯片,通常需要额外定义其 CS(Chip Select)、CLK 和 MOSI/MISO 引脚位置,并初始化对应的驱动程序实例。例如: ```cpp #include <SPI.h> #define FLASH_CS_PIN 5 // GPIO pin connected to external flash chip select line SPIClass spi; // Create an instance of SPIClass object void setup() { pinMode(FLASH_CS_PIN, OUTPUT); digitalWrite(FLASH_CS_PIN, HIGH); spi.begin(); // Start communication with the peripheral device via SPI bus. } ``` 以上代码仅作为基础框架提供给开发者参考;实际应用时还需要依据具体型号的数据手册编写命令序列以执行擦除、编程等动作[^3]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨之清风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值