From b78477f2b0ac4740ac19e92515b9bc23d3843d2a Mon Sep 17 00:00:00 2001 From: Jade Mattsson Date: Thu, 17 Oct 2024 15:24:02 +1100 Subject: [PATCH] Fix 2x SPIFFS mounting/formatting related issues. - If the initial filesystem mounting fails, then a subsequent file.format() does not mount it afterwards, necessitating a node.restart(). In the normal case, after file.format() the filesystem is mounted and ready for use. We now explicitly remount after a format to gain consistent behaviour. - If using USB CDC, the auto-format on first boot interferes with USB enumeration, resulting in a failed startup. We now avoid doing an auto-format if the USB CDC console is enabled. The behaviour is configurable/overrideable via Kconfig. --- components/base_nodemcu/CMakeLists.txt | 2 +- components/base_nodemcu/user_main.c | 36 +++++--------------------- components/modules/file.c | 5 ++++ components/platform/CMakeLists.txt | 1 + components/platform/Kconfig | 12 +++++++++ components/platform/include/platform.h | 6 +++++ components/platform/platform.c | 36 ++++++++++++++++++++++++++ 7 files changed, 67 insertions(+), 31 deletions(-) diff --git a/components/base_nodemcu/CMakeLists.txt b/components/base_nodemcu/CMakeLists.txt index 9c891dad..4df26aee 100644 --- a/components/base_nodemcu/CMakeLists.txt +++ b/components/base_nodemcu/CMakeLists.txt @@ -2,6 +2,6 @@ idf_component_register( SRCS "ip_fmt.c" "user_main.c" INCLUDE_DIRS "include" REQUIRES "lua" - PRIV_REQUIRES "nvs_flash" "spiffs" "esp_netif" "driver" "vfs" "esp_vfs_console" + PRIV_REQUIRES "driver" "esp_netif" "esp_vfs_console" "nvs_flash" "vfs" LDFRAGMENTS "nodemcu.lf" ) diff --git a/components/base_nodemcu/user_main.c b/components/base_nodemcu/user_main.c index 33a1b780..82453afd 100644 --- a/components/base_nodemcu/user_main.c +++ b/components/base_nodemcu/user_main.c @@ -17,7 +17,6 @@ #include "sdkconfig.h" #include "esp_system.h" #include "esp_event.h" -#include "esp_spiffs.h" #include "esp_netif.h" #include "esp_vfs_dev.h" #include "esp_vfs_cdcacm.h" @@ -55,6 +54,10 @@ # define TX_LINE_ENDINGS_CFG ESP_LINE_ENDINGS_LF #endif +#ifndef CONFIG_NODEMCU_AUTO_FORMAT_ON_BOOT +# define CONFIG_NODEMCU_AUTO_FORMAT_ON_BOOT 0 +#endif + // We don't get argument size data from the esp_event dispatch, so it's // not possible to copy and forward events from the default event queue @@ -127,7 +130,6 @@ static void start_lua () static void nodemcu_init(void) { - NODE_ERR("\n"); // Initialize platform first for lua modules. if( platform_init() != PLATFORM_OK ) { @@ -135,34 +137,8 @@ static void nodemcu_init(void) NODE_DBG("Can not init platform for modules.\n"); return; } - const char *label = CONFIG_NODEMCU_DEFAULT_SPIFFS_LABEL; - - esp_vfs_spiffs_conf_t spiffs_cfg = { - .base_path = "", - .partition_label = (label && label[0]) ? label : NULL, - .max_files = CONFIG_NODEMCU_MAX_OPEN_FILES, - .format_if_mount_failed = true, - }; - const char *reason = NULL; - switch(esp_vfs_spiffs_register(&spiffs_cfg)) - { - case ESP_OK: break; - case ESP_ERR_NO_MEM: - reason = "out of memory"; - break; - case ESP_ERR_INVALID_STATE: - reason = "already mounted, or encrypted"; - break; - case ESP_ERR_NOT_FOUND: - reason = "no SPIFFS partition found"; - break; - case ESP_FAIL: - reason = "failed to mount or format partition"; - break; - default: - reason = "unknown"; - break; - } + const char *reason = + platform_remount_default_fs(CONFIG_NODEMCU_AUTO_FORMAT_ON_BOOT); if (reason) printf("Failed to mount SPIFFS partition: %s\n", reason); } diff --git a/components/modules/file.c b/components/modules/file.c index fae1c0bc..73cf8584 100644 --- a/components/modules/file.c +++ b/components/modules/file.c @@ -31,6 +31,11 @@ static int file_format( lua_State* L ) else{ NODE_ERR( "format done.\n" ); } + + const char *err = platform_remount_default_fs(false); + if (err) + return luaL_error(L, err); + return 0; } diff --git a/components/platform/CMakeLists.txt b/components/platform/CMakeLists.txt index 955f8dbb..3166c329 100644 --- a/components/platform/CMakeLists.txt +++ b/components/platform/CMakeLists.txt @@ -24,4 +24,5 @@ idf_component_register( "esp_rom" "lua" "soc" + "spiffs" ) diff --git a/components/platform/Kconfig b/components/platform/Kconfig index 0c9ee65b..f3711d3a 100644 --- a/components/platform/Kconfig +++ b/components/platform/Kconfig @@ -37,6 +37,18 @@ menu "NodeMCU platform config" opened. Raising this limit will incur some extra memory overhead. + config NODEMCU_AUTO_FORMAT_ON_BOOT + bool "Auto-format SPIFFS on first boot" + default "y" if !ESP_CONSOLE_USB_CDC + default "n" if ESP_CONSOLE_USB_CDC + help + The traditional behavior of NodeMCU is to automatically format + the SPIFFS partition on first boot (or any other time the + filesystem is unmountable). When using USB CDC however, the + formatting can interfere with USB device enumeration, leading + to a failed boot. In that case, disable the auto-format and + use file.format() after startup instead. + config NODEMCU_EMBED_LFS bool "Embed LFS as part of the NodeMCU firmware" default "n" diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index 42ec933a..f3e4e2dd 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -272,4 +272,10 @@ bool platform_partition_info (uint8_t idx, platform_partition_t *info); void platform_print_deprecation_note( const char *msg, const char *time_frame); +/** + * Mount or remount the default SPIFFS filesystem. + * @returns An error message string if the operation failed. + */ +const char *platform_remount_default_fs(bool autoformat); + #endif diff --git a/components/platform/platform.c b/components/platform/platform.c index 01b00f75..cb1f7935 100644 --- a/components/platform/platform.c +++ b/components/platform/platform.c @@ -11,6 +11,7 @@ #include "lua.h" #include "rom/uart.h" #include "esp_log.h" +#include "esp_spiffs.h" #include "task/task.h" #include "linput.h" @@ -670,3 +671,38 @@ void platform_print_deprecation_note( const char *msg, const char *time_frame) printf( "Warning, deprecated API! %s. It will be removed %s. See documentation for details.\n", msg, time_frame ); } + +const char *platform_remount_default_fs(bool autoformat) +{ + const char *label = CONFIG_NODEMCU_DEFAULT_SPIFFS_LABEL; + + if (esp_spiffs_mounted(label)) + esp_vfs_spiffs_unregister(label); + + esp_vfs_spiffs_conf_t spiffs_cfg = { + .base_path = "", + .partition_label = (label && label[0]) ? label : NULL, + .max_files = CONFIG_NODEMCU_MAX_OPEN_FILES, + .format_if_mount_failed = autoformat, + }; + const char *reason = NULL; + switch(esp_vfs_spiffs_register(&spiffs_cfg)) + { + case ESP_OK: + case ESP_ERR_INVALID_STATE: // already mounted (or encrypted) + break; + case ESP_ERR_NO_MEM: + reason = "out of memory"; + break; + case ESP_ERR_NOT_FOUND: + reason = "no SPIFFS partition found"; + break; + case ESP_FAIL: + reason = "failed to mount partition, use file.format() to reformat"; + break; + default: + reason = "unknown"; + break; + } + return reason; +}