Initial support for ESP32-C6 and ESP32-H2, plus assorted fixes & improvements (#3646)

* Proof-of-concept multi-type console support via stdio

* Address crashes on linput's use of printf.

On an empty line input, a C3 with UART console would panic while attempting
to output the new Lua prompt. The backtrace shows a xQueueSemaphoreTake
with uxItemSize==0 as the panic cause, deep inside the uart driver, invoked
via vfs_uart and vfs_console layers, from printf.
Similarly, the printf for outputting a backspace/erase sequence would also
trigger a panic.

This workaround (of not mixing fflush() with printf) is likely merely hiding
a deeper issue, but it appears to be consistent. Plus, printf with no args
and a user-supplied format string is a no-no and should be fixed anyway.

* Work around IDF inconsistency with stdout buffering.

* Increase console task stack size.

Seems on Xtensa it ended up not being enough.

* Switch to single-byte console reads.

* Stop cheating and feed Lua from the right context.

* Work around IDF buffering stdout even when told not to, on ACM consoles.

* Initial build support for esp32c6.

Plus fixup of module selection for a variety of targets.

* Update github actions to node 20 versions.

* Update github build to deal with Lua 5.3 being default.

* Address fatal compiler warning.

Newer IDF toolchain is stricter, and we'd apparently failed to build test
the Lua-5.1 path for some time.

* Initial build support for esp32h2.

* Upgrade IDF to v5.1.3

* Fix left-over incorrect type in uzlib.

* Avoid null pointer crashes when debugging startup.

* Workaround for using wifi module on S2 with USB-CDC console.

---------

Co-authored-by: Jade Mattsson <github@frozenlogic.org>
This commit is contained in:
Jade Mattsson 2024-04-27 07:35:22 +10:00 committed by GitHub
parent bc3b31fee5
commit 4cdebe7191
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 250 additions and 54 deletions

View File

@ -10,19 +10,19 @@ jobs:
matrix: matrix:
lua_ver: ['5.1', '5.3'] lua_ver: ['5.1', '5.3']
numbers: ['default', 'alternate'] numbers: ['default', 'alternate']
target: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3'] target: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Prepare cache key - name: Prepare cache key
run: git rev-parse HEAD:sdk/esp32-esp-idf > idf.rev run: git rev-parse HEAD:sdk/esp32-esp-idf > idf.rev
shell: bash shell: bash
- name: Cache Espressif tools - name: Cache Espressif tools
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ~/.espressif path: ~/.espressif
key: ${{ runner.os }}-espressif-tools-${{ hashFiles('idf.rev') }} key: ${{ runner.os }}-espressif-tools-${{ hashFiles('idf.rev') }}
@ -33,6 +33,11 @@ jobs:
run: | run: |
cp sdkconfig.defaults sdkconfig cp sdkconfig.defaults sdkconfig
shell: bash shell: bash
- name: Update config for Lua 5.1
if: ${{ matrix.lua_ver == '5.1' }}
run: |
echo CONFIG_LUA_VERSION_51=y >> sdkconfig
shell: bash
- name: Update config for Lua 5.1, integer-only - name: Update config for Lua 5.1, integer-only
if: ${{ matrix.lua_ver == '5.1' && matrix.numbers == 'alternate' }} if: ${{ matrix.lua_ver == '5.1' && matrix.numbers == 'alternate' }}
run: | run: |
@ -58,7 +63,7 @@ jobs:
echo lua_build_opts="$(expr "$(./build/luac_cross/luac.cross -v)" : '.*\[\(.*\)\]')" >> $GITHUB_ENV echo lua_build_opts="$(expr "$(./build/luac_cross/luac.cross -v)" : '.*\[\(.*\)\]')" >> $GITHUB_ENV
shell: bash shell: bash
- name: Upload luac.cross - name: Upload luac.cross
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
if: ${{ success() }} if: ${{ success() }}
with: with:
name: luac.cross-${{ env.lua_build_opts }}-${{ matrix.target }} name: luac.cross-${{ env.lua_build_opts }}-${{ matrix.target }}

View File

@ -2,6 +2,6 @@ idf_component_register(
SRCS "ip_fmt.c" "user_main.c" SRCS "ip_fmt.c" "user_main.c"
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
REQUIRES "lua" REQUIRES "lua"
PRIV_REQUIRES "nvs_flash" "spiffs" "esp_netif" "driver" PRIV_REQUIRES "nvs_flash" "spiffs" "esp_netif" "driver" "vfs"
LDFRAGMENTS "nodemcu.lf" LDFRAGMENTS "nodemcu.lf"
) )

View File

@ -13,11 +13,16 @@
#include "platform.h" #include "platform.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h>
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_event.h" #include "esp_event.h"
#include "esp_spiffs.h" #include "esp_spiffs.h"
#include "esp_netif.h" #include "esp_netif.h"
#include "esp_vfs_dev.h"
#include "esp_vfs_cdcacm.h"
#include "esp_vfs_usb_serial_jtag.h"
#include "driver/usb_serial_jtag.h"
#include "nvs_flash.h" #include "nvs_flash.h"
#include "task/task.h" #include "task/task.h"
@ -48,6 +53,8 @@ typedef struct {
static task_handle_t relayed_event_task; static task_handle_t relayed_event_task;
static SemaphoreHandle_t relayed_event_handled; static SemaphoreHandle_t relayed_event_handled;
static task_handle_t lua_feed_task;
// This function runs in the context of the system default event loop RTOS task // This function runs in the context of the system default event loop RTOS task
static void relay_default_loop_events( static void relay_default_loop_events(
@ -98,7 +105,7 @@ static void start_lua ()
lua_main(); lua_main();
} }
void nodemcu_init(void) static void nodemcu_init(void)
{ {
NODE_ERR("\n"); NODE_ERR("\n");
// Initialize platform first for lua modules. // Initialize platform first for lua modules.
@ -141,10 +148,111 @@ void nodemcu_init(void)
} }
static void console_nodemcu_task(task_param_t param, task_prio_t prio)
{
(void)prio;
char c = (char)param;
feed_lua_input(&c, 1);
// The IDF doesn't seem to honor setvbuf(stdout, NULL, _IONBF, 0) :(
fsync(fileno(stdout));
}
static void console_task(void *)
{
for (;;)
{
/* We can't use a large read buffer here as some console choices
* (e.g. usb-serial-jtag) don't support read timeouts/partial reads,
* which breaks the echo support and makes for a bad user experience.
*/
char c;
ssize_t n = read(fileno(stdin), &c, 1);
if (n > 0 && run_input)
{
if (!task_post_block_high(lua_feed_task, (task_param_t)c))
{
NODE_ERR("Lost console input data?!\n");
}
}
}
}
static void console_init(void)
{
fflush(stdout);
fsync(fileno(stdout));
/* Disable buffering */
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
/* Disable non-blocking mode */
fcntl(fileno(stdin), F_SETFL, 0);
fcntl(fileno(stdout), F_SETFL, 0);
#if CONFIG_ESP_CONSOLE_UART_DEFAULT || CONFIG_ESP_CONSOLE_UART_CUSTOM
/* Based on console/advanced example */
esp_vfs_dev_uart_port_set_rx_line_endings(
CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
esp_vfs_dev_uart_port_set_tx_line_endings(
CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
/* Configure UART. Note that REF_TICK is used so that the baud rate remains
* correct while APB frequency is changing in light sleep mode.
*/
const uart_config_t uart_config = {
.baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
#if SOC_UART_SUPPORT_REF_TICK
.source_clk = UART_SCLK_REF_TICK,
#elif SOC_UART_SUPPORT_XTAL_CLK
.source_clk = UART_SCLK_XTAL,
#endif
};
/* Install UART driver for interrupt-driven reads and writes */
uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM, 256, 0, 0, NULL, 0);
uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config);
/* Tell VFS to use UART driver */
esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
/* Based on @pjsg's work */
esp_vfs_dev_usb_serial_jtag_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
esp_vfs_dev_usb_serial_jtag_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
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();
#elif CONFIG_ESP_CONSOLE_USB_CDC
/* Based on console/advanced_usb_cdc */
esp_vfs_dev_cdcacm_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
esp_vfs_dev_cdcacm_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
#else
# error "Unsupported console type"
#endif
xTaskCreate(
console_task, "console", 1024, NULL, ESP_TASK_MAIN_PRIO+1, NULL);
}
void __attribute__((noreturn)) app_main(void) void __attribute__((noreturn)) app_main(void)
{ {
task_init(); task_init();
lua_feed_task = task_get_id(console_nodemcu_task);
relayed_event_handled = xSemaphoreCreateBinary(); relayed_event_handled = xSemaphoreCreateBinary();
relayed_event_task = task_get_id(handle_default_loop_event); relayed_event_task = task_get_id(handle_default_loop_event);
@ -155,14 +263,13 @@ void __attribute__((noreturn)) app_main(void)
relay_default_loop_events, relay_default_loop_events,
NULL); NULL);
platform_uart_start(CONFIG_ESP_CONSOLE_UART_NUM);
setvbuf(stdout, NULL, _IONBF, 0);
nodemcu_init (); nodemcu_init ();
nvs_flash_init (); nvs_flash_init ();
esp_netif_init (); esp_netif_init ();
console_init();
start_lua (); start_lua ();
task_pump_messages (); task_pump_messages ();
__builtin_unreachable (); __builtin_unreachable ();

View File

@ -3,6 +3,7 @@
#include "lua.h" #include "lua.h"
#include "lauxlib.h" #include "lauxlib.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
static struct input_state { static struct input_state {
char *data; char *data;
@ -10,7 +11,9 @@ static struct input_state {
size_t len; size_t len;
const char *prompt; const char *prompt;
char last_nl_char; char last_nl_char;
} ins = {0}; } ins = {
.prompt = "? ", // prompt should never be allowed to be null
};
#define NUL '\0' #define NUL '\0'
#define BS '\010' #define BS '\010'
@ -22,6 +25,15 @@ static struct input_state {
bool input_echo = true; bool input_echo = true;
bool run_input = true; bool run_input = true;
void input_setprompt (const char *prompt) {
if (prompt == NULL)
{
fprintf(stderr, "Error: attempted to set a null prompt?!");
return;
}
ins.prompt = prompt;
}
/* /*
** The input state (ins) is private, so input_setup() exposes the necessary ** The input state (ins) is private, so input_setup() exposes the necessary
** access to public properties and is called in user_init() before the Lua ** access to public properties and is called in user_init() before the Lua
@ -31,11 +43,8 @@ void input_setup(int bufsize, const char *prompt) {
// Initialise non-zero elements // Initialise non-zero elements
ins.data = malloc(bufsize); ins.data = malloc(bufsize);
ins.len = bufsize; ins.len = bufsize;
ins.prompt = prompt; // Call to get the prompt error checking
} input_setprompt(prompt);
void input_setprompt (const char *prompt) {
ins.prompt = prompt;
} }
@ -59,7 +68,7 @@ size_t feed_lua_input(const char *buf, size_t n)
/* backspace key */ /* backspace key */
if (ch == DEL || ch == BS) { if (ch == DEL || ch == BS) {
if (ins.line_pos > 0) { if (ins.line_pos > 0) {
if(input_echo) printf(BS_OVER); if(input_echo) fwrite(BS_OVER, strlen(BS_OVER), 1, stdout);
ins.line_pos--; ins.line_pos--;
} }
ins.data[ins.line_pos] = 0; ins.data[ins.line_pos] = 0;
@ -73,7 +82,7 @@ size_t feed_lua_input(const char *buf, size_t n)
if (input_echo) putchar(LF); if (input_echo) putchar(LF);
if (ins.line_pos == 0) { if (ins.line_pos == 0) {
/* Get a empty line, then go to get a new line */ /* Get a empty line, then go to get a new line */
printf(ins.prompt); fwrite(ins.prompt, strlen(ins.prompt), 1, stdout);
fflush(stdout); fflush(stdout);
} else { } else {
ins.data[ins.line_pos++] = LF; ins.data[ins.line_pos++] = LF;

View File

@ -178,7 +178,7 @@ static void DumpCode(const Proto *f, DumpState* D)
static void DumpString(const TString* s, DumpState* D) static void DumpString(const TString* s, DumpState* D)
{ {
if (s==NULL || getstr(s)==NULL) if (s==NULL)
{ {
strsize_t size=0; strsize_t size=0;
DumpSize(size,D); DumpSize(size,D);

View File

@ -6,6 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "user_version.h" #include "user_version.h"
#include "linput.h" #include "linput.h"
@ -211,6 +212,7 @@ static void dojob (lua_State *L) {
prompt = get_prompt(L, MLref!= LUA_NOREF ? 0 : 1); prompt = get_prompt(L, MLref!= LUA_NOREF ? 0 : 1);
input_setprompt(prompt); input_setprompt(prompt);
lua_writestring(prompt,strlen(prompt)); lua_writestring(prompt,strlen(prompt));
fsync(fileno(stdout)); /* work around IDF issue on ACM consoles */
} }

View File

@ -1,4 +1,11 @@
# Modules common to all chips # Modules common to all chips
set(wifi_modules
"espnow.c"
"wifi.c"
"wifi_ap.c"
"wifi_common.c"
"wifi_sta.c"
)
set(module_srcs set(module_srcs
"adc.c" "adc.c"
"bit.c" "bit.c"
@ -8,7 +15,6 @@ set(module_srcs
"dht.c" "dht.c"
"encoder.c" "encoder.c"
"eromfs.c" "eromfs.c"
"espnow.c"
"file.c" "file.c"
"gpio.c" "gpio.c"
"heaptrace.c" "heaptrace.c"
@ -24,6 +30,7 @@ set(module_srcs
"otaupgrade.c" "otaupgrade.c"
"ow.c" "ow.c"
"pipe.c" "pipe.c"
"rmt.c"
"rtcmem.c" "rtcmem.c"
"qrcodegen.c" "qrcodegen.c"
"sigma_delta.c" "sigma_delta.c"
@ -37,10 +44,6 @@ set(module_srcs
"u8g2.c" "u8g2.c"
"uart.c" "uart.c"
"ucg.c" "ucg.c"
"wifi.c"
"wifi_ap.c"
"wifi_common.c"
"wifi_sta.c"
"ws2812.c" "ws2812.c"
) )
@ -53,25 +56,34 @@ if(IDF_TARGET STREQUAL "esp32")
"eth.c" "eth.c"
"i2s.c" "i2s.c"
"pulsecnt.c" "pulsecnt.c"
"rmt.c"
"sdmmc.c" "sdmmc.c"
"touch.c" "touch.c"
${wifi_modules}
) )
elseif(IDF_TARGET STREQUAL "esp32s2") elseif(IDF_TARGET STREQUAL "esp32s2")
list(APPEND module_srcs list(APPEND module_srcs
"dac.c" "dac.c"
"pulsecnt.c" "pulsecnt.c"
"rmt.c" ${wifi_modules}
) )
elseif(IDF_TARGET STREQUAL "esp32s3") elseif(IDF_TARGET STREQUAL "esp32s3")
list(APPEND module_srcs list(APPEND module_srcs
"dac.c"
"pulsecnt.c" "pulsecnt.c"
"rmt.c"
"sdmmc.c" "sdmmc.c"
${wifi_modules}
) )
elseif(IDF_TARGET STREQUAL "esp32c3") elseif(IDF_TARGET STREQUAL "esp32c3")
list(APPEND module_srcs list(APPEND module_srcs
"rmt.c" )
elseif(IDF_TARGET STREQUAL "esp32c6")
list(APPEND module_srcs
"dac.c"
"pulsecnt.c"
${wifi_modules}
)
elseif(IDF_TARGET STREQUAL "esp32h2")
list(APPEND module_srcs
) )
endif() endif()

View File

@ -35,7 +35,7 @@ menu "NodeMCU modules"
Includes the crypto module. Includes the crypto module.
config NODEMCU_CMODULE_DAC config NODEMCU_CMODULE_DAC
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32_C6
bool "DAC module" bool "DAC module"
default "n" default "n"
help help
@ -83,6 +83,7 @@ menu "NodeMCU modules"
does. does.
config NODEMCU_CMODULE_ESPNOW config NODEMCU_CMODULE_ESPNOW
depends on !IDF_TARGET_ESP32H2
bool "ESP-NOW module" bool "ESP-NOW module"
default "n" default "n"
help help
@ -210,7 +211,7 @@ menu "NodeMCU modules"
Includes the pipe module (required by our Lua VM). Includes the pipe module (required by our Lua VM).
config NODEMCU_CMODULE_PULSECNT config NODEMCU_CMODULE_PULSECNT
depends on IDF_TARGET_ESP32 depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6
bool "Pulse counter module" bool "Pulse counter module"
default "n" default "n"
help help
@ -239,7 +240,7 @@ menu "NodeMCU modules"
the battery backed memory. the battery backed memory.
config NODEMCU_CMODULE_SDMMC config NODEMCU_CMODULE_SDMMC
depends on IDF_TARGET_ESP32 depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3
bool "SD-MMC module" bool "SD-MMC module"
default "n" default "n"
help help
@ -309,6 +310,7 @@ menu "NodeMCU modules"
rsource "../ucg/Kconfig.ucg" rsource "../ucg/Kconfig.ucg"
config NODEMCU_CMODULE_WIFI config NODEMCU_CMODULE_WIFI
depends on !IDF_TARGET_ESP32H2
bool "WiFi module" bool "WiFi module"
default "y" default "y"
help help

View File

@ -107,21 +107,30 @@ static int node_bootreason( lua_State *L)
case EXT_CPU_RESET: case EXT_CPU_RESET:
#endif #endif
case DEEPSLEEP_RESET: case DEEPSLEEP_RESET:
#if defined(CONFIG_IDF_TARGET_ESP32) #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C6)
case SDIO_RESET: case SDIO_RESET:
#endif #endif
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32H2)
case GLITCH_RTC_RESET: 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)
case EFUSE_RESET: case EFUSE_RESET:
#endif #endif
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) #if defined(CONFIG_IDF_TARGET_ESP32C6)
case JTAG_RESET:
#endif
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2)
case USB_UART_CHIP_RESET: case USB_UART_CHIP_RESET:
case USB_JTAG_CHIP_RESET: case USB_JTAG_CHIP_RESET:
#endif
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32H2)
case POWER_GLITCH_RESET: case POWER_GLITCH_RESET:
#endif #endif
case TG0WDT_SYS_RESET: case TG0WDT_SYS_RESET:
case TG1WDT_SYS_RESET: case TG1WDT_SYS_RESET:
#if !defined(CONFIG_IDF_TARGET_ESP32C6)
case INTRUSION_RESET: case INTRUSION_RESET:
#endif
case RTCWDT_BROWN_OUT_RESET: case RTCWDT_BROWN_OUT_RESET:
case RTCWDT_RTC_RESET: case RTCWDT_RTC_RESET:
rawinfo = 3; break; rawinfo = 3; break;
@ -262,7 +271,7 @@ static int node_sleep (lua_State *L)
esp_sleep_enable_timer_wakeup(usecs); esp_sleep_enable_timer_wakeup(usecs);
} }
#if !defined(CONFIG_IDF_TARGET_ESP32C3) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
// touch option: boolean // touch option: boolean
if (opt_checkbool(L, "touch", false)) { if (opt_checkbool(L, "touch", false)) {
int err = esp_sleep_enable_touchpad_wakeup(); int err = esp_sleep_enable_touchpad_wakeup();
@ -335,7 +344,7 @@ static int node_dsleep (lua_State *L)
} }
} }
#if !defined(CONFIG_IDF_TARGET_ESP32C3) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
bool pull = opt_checkbool(L, "pull", false); bool pull = opt_checkbool(L, "pull", false);
if (opt_get(L, "isolate", LUA_TTABLE)) { if (opt_get(L, "isolate", LUA_TTABLE)) {
for (int i = 1; ; i++) { for (int i = 1; ; i++) {

View File

@ -34,6 +34,7 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lextra.h" #include "lextra.h"
#include "wifi_common.h" #include "wifi_common.h"
#include "task/task.h"
static int wifi_getmode (lua_State *L) static int wifi_getmode (lua_State *L)
{ {
@ -92,7 +93,21 @@ static int wifi_stop (lua_State *L)
0 : luaL_error (L, "failed to stop wifi, code %d", err); 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_ap_init (void);
extern void wifi_sta_init (void); extern void wifi_sta_init (void);
@ -101,10 +116,13 @@ static int wifi_init (lua_State *L)
wifi_ap_init (); wifi_ap_init ();
wifi_sta_init (); wifi_sta_init ();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); #if defined(CONFIG_ESP_CONSOLE_USB_CDC)
esp_err_t err = esp_wifi_init (&cfg); th = task_get_id(do_esp_wifi_init);
return (err == ESP_OK) ? task_post_low(th, 0);
0 : luaL_error (L, "failed to init wifi, code %d", err); #else
do_esp_wifi_init(0, 0);
#endif
return 0;
} }

View File

@ -72,6 +72,7 @@ menu "NodeMCU platform config"
default y if IDF_TARGET_ESP32S2 default y if IDF_TARGET_ESP32S2
default y if IDF_TARGET_ESP32S3 default y if IDF_TARGET_ESP32S3
default y if IDF_TARGET_ESP32C3 default y if IDF_TARGET_ESP32C3
default y if IDF_TARGET_ESP32C6
default y if IDF_TARGET_ESP32H2 default y if IDF_TARGET_ESP32H2
config NODEMCU_UART_AT_LEAST_3 config NODEMCU_UART_AT_LEAST_3

View File

@ -197,7 +197,7 @@ static int onewire_rmt_attach_pin( uint8_t gpio_num )
return PLATFORM_ERR; return PLATFORM_ERR;
if (gpio_num != ow_rmt.gpio) { if (gpio_num != ow_rmt.gpio) {
#if !defined(CONFIG_IDF_TARGET_ESP32C3) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
// attach GPIO to previous pin // attach GPIO to previous pin
if (gpio_num < 32) { if (gpio_num < 32) {
GPIO.enable_w1ts = (0x1 << gpio_num); GPIO.enable_w1ts = (0x1 << gpio_num);

View File

@ -284,6 +284,11 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari
void platform_uart_setmode(unsigned id, unsigned mode) void platform_uart_setmode(unsigned id, unsigned mode)
{ {
#if CONFIG_ESP_CONSOLE_UART_DEFAULT || CONFIG_ESP_CONSOLE_UART_CUSTOM
if (id == CONFIG_ESP_CONSOLE_UART_NUM)
return;
#endif
uart_mode_t uartMode; uart_mode_t uartMode;
switch(mode) switch(mode)
@ -334,6 +339,11 @@ void platform_uart_flush( unsigned id )
int platform_uart_start( unsigned id ) int platform_uart_start( unsigned id )
{ {
#if CONFIG_ESP_CONSOLE_UART_DEFAULT || CONFIG_ESP_CONSOLE_UART_CUSTOM
if (id == CONFIG_ESP_CONSOLE_UART_NUM)
return -1;
#endif
if(uart_event_task_id == 0) if(uart_event_task_id == 0)
uart_event_task_id = task_get_id( uart_event_task ); uart_event_task_id = task_get_id( uart_event_task );
@ -365,16 +375,16 @@ int platform_uart_start( unsigned id )
void platform_uart_stop( unsigned id ) void platform_uart_stop( unsigned id )
{ {
#if CONFIG_ESP_CONSOLE_UART_DEFAULT || CONFIG_ESP_CONSOLE_UART_CUSTOM
if (id == CONFIG_ESP_CONSOLE_UART_NUM) if (id == CONFIG_ESP_CONSOLE_UART_NUM)
; return;
else { #endif
uart_status_t *us = & uart_status[id]; uart_status_t *us = & uart_status[id];
uart_driver_delete(id); uart_driver_delete(id);
if(us->line_buffer) free(us->line_buffer); if(us->line_buffer) free(us->line_buffer);
us->line_buffer = NULL; us->line_buffer = NULL;
if(us->taskHandle) vTaskDelete(us->taskHandle); if(us->taskHandle) vTaskDelete(us->taskHandle);
us->taskHandle = NULL; us->taskHandle = NULL;
}
} }
int platform_uart_get_config(unsigned id, uint32_t *baudp, uint32_t *databitsp, uint32_t *parityp, uint32_t *stopbitsp) { int platform_uart_get_config(unsigned id, uint32_t *baudp, uint32_t *databitsp, uint32_t *parityp, uint32_t *stopbitsp) {

View File

@ -23,6 +23,11 @@ typedef intptr_t task_param_t;
*/ */
bool task_post(task_prio_t priority, task_handle_t handle, task_param_t param); bool task_post(task_prio_t priority, task_handle_t handle, task_param_t param);
/* Regular task posting is non-blocking, best effort. This version can be used
* where blocking-until-slot-is-available functionality is needed.
*/
bool task_post_block(task_prio_t priority, task_handle_t handle, task_param_t param);
/* When posting NodeMCU tasks from an ISR, this version MUST be used, /* When posting NodeMCU tasks from an ISR, this version MUST be used,
* and vice versa. * and vice versa.
* Doing otherwise breaks assumptions made by the FreeRTOS kernel in terms of * Doing otherwise breaks assumptions made by the FreeRTOS kernel in terms of
@ -44,6 +49,10 @@ bool task_post_isr(task_prio_t priority, task_handle_t handle, task_param_t para
#define task_post_isr_medium(handle,param) task_post_isr(TASK_PRIORITY_MEDIUM, handle, param) #define task_post_isr_medium(handle,param) task_post_isr(TASK_PRIORITY_MEDIUM, handle, param)
#define task_post_isr_high(handle,param) task_post_isr(TASK_PRIORITY_HIGH, handle, param) #define task_post_isr_high(handle,param) task_post_isr(TASK_PRIORITY_HIGH, handle, param)
#define task_post_block_low(handle,param) task_post_block(TASK_PRIORITY_LOW, handle, param)
#define task_post_block_medium(handle,param) task_post_block(TASK_PRIORITY_MEDIUM, handle, param)
#define task_post_block_high(handle,param) task_post_block(TASK_PRIORITY_HIGH, handle, param)
typedef void (*task_callback_t)(task_param_t param, task_prio_t prio); typedef void (*task_callback_t)(task_param_t param, task_prio_t prio);
task_handle_t task_get_id(task_callback_t t); task_handle_t task_get_id(task_callback_t t);

View File

@ -55,14 +55,14 @@ task_handle_t task_get_id(task_callback_t t) {
} }
bool IRAM_ATTR task_post(task_prio_t priority, task_handle_t handle, task_param_t param) static bool IRAM_ATTR task_post_wait(task_prio_t priority, task_handle_t handle, task_param_t param, unsigned max_wait)
{ {
if (priority >= TASK_PRIORITY_COUNT || if (priority >= TASK_PRIORITY_COUNT ||
(handle & TASK_HANDLE_MASK) != TASK_HANDLE_MONIKER) (handle & TASK_HANDLE_MASK) != TASK_HANDLE_MONIKER)
return false; return false;
task_event_t ev = { handle, param }; task_event_t ev = { handle, param };
bool res = (pdPASS == xQueueSendToBack(task_Q[priority], &ev, 0)); bool res = (pdPASS == xQueueSendToBack(task_Q[priority], &ev, max_wait));
xSemaphoreGive(pending); xSemaphoreGive(pending);
@ -70,6 +70,18 @@ bool IRAM_ATTR task_post(task_prio_t priority, task_handle_t handle, task_param_
} }
bool IRAM_ATTR task_post(task_prio_t priority, task_handle_t handle, task_param_t param)
{
return task_post_wait(priority, handle, param, 0);
}
bool IRAM_ATTR task_post_block(task_prio_t priority, task_handle_t handle, task_param_t param)
{
return task_post_wait(priority, handle, param, portMAX_DELAY);
}
bool IRAM_ATTR task_post_isr(task_prio_t priority, task_handle_t handle, task_param_t param) bool IRAM_ATTR task_post_isr(task_prio_t priority, task_handle_t handle, task_param_t param)
{ {
if (priority >= TASK_PRIORITY_COUNT || if (priority >= TASK_PRIORITY_COUNT ||

View File

@ -18,7 +18,7 @@
#define uz_malloc malloc #define uz_malloc malloc
#define uz_free free #define uz_free free
#if defined(__XTENSA__) || defined(CONFIG_IDF_TARGET_ESP32C3) #if defined(CONFIG_IDF_TARGET)
#define UZLIB_THROW(v) longjmp(unwindAddr, (v)) #define UZLIB_THROW(v) longjmp(unwindAddr, (v))
#define UZLIB_SETJMP setjmp #define UZLIB_SETJMP setjmp

View File

@ -251,7 +251,7 @@ void resizeBuffer(void) {
/* The outbuf is given an initial size estimate but if we are running */ /* The outbuf is given an initial size estimate but if we are running */
/* out of space then extropolate size using current compression */ /* out of space then extropolate size using current compression */
double newEstimate = (((double) oBuf->len)*oBuf->inLen) / oBuf->inNdx; double newEstimate = (((double) oBuf->len)*oBuf->inLen) / oBuf->inNdx;
oBuf->size = 128 + (uint) newEstimate; oBuf->size = 128 + (uint32_t) newEstimate;
if (!(nb = realloc(oBuf->buffer, oBuf->size))) if (!(nb = realloc(oBuf->buffer, oBuf->size)))
UZLIB_THROW(UZLIB_MEMORY_ERROR); UZLIB_THROW(UZLIB_MEMORY_ERROR);
oBuf->buffer = nb; oBuf->buffer = nb;

@ -1 +1 @@
Subproject commit 482a8fb2d78e3b58eb21b26da8a5bedf90623213 Subproject commit e7771c75bd1dbbfb7b3c5381be7e063b197c9734