diff --git a/components/base_nodemcu/CMakeLists.txt b/components/base_nodemcu/CMakeLists.txt index 9c891dad5..4df26aee8 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 906d337a8..b57de31b9 100644 --- a/components/base_nodemcu/user_main.c +++ b/components/base_nodemcu/user_main.c @@ -17,13 +17,15 @@ #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" +#include "esp_vfs_console.h" #include "esp_vfs_usb_serial_jtag.h" +#include "driver/uart_vfs.h" #include "driver/usb_serial_jtag.h" #include "driver/uart_vfs.h" +#include "driver/usb_serial_jtag_vfs.h" #include "nvs_flash.h" #include "task/task.h" @@ -54,6 +56,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 @@ -126,7 +132,6 @@ static void start_lua () static void nodemcu_init(void) { - NODE_ERR("\n"); // Initialize platform first for lua modules. if( platform_init() != PLATFORM_OK ) { @@ -134,34 +139,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); } @@ -260,15 +239,15 @@ static void console_init(void) #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG /* Based on @pjsg's work */ - esp_vfs_dev_usb_serial_jtag_set_rx_line_endings(RX_LINE_ENDINGS_CFG); - esp_vfs_dev_usb_serial_jtag_set_tx_line_endings(TX_LINE_ENDINGS_CFG); + usb_serial_jtag_vfs_set_rx_line_endings(RX_LINE_ENDINGS_CFG); + usb_serial_jtag_vfs_set_tx_line_endings(TX_LINE_ENDINGS_CFG); usb_serial_jtag_driver_config_t usb_serial_jtag_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(); /* Install USB-SERIAL-JTAG driver for interrupt-driven reads and write */ usb_serial_jtag_driver_install(&usb_serial_jtag_config); - esp_vfs_usb_serial_jtag_use_driver(); + usb_serial_jtag_vfs_use_driver(); #elif CONFIG_ESP_CONSOLE_USB_CDC /* Based on console/advanced_usb_cdc */ @@ -279,7 +258,8 @@ static void console_init(void) #endif xTaskCreate( - console_task, "console", 1024, NULL, ESP_TASK_MAIN_PRIO+1, NULL); + console_task, "console", configMINIMAL_STACK_SIZE, + NULL, ESP_TASK_MAIN_PRIO+1, NULL); } diff --git a/components/modules/Kconfig b/components/modules/Kconfig index ce13f848d..19c869755 100644 --- a/components/modules/Kconfig +++ b/components/modules/Kconfig @@ -323,6 +323,18 @@ menu "NodeMCU modules" help Includes the WiFi module (recommended). + config NODEMCU_CMODULE_WIFI_STARTUP_DELAY + depends on NODEMCU_CMODULE_WIFI + depends on ESP_CONSOLE_USB_CDC + int "WiFi start-up delay (ms)" + default 500 + help + For some unknown reason there is an issue with allowing the + WiFi stack to initialise immediately when using a USB CDC + console (at least on the ESP32-S2). The workaround is to + delay the initialisation sequence by enough that whatever + else is needing to run gets to run first. + config NODEMCU_CMODULE_WS2812 bool "WS2812 module" default "n" diff --git a/components/modules/eth.c b/components/modules/eth.c index 253935b1b..7ab7d8ffa 100644 --- a/components/modules/eth.c +++ b/components/modules/eth.c @@ -274,9 +274,9 @@ static int leth_init( lua_State *L ) eth_esp32_emac_config_t emac_cfg = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - emac_cfg.smi_mdc_gpio_num = + emac_cfg.smi_gpio.mdc_num = opt_checkint_range( L, "mdc", -1, GPIO_NUM_0, GPIO_NUM_MAX-1 ); - emac_cfg.smi_mdio_gpio_num = + emac_cfg.smi_gpio.mdio_num = opt_checkint_range( L, "mdio", -1, GPIO_NUM_0, GPIO_NUM_MAX-1 ); eth_mac_config_t mac_cfg = ETH_MAC_DEFAULT_CONFIG(); diff --git a/components/modules/file.c b/components/modules/file.c index fae1c0bc6..73cf8584b 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/modules/node.c b/components/modules/node.c index 6dc1b3eea..247a0531e 100644 --- a/components/modules/node.c +++ b/components/modules/node.c @@ -113,7 +113,7 @@ static int node_bootreason( lua_State *L) #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C6) case SDIO_RESET: #endif -#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32H2) +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) case GLITCH_RTC_RESET: #endif #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C5) @@ -122,6 +122,9 @@ static int node_bootreason( lua_State *L) #if defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) case JTAG_RESET: #endif +#if defined(CONFIG_IDF_TARGET_ESP32H2) + case JTAG_CPU_RESET: +#endif #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C5) case USB_UART_CHIP_RESET: case USB_JTAG_CHIP_RESET: @@ -131,7 +134,7 @@ static int node_bootreason( lua_State *L) #endif case TG0WDT_SYS_RESET: case TG1WDT_SYS_RESET: -#if !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C5) +#if !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32H2) case INTRUSION_RESET: #endif case RTCWDT_BROWN_OUT_RESET: diff --git a/components/modules/wifi.c b/components/modules/wifi.c index f16b98331..81b86a0e8 100644 --- a/components/modules/wifi.c +++ b/components/modules/wifi.c @@ -93,22 +93,6 @@ static int wifi_stop (lua_State *L) 0 : luaL_error (L, "failed to stop wifi, code %d", err); } -#if defined(CONFIG_ESP_CONSOLE_USB_CDC) -// For some unknown reason, on an S2 with USB CDC console enabled, if we allow -// the esp_wifi_init() to run during initial startup, something Bad(tm) -// happens and the S2 fails to enumerate on the USB bus. However, if we defer -// the wifi initialisation, it starts up fine. This is an ugly workaround, but -// I'm out of ideas at this point. If I use a UART console, I see no errors -// even with the immediate init. -static task_handle_t th; -#endif - -static void do_esp_wifi_init(task_param_t p, task_prio_t) -{ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init (&cfg)); -} - extern void wifi_ap_init (void); extern void wifi_sta_init (void); static int wifi_init (lua_State *L) @@ -117,11 +101,16 @@ static int wifi_init (lua_State *L) wifi_sta_init (); #if defined(CONFIG_ESP_CONSOLE_USB_CDC) - th = task_get_id(do_esp_wifi_init); - task_post_low(th, 0); -#else - do_esp_wifi_init(0, 0); +// For some unknown reason, on an S2 with USB CDC console enabled, if we allow +// the esp_wifi_init() to run during initial startup, something Bad(tm) +// happens and the S2 fails to enumerate on the USB bus. However, if we defer +// it by half a second or so, everything works. This is an ugly workaround, +// but I'm out of ideas at this point. + vTaskDelay(CONFIG_NODEMCU_CMODULE_WIFI_STARTUP_DELAY / portTICK_PERIOD_MS); #endif + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init (&cfg)); + return 0; } diff --git a/components/platform/CMakeLists.txt b/components/platform/CMakeLists.txt index 955f8dbb4..3166c3296 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 35da71c44..fbf5ff8c7 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" @@ -81,6 +93,7 @@ menu "NodeMCU platform config" default y if IDF_TARGET_ESP32 default y if IDF_TARGET_ESP32S3 default y if IDF_TARGET_ESP32C5 + default y if IDF_TARGET_ESP32C6 config NODEMCU_UART_DRIVER_BUF_SIZE_RX0 int "RX buffer size for UART0" diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index 42ec933a6..f3e4e2dd8 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 86606df8c..cb1f79354 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" @@ -215,7 +216,7 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari uart_config_t cfg = { .baud_rate = baud, .flow_ctrl = flow_control, - .rx_flow_ctrl_thresh = UART_FIFO_LEN - 16, + .rx_flow_ctrl_thresh = UART_HW_FIFO_LEN(id) - 16, .source_clk = UART_SCLK_DEFAULT, }; @@ -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; +}