diff --git a/components/base_nodemcu/user_main.c b/components/base_nodemcu/user_main.c index 01a2dde2..c72cc654 100644 --- a/components/base_nodemcu/user_main.c +++ b/components/base_nodemcu/user_main.c @@ -148,11 +148,29 @@ static void nodemcu_init(void) } +static bool have_console_on_data_cb(void) +{ +#if CONFIG_ESP_CONSOLE_UART_DEFAULT || CONFIG_ESP_CONSOLE_UART_CUSTOM + return uart_has_on_data_cb(CONFIG_ESP_CONSOLE_UART_NUM); +#else + return false; +#endif +} + + static void console_nodemcu_task(task_param_t param, task_prio_t prio) { (void)prio; char c = (char)param; - feed_lua_input(&c, 1); + + if (run_input) + feed_lua_input(&c, 1); + +#if CONFIG_ESP_CONSOLE_UART_DEFAULT || CONFIG_ESP_CONSOLE_UART_CUSTOM + if (have_console_on_data_cb()) + uart_feed_data(CONFIG_ESP_CONSOLE_UART_NUM, &c, 1); +#endif + // The IDF doesn't seem to honor setvbuf(stdout, NULL, _IONBF, 0) :( fsync(fileno(stdout)); } @@ -168,7 +186,7 @@ static void console_task(void *) */ char c; ssize_t n = read(fileno(stdin), &c, 1); - if (n > 0 && run_input) + if (n > 0 && (run_input || have_console_on_data_cb())) { if (!task_post_block_high(lua_feed_task, (task_param_t)c)) { diff --git a/components/modules/uart.c b/components/modules/uart.c index 107e2884..6a738f0a 100644 --- a/components/modules/uart.c +++ b/components/modules/uart.c @@ -4,48 +4,93 @@ #include "lauxlib.h" #include "platform.h" #include "linput.h" +#include "lmem.h" #include #include +typedef struct { + int receive_rf; + int error_rf; + char *line_buffer; + size_t line_position; + uint16_t need_len; + int16_t end_char; +} uart_cb_cfg_t; + static lua_State *gL = NULL; +static uart_cb_cfg_t uart_cb_cfg[NUM_UART]; -bool uart_has_on_data_cb(unsigned id){ - return uart_status[id].receive_rf != LUA_NOREF; -} -bool uart_on_data_cb(unsigned id, const char *buf, size_t len){ +static bool uart_on_data_cb(unsigned id, const char *buf, size_t len){ if(!buf || len==0) return false; - if(uart_status[id].receive_rf == LUA_NOREF) + if(uart_cb_cfg[id].receive_rf == LUA_NOREF) return false; if(!gL) return false; int top = lua_gettop(gL); - lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_status[id].receive_rf); + lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_cb_cfg[id].receive_rf); lua_pushlstring(gL, buf, len); luaL_pcallx(gL, 1, 0); lua_settop(gL, top); return !run_input; } + bool uart_on_error_cb(unsigned id, const char *buf, size_t len){ if(!buf || len==0) return false; - if(uart_status[id].error_rf == LUA_NOREF) + if(uart_cb_cfg[id].error_rf == LUA_NOREF) return false; if(!gL) return false; int top = lua_gettop(gL); - lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_status[id].error_rf); + lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_cb_cfg[id].error_rf); lua_pushlstring(gL, buf, len); luaL_pcallx(gL, 1, 0); lua_settop(gL, top); return true; } + +bool uart_has_on_data_cb(unsigned id){ + return uart_cb_cfg[id].receive_rf != LUA_NOREF; +} + + +void uart_feed_data(unsigned id, const char *buf, size_t len) +{ + if (id >= NUM_UART) + return; + + uart_cb_cfg_t *cfg = &uart_cb_cfg[id]; + if (!cfg->line_buffer) + return; + + for (unsigned i = 0; i < len; ++i) + { + char ch = buf[i]; + cfg->line_buffer[cfg->line_position] = ch; + cfg->line_position++; + + uint16_t need_len = cfg->need_len; + int16_t end_char = cfg->end_char; + size_t max_wanted = + (end_char >= 0 && need_len == 0) ? LUA_MAXINPUT : need_len; + bool at_end = (cfg->line_position >= max_wanted); + bool end_char_found = + (end_char >= 0 && (uint8_t)ch == (uint8_t)end_char); + if (at_end || end_char_found) { + uart_on_data_cb(id, cfg->line_buffer, cfg->line_position); + cfg->line_position = 0; + } + } +} + + // Lua: uart.on([id], "method", [number/char], function, [run_input]) static int uart_on( lua_State* L ) { @@ -54,14 +99,15 @@ static int uart_on( lua_State* L ) int32_t run = 1; uint8_t stack = 1; const char *method; - uart_status_t *us; if( lua_isnumber( L, stack ) ) { id = ( unsigned )luaL_checkinteger( L, stack ); MOD_CHECK_ID( uart, id ); stack++; } - us = & uart_status[id]; + + uart_cb_cfg_t *cfg = &uart_cb_cfg[id]; + method = luaL_checklstring( L, stack, &sl ); stack++; if (method == NULL) @@ -69,11 +115,12 @@ static int uart_on( lua_State* L ) if( lua_type( L, stack ) == LUA_TNUMBER ) { - us->need_len = ( uint16_t )luaL_checkinteger( L, stack ); + cfg->need_len = (uint16_t)luaL_checkinteger(L, stack); stack++; - us->end_char = -1; - if( us->need_len > 255 ){ - us->need_len = 255; + cfg->end_char = -1; + if(cfg->need_len > 255) + { + cfg->need_len = 255; return luaL_error( L, "wrong arg range" ); } } @@ -84,8 +131,8 @@ static int uart_on( lua_State* L ) if(el!=1){ return luaL_error( L, "wrong arg range" ); } - us->end_char = (int16_t)end[0]; - us->need_len = 0; + cfg->end_char = (int16_t)end[0]; + cfg->need_len = 0; } if (lua_isfunction(L, stack)) { @@ -99,12 +146,12 @@ static int uart_on( lua_State* L ) if(sl == 4 && strcmp(method, "data") == 0){ if(id == CONFIG_ESP_CONSOLE_UART_NUM) run_input = true; - if(us->receive_rf != LUA_NOREF){ - luaL_unref(L, LUA_REGISTRYINDEX, us->receive_rf); - us->receive_rf = LUA_NOREF; + if(cfg->receive_rf != LUA_NOREF){ + luaL_unref(L, LUA_REGISTRYINDEX, cfg->receive_rf); + cfg->receive_rf = LUA_NOREF; } if(!lua_isnil(L, -1)){ - us->receive_rf = luaL_ref(L, LUA_REGISTRYINDEX); + cfg->receive_rf = luaL_ref(L, LUA_REGISTRYINDEX); gL = L; if(id == CONFIG_ESP_CONSOLE_UART_NUM && run==0) run_input = false; @@ -112,12 +159,12 @@ static int uart_on( lua_State* L ) lua_pop(L, 1); } } else if(sl == 5 && strcmp(method, "error") == 0){ - if(us->error_rf != LUA_NOREF){ - luaL_unref(L, LUA_REGISTRYINDEX, us->error_rf); - us->error_rf = LUA_NOREF; + if(cfg->error_rf != LUA_NOREF){ + luaL_unref(L, LUA_REGISTRYINDEX, cfg->error_rf); + cfg->error_rf = LUA_NOREF; } if(!lua_isnil(L, -1)){ - us->error_rf = luaL_ref(L, LUA_REGISTRYINDEX); + cfg->error_rf = luaL_ref(L, LUA_REGISTRYINDEX); gL = L; } else { lua_pop(L, 1); @@ -183,7 +230,7 @@ static int uart_setup( lua_State* L ) static int uart_setmode(lua_State* L) { unsigned id, mode; - + id = luaL_checkinteger( L, 1 ); MOD_CHECK_ID( uart, id ); mode = luaL_checkinteger( L, 2 ); @@ -230,6 +277,11 @@ static int uart_stop( lua_State* L ) id = luaL_checkinteger( L, 1 ); MOD_CHECK_ID( uart, id ); platform_uart_stop( id ); + if (uart_cb_cfg[id].line_buffer) + { + luaM_freemem(L, uart_cb_cfg[id].line_buffer, LUA_MAXINPUT); + uart_cb_cfg[id].line_buffer = NULL; + } return 0; } @@ -240,6 +292,8 @@ static int uart_start( lua_State* L ) int err; id = luaL_checkinteger( L, 1 ); MOD_CHECK_ID( uart, id ); + if (!uart_cb_cfg[id].line_buffer) + uart_cb_cfg[id].line_buffer = luaM_malloc(L, LUA_MAXINPUT); err = platform_uart_start( id ); lua_pushboolean( L, err == 0 ); return 1; @@ -303,21 +357,23 @@ LROT_BEGIN(uart, NULL, 0) LROT_NUMENTRY( FLOWCTRL_NONE, PLATFORM_UART_FLOW_NONE ) LROT_NUMENTRY( FLOWCTRL_CTS, PLATFORM_UART_FLOW_CTS ) LROT_NUMENTRY( FLOWCTRL_RTS, PLATFORM_UART_FLOW_RTS ) - LROT_NUMENTRY( MODE_UART, PLATFORM_UART_MODE_UART ) + LROT_NUMENTRY( MODE_UART, PLATFORM_UART_MODE_UART ) LROT_NUMENTRY( MODE_RS485_COLLISION_DETECT, PLATFORM_UART_MODE_RS485_COLLISION_DETECT ) LROT_NUMENTRY( MODE_RS485_APP_CONTROL, PLATFORM_UART_MODE_RS485_APP_CONTROL ) LROT_NUMENTRY( MODE_RS485_HALF_DUPLEX, PLATFORM_UART_MODE_HALF_DUPLEX ) - LROT_NUMENTRY( MODE_IRDA, PLATFORM_UART_MODE_IRDA ) + LROT_NUMENTRY( MODE_IRDA, PLATFORM_UART_MODE_IRDA ) LROT_END(uart, NULL, 0) int luaopen_uart( lua_State *L ) { - uart_status_t *us; - for(int id = 0; id < NUM_UART; id++) { - us = & uart_status[id]; - us->receive_rf = LUA_NOREF; - us->error_rf = LUA_NOREF; - us->need_len = 0; - us->end_char = -1; + for(int id = 0; id < sizeof(uart_cb_cfg)/sizeof(uart_cb_cfg[0]); id++) + { + uart_cb_cfg_t *cfg = &uart_cb_cfg[id]; + cfg->receive_rf = LUA_NOREF; + cfg->error_rf = LUA_NOREF; + cfg->line_buffer = NULL; + cfg->line_position = 0; + cfg->need_len = 0; + cfg->end_char = -1; } return 0; } diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index 2706a9de..42ec933a 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -91,15 +91,12 @@ typedef struct { typedef struct { QueueHandle_t queue; TaskHandle_t taskHandle; - int receive_rf; - int error_rf; - char *line_buffer; - size_t line_position; - uint16_t need_len; - int16_t end_char; } uart_status_t; -extern uart_status_t uart_status[NUM_UART]; +// We have a bit of legacy spaghetti - these point into modules/uart.c +extern bool uart_has_on_data_cb(unsigned id); +extern void uart_feed_data(unsigned id, const char *buf, size_t len); +extern bool uart_on_error_cb(unsigned id, const char *buf, size_t len); // Flow control types (this is a bit mask, one can specify PLATFORM_UART_FLOW_RTS | PLATFORM_UART_FLOW_CTS ) #define PLATFORM_UART_FLOW_NONE 0 diff --git a/components/platform/platform.c b/components/platform/platform.c index 2d8141bd..86606df8 100644 --- a/components/platform/platform.c +++ b/components/platform/platform.c @@ -83,14 +83,9 @@ uart_status_t uart_status[NUM_UART]; task_handle_t uart_event_task_id = 0; SemaphoreHandle_t sem = NULL; -extern bool uart_has_on_data_cb(unsigned id); -extern bool uart_on_data_cb(unsigned id, const char *buf, size_t len); -extern bool uart_on_error_cb(unsigned id, const char *buf, size_t len); - void uart_event_task( task_param_t param, task_prio_t prio ) { uart_event_post_t *post = (uart_event_post_t *)param; unsigned id = post->id; - uart_status_t *us = &uart_status[id]; xSemaphoreGive(sem); if(post->type == PLATFORM_UART_EVENT_DATA) { if (id == CONFIG_ESP_CONSOLE_UART_NUM && run_input) { @@ -101,28 +96,9 @@ void uart_event_task( task_param_t param, task_prio_t prio ) { i += used; } } - if (uart_has_on_data_cb(id)) { - size_t i = 0; - while (i < post->size) - { - char ch = post->data[i]; - us->line_buffer[us->line_position] = ch; - us->line_position++; + if (uart_has_on_data_cb(id)) + uart_feed_data(id, post->data, post->size); - uint16_t need_len = us->need_len; - int16_t end_char = us->end_char; - size_t max_wanted = - (end_char >= 0 && need_len == 0) ? LUA_MAXINPUT : need_len; - bool at_end = (us->line_position >= max_wanted); - bool end_char_found = - (end_char >= 0 && (uint8_t)ch == (uint8_t)end_char); - if (at_end || end_char_found) { - uart_on_data_cb(id, us->line_buffer, us->line_position); - us->line_position = 0; - } - ++i; - } - } free(post->data); } else { const char *err; @@ -353,20 +329,12 @@ int platform_uart_start( unsigned id ) if(ret != ESP_OK) { return -1; } - us->line_buffer = malloc(LUA_MAXINPUT); - us->line_position = 0; - if(us->line_buffer == NULL) { - uart_driver_delete(id); - return -1; - } char pcName[6]; snprintf( pcName, 6, "uart%d", id ); pcName[5] = '\0'; if(xTaskCreate(task_uart, pcName, 2048, (void*)id, ESP_TASK_MAIN_PRIO + 1, & us->taskHandle) != pdPASS) { uart_driver_delete(id); - free(us->line_buffer); - us->line_buffer = NULL; return -1; } @@ -381,8 +349,6 @@ void platform_uart_stop( unsigned id ) #endif uart_status_t *us = & uart_status[id]; uart_driver_delete(id); - if(us->line_buffer) free(us->line_buffer); - us->line_buffer = NULL; if(us->taskHandle) vTaskDelete(us->taskHandle); us->taskHandle = NULL; }