Wemos Mini ESP8266使用LittleFS写入JSON文件时崩溃求助
ESP8266 LittleFS写入JSON频繁崩溃问题排查
问题场景
使用Wemos Mini ESP8266开发控制面板,尝试通过LittleFS将JSON数据写入文件时,设备频繁崩溃,触发LoadStoreError异常。
原代码
#include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <Wire.h> #include <LittleFS.h> #include <ArduinoJson.h> #include <Arduino.h> const char* ssid = "wifi01"; const char* password = "password01"; const char *dataFile = "/data.json"; unsigned long last_save = 0; ESP8266WebServer server(80); void handleRoot() { server.send(200, "text/plain", "Index page"); } bool saveData() { LittleFS.begin(); StaticJsonDocument<200> doc; doc["foo"] = 10; doc["bar"] = 50; File data = LittleFS.open(dataFile, "w"); serializeJson(doc, data); LittleFS.end(); return true; } void setup(void) { Serial.begin(9600); WiFi.mode(WIFI_AP); WiFi.softAP(ssid, password); IPAddress myIP = WiFi.softAPIP(); server.on("/", handleRoot); server.begin(); Serial.println("Server started"); last_save = millis(); } void loop(void) { server.handleClient(); if(millis() - last_save > 5000){ saveData(); } }
异常栈
Exception (3): epc1=0x4010076d epc2=0x00000000 epc3=0x00000000 excvaddr=0x4006f441 depc=0x00000000 >>>stack>>> ctx: cont sp: 3ffffcc0 end: 3fffffd0 offset: 0150 3ffffe10: 402021dc 3ffffe20 ffffffff 00002000 3ffffe20: 00000040 3ffef8fc 00000020 401009f4 3ffffe30: 00000000 00000001 3ffef884 40202a3c 3ffffe40: 0000ef6f 00000001 3ffefc36 3ffef884 3ffffe50: 3ffeea44 3ffef884 3ffef87c 40204a1f 3ffffe60: 00000008 3ffffed0 37400000 402044fc 3ffffe70: 00000000 00000001 00000003 000011c0 3ffffe80: 500ffc30 00010002 ffffffff ffffffff 3ffffe90: 37400408 3ffffed0 00000005 00000005 3ffffea0: 000007e0 000000fc 3ffe85ec 40100672 3ffffeb0: 00000a80 00000150 3ffe85ec 40100672 3ffffec0: 00000988 00000131 3ffe85ec 40100672 3ffffed0: 00000cb8 00000197 3ffe85ec 3ffeeb54 3ffffee0: 3ffeea44 3ffef884 3ffef87c 4020a97d 3ffffef0: 3fffff1c 00000000 3ffef87c 4020aa7c 3fffff00: 3ffeea44 00000000 3ffeeb28 402085b6 3fffff10: 3ffe85d4 3fffda00 00000000 00000000 3fffff20: 00000000 feefeffe feefeffe feefeffe 3fffff30: 40207d0c feefeffe 40210584 40209f36 3fffff40: 00040000 feefffff 00030000 ffff0020 3fffff50: 402114e8 3fffff70 00000001 402109dc 3fffff60: 3fffdad0 00000000 3ffee7f0 4020898d 3fffff70: 4021126c 00000000 00001388 3fffff50 3fffff80: 00000000 00001461 970a3d70 001790d6 3fffff90: 00000000 00000000 feefeffe 3ffeeb54 3fffffa0: 3fffdad0 00000000 3ffeeb28 3ffeeb54 3fffffb0: 3fffdad0 00000000 3ffeeb28 4020e2c8 3fffffc0: feefeffe feefeffe 3fffdab0 40100c99 <<<stack<<<
解码后的异常信息
Exception 3: LoadStoreError: Processor internal physical address or data error during load or store PC: 0x4010076d EXCVADDR: 0x4006f441 Decoding stack results 0x402021dc: lfs_dir_find_match at c:\users\������\appdata\local\arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\littlefs\lib\littlefs/lfs.c line 1296 0x401009f4: malloc(size_t) at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 912 0x40202a3c: lfs_init at c:\users\������\appdata\local\arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\littlefs\lib\littlefs/lfs_util.h line 221 0x40204a1f: lfs_mount at c:\users\������\appdata\local\arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\littlefs\lib\littlefs/lfs.c line 4097 0x402044fc: lfs_commitattr at c:\users\������\appdata\local\arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\littlefs\lib\littlefs/lfs.c line 3880 0x40100672: umm_free_core(umm_heap_context_t*, void*) at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 642 0x40100672: umm_free_core(umm_heap_context_t*, void*) at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 642 0x40100672: umm_free_core(umm_heap_context_t*, void*) at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 642 0x4020a97d: littlefs_impl::LittleFSImpl::_tryMount() at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\LittleFS\src/LittleFS.h line 285 0x4020aa7c: littlefs_impl::LittleFSImpl::begin() at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\LittleFS\src/LittleFS.h line 193 0x402085b6: saveData() at C:\Users\������\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Memory/ResourceManager.hpp line 31 0x40207d0c: handleRoot() at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WebServer\src/ESP8266WebServer-impl.h line 518 0x40210584: std::_Function_handler ::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\������\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 268 0x40209f36: WiFiServer::accept() at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WiFi\src\WiFiServer.cpp line 151 0x402109dc: WiFiClient::operator bool() at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WiFi\src\WiFiClient.cpp line 342 0x4020898d: esp8266webserver::ESP8266WebServerTemplate ::handleClient() at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WebServer\src/ESP8266WebServer-impl.h line 282 0x4020e2c8: loop_wrapper() at C:\Users\������\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 258
问题分析与修复
从异常栈可知,崩溃发生在LittleFS挂载操作环节,核心原因是频繁调用LittleFS.begin()和LittleFS.end()。每次调用begin()都会重新挂载文件系统,频繁挂载卸载会引发Flash操作冲突,导致内存或地址错误。此外,文件操作后未关闭File对象,可能造成资源泄漏。
修复要点:
- 在
setup()中仅挂载一次LittleFS,无需每次写入重复执行挂载卸载。 - 文件写入完成后调用
File.close()释放资源。 - 添加错误检查,确保LittleFS挂载、文件打开操作成功,避免空指针操作。
修改后的代码
#include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <Wire.h> #include <LittleFS.h> #include <ArduinoJson.h> #include <Arduino.h> const char* ssid = "wifi01"; const char* password = "password01"; const char *dataFile = "/data.json"; unsigned long last_save = 0; ESP8266WebServer server(80); void handleRoot() { server.send(200, "text/plain", "Index page"); } bool saveData() { StaticJsonDocument<200> doc; doc["foo"] = 10; doc["bar"] = 50; // 打开文件并检查是否成功 File data = LittleFS.open(dataFile, "w"); if (!data) { Serial.println("Failed to open file for writing"); return false; } // 序列化JSON并写入文件 serializeJson(doc, data); // 关闭文件释放资源 data.close(); Serial.println("Data saved successfully"); return true; } void setup(void) { Serial.begin(9600); // 仅挂载一次LittleFS,添加错误处理 if (!LittleFS.begin()) { Serial.println("LittleFS mount failed"); return; } Serial.println("LittleFS mounted successfully"); WiFi.mode(WIFI_AP); WiFi.softAP(ssid, password); IPAddress myIP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(myIP); server.on("/", handleRoot); server.begin(); Serial.println("Server started"); last_save = millis(); } void loop(void) { server.handleClient(); if(millis() - last_save > 5000){ saveData(); last_save = millis(); // 更新时间戳,避免重复触发 } }
额外建议
- 降低Flash写入频率:ESP8266的Flash有写入寿命限制,频繁写入会缩短设备寿命,可根据实际需求调整写入间隔。
- 启用LittleFS格式化:如果首次使用或Flash存在损坏,可在挂载失败时执行格式化:
if (!LittleFS.begin()) { Serial.println("LittleFS mount failed, formatting..."); LittleFS.format(); if (!LittleFS.begin()) { Serial.println("Format failed, cannot use LittleFS"); return; } }
内容的提问来源于stack exchange,提问作者Yukio Ito
相关产品推荐
相关产品推荐

