From 1f2e5bba4ab38c499d41c57a1e74e5c405fd3868 Mon Sep 17 00:00:00 2001 From: Terry Ellison Date: Tue, 16 Jun 2020 08:19:55 +0100 Subject: [PATCH] Implement panic call handling for all modules (#3163) --- .gdbinitlua | 31 ++- app/lua/lauxlib.c | 34 ++- app/lua/lauxlib.h | 3 +- app/lua/ldebug.c | 6 +- app/lua/lflash.c | 8 +- app/lua/lnodemcu.c | 40 +-- app/lua/lnodemcu.h | 19 +- app/lua/lobject.h | 2 +- app/lua/lua.h | 16 +- app/lua53/lauxlib.c | 67 +++-- app/lua53/lauxlib.h | 2 + app/lua53/llimits.h | 1 - app/lua53/lnodemcu.c | 10 +- app/lua53/lnodemcu.h | 55 +--- app/lua53/lua.c | 72 +++-- app/lua53/lua.h | 14 +- app/lua53/lundump.h | 42 +++ app/modules/ads1115.c | 2 +- app/modules/bme280.c | 2 +- app/modules/bme680.c | 2 +- app/modules/cron.c | 2 +- app/modules/crypto.c | 3 +- app/modules/dcc.c | 34 +-- app/modules/enduser_setup.c | 6 +- app/modules/file.c | 3 +- app/modules/gpio.c | 8 +- app/modules/gpio_pulse.c | 2 +- app/modules/http.c | 2 +- app/modules/hx711.c | 2 +- app/modules/node.c | 59 +++- app/modules/pcm.c | 2 +- app/modules/pipe.c | 2 +- app/modules/rotary.c | 2 +- app/modules/sntp.c | 4 +- app/modules/softuart.c | 2 +- app/modules/somfy.c | 2 +- app/modules/switec.c | 2 +- app/modules/tcs34725.c | 2 +- app/modules/tls.c | 17 +- app/modules/tmr.c | 290 +++++++------------- app/modules/websocket.c | 8 +- app/modules/wifi.c | 11 +- app/modules/wifi_eventmon.c | 2 +- app/modules/wifi_monitor.c | 2 +- app/modules/wps.c | 2 +- app/pcm/pcm_core.c | 10 +- app/platform/platform.c | 110 +++----- app/pm/pmSleep.c | 2 +- app/pm/swtimer.c | 174 ++++++------ app/spiffs/nodemcu_spiffs.h | 1 + app/spiffs/spiffs.c | 2 +- app/spiffs/spiffs_nucleus.c | 12 +- app/spiffs/spiffs_nucleus.h | 16 +- app/u8g2lib/u8x8_d_fbrle.c | 4 +- lua_modules/liquidcrystal/lc-gpio4bit.lua | 2 +- lua_modules/liquidcrystal/lc-gpio8bit.lua | 2 +- lua_modules/liquidcrystal/lc-i2c4bit.lua | 2 +- lua_modules/liquidcrystal/liquidcrystal.lua | 2 +- 58 files changed, 609 insertions(+), 629 deletions(-) diff --git a/.gdbinitlua b/.gdbinitlua index ef467354..c767d53d 100644 --- a/.gdbinitlua +++ b/.gdbinitlua @@ -50,32 +50,25 @@ define prTV printf "Boolean: %u\n", $val.n end if $type == 2 - # ROTable - printf "ROTable: %p\n", $val.p - end - if $type == 3 - # Light Function - printf "Light Func: %p\n", $val.p - end - if $type == 4 # Light User Data printf "Light Udata: %p\n", $val.p end - if $type == 5 + if $type == 3 # Number printf "Number: %u\n", $val.n end - if $type == 6 - prTS $arg0 + if $type == 4 + # String + printf "String: %s\n", (char *)($val.p)+16 end - if $type == 7 + if $type == 5 # Table set $o = &($val->gc.h) printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked printf "Nodes: %4i %p\n", 2<<($o->lsizenode), $o->node printf "Arry: %4i %p\n", $o->sizearray, $o->array end - if $type == 8 + if $type == 6 # Function set $o = &($val->gc.cl.c) printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked @@ -88,16 +81,24 @@ define prTV $o->nupvalues, $o->gclist, $o->env, $o->f end end - if $type == 9 + if $type == 7 # UserData set $o = &($val->gc.u.uv) printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked printf "UD = %p Userdata: metatable = ", ($o+1)) print ($o)->metatable end - if $type == 10 + if $type == 8 # Thread end + if $type == 21 + # ROTable + printf "ROTable: %p\n", $val.p + end + if $type == 38 + # Light Function + printf "Light Func: %p\n", $val.p + end end end diff --git a/app/lua/lauxlib.c b/app/lua/lauxlib.c index 14575166..c3caa5eb 100644 --- a/app/lua/lauxlib.c +++ b/app/lua/lauxlib.c @@ -684,6 +684,26 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { } +LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref) { + int reft; +/* + * If the ref is positive and the entry in table t exists then + * overwrite the value otherwise fall through to luaL_ref() + */ + if (ref) { + if (*ref >= 0) { + t = abs_index(L, t); + lua_rawgeti(L, t, *ref); + reft = lua_type(L, -1); + lua_pop(L, 1); + if (reft != LUA_TNIL) { + lua_rawseti(L, t, *ref); + return; + } + } + *ref = luaL_ref(L, t); + } +} /* ** {====================================================== @@ -899,23 +919,23 @@ LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) * is the option to exit the interactive session and start the Xtensa remote GDB * which will then sync up with the remote GDB client to allow forensics of the error. */ -#ifdef LUA_CROSS_COMPILER -LUALIB_API void lua_debugbreak(void) { - puts(" lua_debugbreak "); /* allows BT analysis of assert fails */ -} -#else extern void gdbstub_init(void); +extern void gdbstub_redirect_output(int); -LUALIB_API void lua_debugbreak(void) { +LUALIB_API void lua_debugbreak (void) { +#ifdef LUA_CROSS_COMPILER + puts(" lua_debugbreak "); /* allows gdb BT analysis of assert fails */ +#else static int repeat_entry = 0; if (repeat_entry == 0) { dbg_printf("Start up the gdb stub if not already started\n"); gdbstub_init(); + gdbstub_redirect_output(1); repeat_entry = 1; } asm("break 0,0" ::); -} #endif +} #endif diff --git a/app/lua/lauxlib.h b/app/lua/lauxlib.h index d837725e..2ebbf7b3 100644 --- a/app/lua/lauxlib.h +++ b/app/lua/lauxlib.h @@ -73,6 +73,8 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, LUALIB_API int (luaL_ref) (lua_State *L, int t); LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); +#define luaL_unref2(l,t,r) luaL_unref(L, (t), (r)); r = LUA_NOREF +LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref); LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); @@ -160,7 +162,6 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); /* }====================================================== */ -LUALIB_API int luaL_traceback (lua_State *L); LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres); LUALIB_API int luaL_posttask( lua_State* L, int prio ); diff --git a/app/lua/ldebug.c b/app/lua/ldebug.c index 449aa152..6de90c53 100644 --- a/app/lua/ldebug.c +++ b/app/lua/ldebug.c @@ -668,7 +668,7 @@ static int isinstack (CallInfo *ci, const TValue *o) { void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { const char *name = NULL; - const char *t = luaT_typenames[ttype(o)]; + const char *t = luaT_typenames[basettype(o)]; const char *kind = (isinstack(L->ci, o)) ? getobjname(L, L->ci, cast_int(o - L->base), &name) : NULL; @@ -696,8 +696,8 @@ void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = luaT_typenames[ttype(p1)]; - const char *t2 = luaT_typenames[ttype(p2)]; + const char *t1 = luaT_typenames[basettype(p1)]; + const char *t2 = luaT_typenames[basettype(p2)]; if (t1[2] == t2[2]) luaG_runerror(L, "attempt to compare two %s values", t1); else diff --git a/app/lua/lflash.c b/app/lua/lflash.c index 417801eb..df312c72 100644 --- a/app/lua/lflash.c +++ b/app/lua/lflash.c @@ -138,7 +138,7 @@ static void flashErase(uint32_t start, uint32_t end){ } /* ===================================================================================== - * luaN_init(), luaN_reload_reboot() and luaN_index() are exported via lflash.h. + * luaN_init() is exported via lflash.h. * The first is the startup hook used in lstate.c and the last two are * implementations of the node.flash API calls. */ @@ -194,10 +194,12 @@ static int loadLFS (lua_State *L); static int loadLFSgc (lua_State *L); static void procFirstPass (void); +/* lua_lfsreload() and lua_lfsindex() are exported via lua.h */ + /* * Library function called by node.flashreload(filename). */ -LUALIB_API int luaN_reload_reboot (lua_State *L) { +LUALIB_API int lua_lfsreload (lua_State *L) { const char *fn = lua_tostring(L, 1), *msg = ""; int status; @@ -266,7 +268,7 @@ LUALIB_API int luaN_reload_reboot (lua_State *L) { * - The base address and length of the LFS * - An array of the module names in the LFS */ -LUAI_FUNC int luaN_index (lua_State *L) { +LUAI_FUNC int lua_lfsindex (lua_State *L) { int n = lua_gettop(L); /* Return nil + the LFS base address if the LFS size > 0 and it isn't loaded */ diff --git a/app/lua/lnodemcu.c b/app/lua/lnodemcu.c index b8362420..5e1b3322 100644 --- a/app/lua/lnodemcu.c +++ b/app/lua/lnodemcu.c @@ -26,27 +26,31 @@ ** directly through the task interface the call is wrapped in a C closure with ** the error string as an Upval and this is posted to call the Lua reporter. */ -static int report_traceback (lua_State *L) { -// **Temp** lua_rawgeti(L, LUA_REGISTRYINDEX, G(L)->error_reporter); - lua_getglobal(L, "print"); +static int errhandler_aux (lua_State *L) { + lua_getfield(L, LUA_REGISTRYINDEX, "onerror"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 1); + lua_getglobal(L, "print"); + } lua_pushvalue(L, lua_upvalueindex(1)); lua_call(L, 1, 0); /* Using an error handler would cause an infinite loop! */ return 0; } /* -** Catch all error handler for CB calls. This uses debug.traceback() to -** generate a full Lua traceback. +** Error handler for luaL_pcallx(), called from the lua_pcall() with a single +** argument -- the thrown error. This plus depth=2 is passed to debug.traceback() +** to convert into an error message which it handles in a separate posted task. */ -LUALIB_API int luaL_traceback (lua_State *L) { - if (lua_isstring(L, 1)) { - lua_getglobal(L, "debug"); - lua_getfield(L, -1, "traceback"); - lua_remove(L, -2); - lua_pushvalue(L, 1); /* pass error message */ +static int errhandler (lua_State *L) { + lua_getglobal(L, "debug"); + lua_getfield(L, -1, "traceback"); + if (lua_isfunction(L, -1)) { + lua_insert(L, 1); /* insert tracback function above error */ + lua_pop(L, 1); /* dump the debug table entry */ lua_pushinteger(L, 2); /* skip this function and traceback */ lua_call(L, 2, 1); /* call debug.traceback and return it as a string */ - lua_pushcclosure(L, report_traceback, 1); /* report with str as upval */ + lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */ luaL_posttask(L, LUA_TASK_HIGH); } return 0; @@ -60,12 +64,16 @@ LUALIB_API int luaL_traceback (lua_State *L) { LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { // [-narg, +0, v] int status; int base = lua_gettop(L) - narg; - lua_pushcfunction(L, luaL_traceback); + lua_pushcfunction(L, errhandler); lua_insert(L, base); /* put under args */ - status = lua_pcall(L, narg, (nres < 0 ? LUA_MULTRET : nres), base); + status = lua_pcall(L, narg, nres, base); lua_remove(L, base); /* remove traceback function */ - if (status && nres >=0) - lua_settop(L, base + nres); /* balance the stack on error */ + if (status != LUA_OK && status != LUA_ERRRUN) { + lua_gc(L, LUA_GCCOLLECT, 0); /* call onerror directly if handler failed */ + lua_pushliteral(L, "out of memory"); + lua_pushcclosure(L, errhandler_aux, 1); /* report EOM as upval */ + luaL_posttask(L, LUA_TASK_HIGH); + } return status; } diff --git a/app/lua/lnodemcu.h b/app/lua/lnodemcu.h index 1fe9b30e..e5fedec6 100644 --- a/app/lua/lnodemcu.h +++ b/app/lua/lnodemcu.h @@ -1,5 +1,6 @@ -/* Read-only tables for Lua */ - +/* + * NodeMCU extensions to Lua 5.1 for readonly Flash memory support + */ #ifndef lnodemcu_h #define lnodemcu_h @@ -16,7 +17,8 @@ #define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s))) #endif -/* Macros one can use to define rotable entries */ +/* Macros used to declare rotable entries */ + #define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION} #define LRO_LUDATA(v) {{.p = cast(void*,v)}, LUA_TLIGHTUSERDATA} #define LRO_NILVAL {{.p = NULL}, LUA_TNIL} @@ -25,7 +27,7 @@ #define LRO_FLOATVAL(v) LRO_NUMVAL(v) #define LRO_ROVAL(v) {{.gc = cast(GCObject *, &(v ## _ROTable))}, LUA_TROTABLE} -#define LROT_MARKED 0 //<<<<<<<<<<*** TBD *** >>>>>>>>>>> +#define LROT_MARKED 0 //<<<<<<<<<< *** TBD *** >>>>>>>>>>> #define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)}, #define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA(x)}, @@ -38,9 +40,9 @@ #define LROT_ENTRYREF(rt) (rt ##_entries) #define LROT_TABLEREF(rt) (&rt ##_ROTable) #define LROT_BEGIN(rt,mt,f) LROT_TABLE(rt); \ - static const ROTable_entry rt ## _entries[] = { + static ROTable_entry rt ## _entries[] = { #define LROT_ENTRIES_IN_SECTION(rt,s) \ - static const ROTable_entry LOCK_IN_SECTION(s) rt ## _entries[] = { + static ROTable_entry LOCK_IN_SECTION(s) rt ## _entries[] = { #define LROT_END(rt,mt,f) {NULL, LRO_NILVAL} }; \ const ROTable rt ## _ROTable = { \ (GCObject *)1, LUA_TROTABLE, LROT_MARKED, \ @@ -64,4 +66,9 @@ #define LROT_MASK_GC_INDEX (LROT_MASK_GC | LROT_MASK_INDEX) /* Maximum length of a rotable name and of a string key*/ + +#ifdef LUA_CORE + #endif +#endif + diff --git a/app/lua/lobject.h b/app/lua/lobject.h index 0c1849c1..c98b60db 100644 --- a/app/lua/lobject.h +++ b/app/lua/lobject.h @@ -410,7 +410,7 @@ typedef struct Table { GET_BYTE_FN(flags,Table,4,16) GET_BYTE_FN(lsizenode,Table,4,24) -typedef struct ROTable_entry { +typedef const struct ROTable_entry { const char *key; const TValue value; } ROTable_entry; diff --git a/app/lua/lua.h b/app/lua/lua.h index 8fce4196..60bc7da4 100644 --- a/app/lua/lua.h +++ b/app/lua/lua.h @@ -383,10 +383,13 @@ struct lua_Debug { /* }====================================================================== */ typedef struct ROTable ROTable; -typedef struct ROTable_entry ROTable_entry; +typedef const struct ROTable_entry ROTable_entry; -LUA_API void (lua_pushrotable) (lua_State *L, const ROTable *p); -LUA_API void (lua_createrotable) (lua_State *L, ROTable *t, const ROTable_entry *e, ROTable *mt); +LUA_API void (lua_pushrotable) (lua_State *L, const ROTable *p); +LUA_API void (lua_createrotable) (lua_State *L, ROTable *t, ROTable_entry *e, ROTable *mt); + +LUAI_FUNC int lua_lfsreload (lua_State *L); +LUAI_FUNC int lua_lfsindex (lua_State *L); #define EGC_NOT_ACTIVE 0 // EGC disabled #define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure @@ -413,7 +416,12 @@ LUA_API void lua_setegcmode(lua_State *L, int mode, int limit); #define dbg_printf printf #endif -extern void lua_debugbreak(void); + +#ifdef DEVELOPMENT_USE_GDB +LUALIB_API void (lua_debugbreak)(void); +#else +#define lua_debugbreak() (void)(0) +#endif // EGC operations modes #define EGC_NOT_ACTIVE 0 // EGC disabled diff --git a/app/lua53/lauxlib.c b/app/lua53/lauxlib.c index 62b83f70..5cbf813f 100644 --- a/app/lua53/lauxlib.c +++ b/app/lua53/lauxlib.c @@ -649,6 +649,28 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { } } + +LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref) { + int reft; +/* + * If the ref is positive and the entry in table t exists then + * overwrite the value otherwise fall through to luaL_ref() + */ + if (ref) { + if (*ref >= 0) { + t = lua_absindex(L, t); + lua_rawgeti(L, t, *ref); + reft = lua_type(L, -1); + lua_pop(L, 1); + if (reft != LUA_TNIL) { + lua_rawseti(L, t, *ref); + return; + } + } + *ref = luaL_ref(L, t); + } +} + /* }====================================================== */ @@ -1127,26 +1149,23 @@ static int errhandler_aux (lua_State *L) { return 0; } - /* -** Error handler for luaL_pcallx() +** Error handler for luaL_pcallx(), called from the lua_pcall() with a single +** argument -- the thrown error. This plus depth=2 is passed to debug.traceback() +** to convert into an error message which it handles in a separate posted task. */ static int errhandler (lua_State *L) { - if (lua_isnil(L, -1)) - return 0; - if (lua_type(L, -1) != LUA_TSTRING) { /* is error object not a string? */ - if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ - lua_type(L, -1) == LUA_TSTRING) { /* that produces a string? */ - lua_remove(L, 1); /* replace ToS with this */ - } else if (!lua_isnil(L,-1)) { - lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1)); - lua_remove(L, 1); /* replace ToS with error object is type value */ - } + lua_getglobal(L, "debug"); + lua_getfield(L, -1, "traceback"); + if (lua_isfunction(L, -1)) { + lua_insert(L, 1); /* insert tracback function above error */ + lua_pop(L, 1); /* dump the debug table entry */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback and return it as a string */ + lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */ + luaL_posttask(L, LUA_TASK_HIGH); } - luaL_traceback(L, L, lua_tostring(L, 1), 1); /* append a standard traceback */ - lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */ - luaL_posttask(L, LUA_TASK_HIGH); - return 1; /* return the traceback */ + return 0; } /* @@ -1155,11 +1174,17 @@ static int errhandler (lua_State *L) { */ LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { int status; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, errhandler); /* push message handler */ - lua_insert(L, base); /* put it under function and args */ + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, errhandler); /* push message handler */ + lua_insert(L, base); /* put it under function and args */ status = lua_pcall(L, narg, nres, base); - lua_remove(L, base); /* remove message handler from the stack */ + lua_remove(L, base); /* remove message handler from the stack */ + if (status != LUA_OK && status != LUA_ERRRUN) { + lua_gc(L, LUA_GCCOLLECT, 0); /* call onerror directly if handler failed */ + lua_pushliteral(L, "out of memory"); + lua_pushcclosure(L, errhandler_aux, 1); /* report EOM as upval */ + luaL_posttask(L, LUA_TASK_HIGH); + } return status; } @@ -1180,7 +1205,7 @@ static void do_task (platform_task_param_t task_fn_ref, uint8_t prio) { luaL_checktype(L, -1, LUA_TFUNCTION); luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref); lua_pushinteger(L, prio); - luaL_pcallx (L, 1, 0); + luaL_pcallx(L, 1, 0); } /* diff --git a/app/lua53/lauxlib.h b/app/lua53/lauxlib.h index 8fcbc602..3e36785f 100644 --- a/app/lua53/lauxlib.h +++ b/app/lua53/lauxlib.h @@ -79,6 +79,8 @@ LUALIB_API int (luaL_execresult) (lua_State *L, int stat); LUALIB_API int (luaL_ref) (lua_State *L, int t); LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); +#define luaL_unref2(l,t,r) luaL_unref(L, (t), (r)); r = LUA_NOREF +LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref); LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); diff --git a/app/lua53/llimits.h b/app/lua53/llimits.h index 65264b6d..f9855b1c 100644 --- a/app/lua53/llimits.h +++ b/app/lua53/llimits.h @@ -83,7 +83,6 @@ typedef LUAI_UACNUMBER l_uacNumber; typedef LUAI_UACINT l_uacInt; #if defined(DEVELOPMENT_USE_GDB) && !defined(lua_assert) -extern void (lua_debugbreak)(void); # define lua_assert(c) ((c) ? (void) 0 : lua_debugbreak()) #endif diff --git a/app/lua53/lnodemcu.c b/app/lua53/lnodemcu.c index f275e728..ae989282 100644 --- a/app/lua53/lnodemcu.c +++ b/app/lua53/lnodemcu.c @@ -202,8 +202,6 @@ LUALIB_API void lua_debugbreak(void) { asm("break 0,0" ::); #endif } -#else -#define lua_debugbreak() (void)(0) #endif //== NodeMCU lua.h API extensions ============================================// @@ -567,7 +565,7 @@ LUAI_FUNC int luaN_init (lua_State *L) { #define getfield(L,t,f) \ lua_getglobal(L, #t); luaL_getmetafield( L, 1, #f ); lua_remove(L, -2); -LUAI_FUNC int luaN_reload_reboot (lua_State *L) { +LUAI_FUNC int lua_lfsreload (lua_State *L) { int n = 0; #ifdef LUA_USE_ESP size_t l; @@ -579,6 +577,10 @@ LUAI_FUNC int luaN_reload_reboot (lua_State *L) { #endif lua_settop(L, 1); lua_getglobal(L, "file"); + if (lua_isnil(L, 2)) { + lua_pushstring(L, "No file system mounted"); + return 1; + } lua_getfield(L, 2, "exists"); lua_pushstring(L, img + off); lua_call(L, 1, 1); @@ -594,7 +596,7 @@ LUAI_FUNC int luaN_reload_reboot (lua_State *L) { return 1; } -LUAI_FUNC int luaN_index (lua_State *L) { +LUAI_FUNC int lua_lfsindex (lua_State *L) { lua_settop(L,1); if (lua_isstring(L, 1)){ lua_getglobal(L, "LFS"); diff --git a/app/lua53/lnodemcu.h b/app/lua53/lnodemcu.h index 0dcd76f5..ed508318 100644 --- a/app/lua53/lnodemcu.h +++ b/app/lua53/lnodemcu.h @@ -1,5 +1,5 @@ /* - * NodeMCU extensions to Lua for readonly Flash memory support + * NodeMCU extensions to Lua 5.3 for readonly Flash memory support */ #ifndef lnodemcu_h #define lnodemcu_h @@ -27,7 +27,7 @@ #define LRO_FLOATVAL(v) {{.n = v}, LUA_TNUMFLT} #define LRO_ROVAL(v) {{.gc = cast(GCObject *, &(v ## _ROTable))}, LUA_TTBLROF} -#define LROT_MARKED 0 //<<<<<<<<<<*** TBD *** >>>>>>>>>>> +#define LROT_MARKED 0 //<<<<<<<<<< *** TBD *** >>>>>>>>>>> #define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)}, #define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA(x)}, @@ -65,65 +65,18 @@ #define LROT_MASK_NEWINDEX LROT_MASK(NEWINDEX) #define LROT_MASK_GC_INDEX (LROT_MASK_GC | LROT_MASK_INDEX) -/* Maximum length of a rotable name and of a string key*/ -#define LUA_MAX_ROTABLE_NAME 32 + +#define LUA_MAX_ROTABLE_NAME 32 /* Maximum length of a rotable name and of a string key*/ #ifdef LUA_CORE #include "lstate.h" #include "lzio.h" -typedef struct FlashHeader LFSHeader; -/* -** The LFSHeader uses offsets rather than pointers to avoid 32 vs 64 bit issues -** during host compilation. The offsets are in units of lu_int32's and NOT -** size_t, though clearly any internal pointers are of the size_t for the -** executing architectures: 4 or 8 byte. Likewise recources are size_t aligned -** so LFS regions built for 64-bit execution will have 4-byte alignment packing -** between resources. -*/ -struct FlashHeader{ - lu_int32 flash_sig; /* a standard fingerprint identifying an LFS image */ - lu_int32 flash_size; /* Size of LFS image in bytes */ - lu_int32 seed; /* random number seed used in LFS */ - lu_int32 timestamp; /* timestamp of LFS build */ - lu_int32 nROuse; /* number of elements in ROstrt */ - lu_int32 nROsize; /* size of ROstrt */ - lu_int32 oROhash; /* offset of TString ** ROstrt hash */ - lu_int32 protoROTable; /* offset of master ROTable for proto lookup */ - lu_int32 protoHead; /* offset of linked list of Protos in LFS */ - lu_int32 shortTShead; /* offset of linked list of short TStrings in LFS */ - lu_int32 longTShead; /* offset of linked list of long TStrings in LFS */ - lu_int32 reserved; -}; - -#ifdef LUA_USE_HOST -extern void *LFSregion; -LUAI_FUNC void luaN_setabsolute(lu_int32 addr); -#endif - -#define FLASH_FORMAT_VERSION ( 2 << 8) -#define FLASH_SIG_B1 0x06 -#define FLASH_SIG_B2 0x02 -#define FLASH_SIG_PASS2 0x0F -#define FLASH_FORMAT_MASK 0xF00 -#define FLASH_SIG_B2_MASK 0x04 -#define FLASH_SIG_ABSOLUTE 0x01 -#define FLASH_SIG_IN_PROGRESS 0x08 -#define FLASH_SIG (0xfafaa050 | FLASH_FORMAT_VERSION) - -#define FLASH_FORMAT_MASK 0xF00 - LUAI_FUNC int luaN_init (lua_State *L); -LUAI_FUNC int luaN_flashSetup (lua_State *L); - -LUAI_FUNC int luaN_reload_reboot (lua_State *L); -LUAI_FUNC int luaN_index (lua_State *L); - LUAI_FUNC void *luaN_writeFlash (void *data, const void *rec, size_t n); LUAI_FUNC void luaN_flushFlash (void *); LUAI_FUNC void luaN_setFlash (void *, unsigned int o); - #endif #endif diff --git a/app/lua53/lua.c b/app/lua53/lua.c index 9fb08680..d99f2300 100644 --- a/app/lua53/lua.c +++ b/app/lua53/lua.c @@ -64,9 +64,10 @@ static void l_print (lua_State *L, int n) { luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); lua_getglobal(L, "print"); lua_insert(L, -n-1); - if (lua_pcall(L, n, 0, 0) != LUA_OK) - lua_writestringerror( "error calling 'print' (%s)\n", - lua_tostring(L, -1)); + if (lua_pcall(L, n, 0, 0) != LUA_OK) { + lua_writestringerror("error calling 'print' (%s)\n", lua_tostring(L, -1)); + lua_settop(L, -n-1); + } } } @@ -75,52 +76,43 @@ static void l_print (lua_State *L, int n) { ** Message handler is used with all chunks calls. Returns the traceback on ToS */ static int msghandler (lua_State *L) { - const char *msg = lua_tostring(L, 1); - if (msg == NULL) { /* is error object not a string? */ - if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ - lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ - return 1; /* that is the message */ - msg = lua_pushfstring(L, "(error object is a %s value)", - luaL_typename(L, 1)); - lua_remove(L, -2); /* otherwise swap with printable error */ + lua_getglobal(L, "debug"); + lua_getfield(L, -1, "traceback"); + if (lua_isfunction(L, -1)) { + lua_insert(L, 1); /* insert tracback function above error */ + lua_pop(L, 1); /* dump the debug table entry */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback and return it as a string */ } -#ifdef LUA_VERSION_51 - lua_getglobal(L,"debug"); - lua_getfield(L, -1,"traceback"); - lua_insert(L, 1); /* pass error message */ - lua_pop(L, 1); - lua_pushinteger(L, 2); /* skip this function and traceback */ - lua_call(L, 2, 1); /* call debug.traceback */ -#else /* LUA_VERSION_53 */ - luaL_traceback(L, L, msg, 1); /* append a standard traceback */ -#endif return 1; /* return the traceback */ } /* -** Interface to 'lua_pcall', which sets appropriate message function -** and error handler. Used to run all chunks. +** Interface to 'lua_pcall', which sets appropriate message function and error +** handler. Used to run all chunks. Results or error traceback left on stack. +** This function is interactive so unlike lua_pcallx(), the error is sent direct +** to the print function and erroring does not trigger an on error restart. */ -static int docall (lua_State *L, int narg, int nres) { +static int docall (lua_State *L, int narg) { int status; int base = lua_gettop(L) - narg; /* function index */ lua_pushcfunction(L, msghandler); /* push message handler */ lua_insert(L, base); /* put it under chunk and args */ - status = lua_pcall(L, narg, (nres ? 0 : LUA_MULTRET), base); + status = lua_pcall(L, narg, LUA_MULTRET, base); lua_remove(L, base); /* remove message handler from the stack */ /* force a complete garbage collection in case of errors */ if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); return status; } + +#ifndef DISABLE_STARTUP_BANNER static void print_version (lua_State *L) { - #ifndef DISABLE_STARTUP_BANNER lua_writestringerror( "\n" NODE_VERSION " build " BUILD_DATE " powered by " LUA_RELEASE " on SDK %s\n", SDK_VERSION); - #endif } - +#endif /* ** Returns the string to be used as a prompt by the interpreter. @@ -164,7 +156,6 @@ static void l_create_stdin (lua_State *L); ** other C API and Lua functions might be executed as tasks between lines in ** a multiline, so a standard luaL_ref() registry entry is used instead. */ -//// TODO SHOLD this have an boot return false if pipe empty else nil static void dojob (lua_State *L) { static int MLref = LUA_NOREF; /* Lua Reg entry for cached multi-line */ int status; @@ -204,21 +195,18 @@ static void dojob (lua_State *L) { } /* Execute the compiled chunk of successful */ if (status == 0) - status = docall(L, 0, 0); + status = docall(L, 0); /* print any returned results or error message */ - if (status && !lua_isnil(L, -1)) - lua_writestringerror("Lua error: %s\n", lua_tostring(L, -1)); - if (status == 0 && lua_gettop(L) - 1) - l_print(L, lua_gettop(L) - 1); - - lua_settop(L, 2); - if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); + if (status && !lua_isnil(L, -1)) { + lua_pushliteral(L, "Lua error: "); + lua_insert(L , -2); + } + l_print(L, lua_gettop(L) - 1); /* print error or results one stack */ } prompt = get_prompt(L, MLref!= LUA_NOREF ? 0 : 1); input_setprompt(prompt); lua_writestring(prompt,strlen(prompt)); - lua_pushnil(L); } @@ -241,7 +229,9 @@ static int pmain (lua_State *L) { input_setup(LUA_MAXINPUT, get_prompt(L, 1)); lua_input_string(" \n", 2); /* queue CR to issue first prompt */ +#ifndef DISABLE_STARTUP_BANNER print_version(L); +#endif /* * And last of all, kick off application initialisation. Note that if * LUA_INIT_STRING is a file reference and the file system is uninitialised @@ -252,7 +242,7 @@ static int pmain (lua_State *L) { luaL_loadfile(L, init+1) : luaL_loadbuffer(L, init, strlen(init), "=INIT"); if (status == LUA_OK) - status = docall(L, 0, 0); + status = docall(L, 0); if (status != LUA_OK) l_print (L, 1); return 0; @@ -274,7 +264,7 @@ int lua_main (void) { } globalL = L; lua_pushcfunction(L, pmain); - if (docall(L, 0, 0) != LUA_OK) { + if (docall(L, 0) != LUA_OK) { if (strstr(lua_tostring(L, -1),"!LFSrestart!")) { lua_close(L); return 1; /* non-zero return to flag LFS reload */ @@ -337,7 +327,7 @@ static int l_read_stdin (lua_State *L) { /* likewise if not CR terminated, then unread and ditto */ lua_insert(L, 1); /* insert false return above the pipe */ lua_getfield(L, 2, "unread"); - lua_insert(L, 1); /* insert pipe.unread above the pipe */ + lua_insert(L, 2); /* insert pipe.unread above the pipe */ lua_call(L, 2, 0); /* pobj:unread(line) */ return 1; /* return false */ } diff --git a/app/lua53/lua.h b/app/lua53/lua.h index 9f8adc5e..818efb9b 100644 --- a/app/lua53/lua.h +++ b/app/lua53/lua.h @@ -467,16 +467,15 @@ typedef struct ROTable ROTable; typedef const struct ROTable_entry ROTable_entry; typedef size_t KeyCache; -LUA_API void (lua_pushrotable) (lua_State *L, const ROTable *p); +LUA_API void (lua_pushrotable) (lua_State *L, const ROTable *p); LUA_API void (lua_createrotable) (lua_State *L, ROTable *t, const ROTable_entry *e, ROTable *mt); LUA_API lua_State *(lua_getstate) (void); LUA_API KeyCache *(lua_getcache) (int cl); LUA_API int (lua_getstrings) (lua_State *L, int opt); LUA_API int (lua_freeheap) (void); -LUAI_FUNC int luaN_flashSetup (lua_State *L); -LUAI_FUNC int luaN_reload_reboot (lua_State *L); -LUAI_FUNC int luaN_index (lua_State *L); +LUAI_FUNC int lua_lfsreload (lua_State *L); +LUAI_FUNC int lua_lfsindex (lua_State *L); #define luaN_freearray(L,a,l) luaM_freearray(L,a,l) @@ -487,10 +486,11 @@ LUAI_FUNC int luaN_index (lua_State *L); typedef struct Proto Proto; #ifdef DEVELOPMENT_USE_GDB -LUALIB_API void lua_debugbreak(void); -#define ASSERT(s) if (!(s)) {();} +LUALIB_API void (lua_debugbreak)(void); +#define ASSERT(s) if (!(s)) {lua_debugbreak();} #else -#define ASSERT(s) +#define lua_debugbreak() (void)(0) +#define ASSERT(s) (void)(0) #endif LUAI_FUNC int luaG_stripdebug (lua_State *L, Proto *f, int level, int recv); diff --git a/app/lua53/lundump.h b/app/lua53/lundump.h index ef4bff5b..fe7101a2 100644 --- a/app/lua53/lundump.h +++ b/app/lua53/lundump.h @@ -48,4 +48,46 @@ LUAI_FUNC int luaU_DumpAllProtos(lua_State *L, const Proto *m, lua_Writer w, void *data, int strip); LUAI_FUNC int luaU_undumpLFS(lua_State *L, ZIO *Z, int isabs); + +typedef struct FlashHeader LFSHeader; +/* +** The LFSHeader uses offsets rather than pointers to avoid 32 vs 64 bit issues +** during host compilation. The offsets are in units of lu_int32's and NOT +** size_t, though clearly any internal pointers are of the size_t for the +** executing architectures: 4 or 8 byte. Likewise recources are size_t aligned +** so LFS regions built for 64-bit execution will have 4-byte alignment packing +** between resources. +*/ +struct FlashHeader{ + lu_int32 flash_sig; /* a standard fingerprint identifying an LFS image */ + lu_int32 flash_size; /* Size of LFS image in bytes */ + lu_int32 seed; /* random number seed used in LFS */ + lu_int32 timestamp; /* timestamp of LFS build */ + lu_int32 nROuse; /* number of elements in ROstrt */ + lu_int32 nROsize; /* size of ROstrt */ + lu_int32 oROhash; /* offset of TString ** ROstrt hash */ + lu_int32 protoROTable; /* offset of master ROTable for proto lookup */ + lu_int32 protoHead; /* offset of linked list of Protos in LFS */ + lu_int32 shortTShead; /* offset of linked list of short TStrings in LFS */ + lu_int32 longTShead; /* offset of linked list of long TStrings in LFS */ + lu_int32 reserved; +}; + +#ifdef LUA_USE_HOST +extern void *LFSregion; +LUAI_FUNC void luaN_setabsolute(lu_int32 addr); +#endif + +#define FLASH_FORMAT_VERSION ( 2 << 8) +#define FLASH_SIG_B1 0x06 +#define FLASH_SIG_B2 0x02 +#define FLASH_SIG_PASS2 0x0F +#define FLASH_FORMAT_MASK 0xF00 +#define FLASH_SIG_B2_MASK 0x04 +#define FLASH_SIG_ABSOLUTE 0x01 +#define FLASH_SIG_IN_PROGRESS 0x08 +#define FLASH_SIG (0xfafaa050 | FLASH_FORMAT_VERSION) + +#define FLASH_FORMAT_MASK 0xF00 + #endif diff --git a/app/modules/ads1115.c b/app/modules/ads1115.c index 717a3bb8..00b6a5eb 100644 --- a/app/modules/ads1115.c +++ b/app/modules/ads1115.c @@ -499,7 +499,7 @@ static int ads1115_lua_readoutdone(void * param) { luaL_unref(L, LUA_REGISTRYINDEX, ads_ctrl->timer_ref); ads_ctrl->timer_ref = LUA_NOREF; read_common(ads_ctrl, raw, L); - lua_call(L, 4, 0); + luaL_pcallx(L, 4, 0); } // Read the conversion register from the ADC device diff --git a/app/modules/bme280.c b/app/modules/bme280.c index 057e1e68..532e8132 100644 --- a/app/modules/bme280.c +++ b/app/modules/bme280.c @@ -320,9 +320,9 @@ static void bme280_readoutdone (void *arg) NODE_DBG("timer out\n"); lua_State *L = lua_getstate(); lua_rawgeti (L, LUA_REGISTRYINDEX, lua_connected_readout_ref); - lua_call (L, 0, 0); luaL_unref (L, LUA_REGISTRYINDEX, lua_connected_readout_ref); os_timer_disarm (&bme280_timer); + luaL_pcallx (L, 0, 0); } static int bme280_lua_startreadout(lua_State* L) { diff --git a/app/modules/bme680.c b/app/modules/bme680.c index b3c9ad37..9b3dee89 100644 --- a/app/modules/bme680.c +++ b/app/modules/bme680.c @@ -430,9 +430,9 @@ static void bme280_readoutdone (void *arg) NODE_DBG("timer out\n"); lua_State *L = lua_getstate(); lua_rawgeti (L, LUA_REGISTRYINDEX, lua_connected_readout_ref); - lua_call (L, 0, 0); luaL_unref (L, LUA_REGISTRYINDEX, lua_connected_readout_ref); os_timer_disarm (&bme680_timer); + luaL_pcallx (L, 0, 0); } static int bme680_lua_startreadout(lua_State* L) { diff --git a/app/modules/cron.c b/app/modules/cron.c index 3afad93a..aa85e8b0 100644 --- a/app/modules/cron.c +++ b/app/modules/cron.c @@ -200,7 +200,7 @@ static void cron_handle_time(uint8_t mon, uint8_t dom, uint8_t dow, uint8_t hour if ((ent->desc.min & desc.min ) == 0) continue; lua_rawgeti(L, LUA_REGISTRYINDEX, ent->cb_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, cronent_list[i]); - lua_call(L, 1, 0); + luaL_pcallx(L, 1, 0); } } diff --git a/app/modules/crypto.c b/app/modules/crypto.c index df46703c..2d28f375 100644 --- a/app/modules/crypto.c +++ b/app/modules/crypto.c @@ -54,7 +54,8 @@ static int call_encoder( lua_State* L, const char *function ) { lua_getfield(L, -1, function); lua_insert(L, 1); //move function below the argument lua_pop(L, 1); //and dump the encoder rotable from stack. - lua_call(L,1,1); // call encoder.xxx(string) + lua_call(L,1,1); // Normal call encoder.xxx(string) + // (errors thrown back to caller) return 1; } diff --git a/app/modules/dcc.c b/app/modules/dcc.c index 70b36784..c501b94f 100644 --- a/app/modules/dcc.c +++ b/app/modules/dcc.c @@ -53,13 +53,13 @@ void notifyDccReset(uint8_t hardReset ) { lua_State* L = lua_getstate(); cbInit(L, DCC_RESET); cbAddFieldInteger(L, hardReset, "hardReset"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccIdle(void) { lua_State* L = lua_getstate(); cbInit(L, DCC_IDLE); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps ) { @@ -70,7 +70,7 @@ void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_D cbAddFieldInteger(L, Speed, "Speed"); cbAddFieldInteger(L, Dir, "Dir"); cbAddFieldInteger(L, SpeedSteps, "SpeedSteps"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccSpeedRaw( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Raw) { @@ -79,7 +79,7 @@ void notifyDccSpeedRaw( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Raw) { cbAddFieldInteger(L, Addr, "Addr"); cbAddFieldInteger(L, AddrType, "AddrType"); cbAddFieldInteger(L, Raw, "Raw"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { @@ -89,7 +89,7 @@ void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uin cbAddFieldInteger(L, AddrType, "AddrType"); cbAddFieldInteger(L, FuncGrp, "FuncGrp"); cbAddFieldInteger(L, FuncState, "FuncState"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t Direction, uint8_t OutputPower ) { @@ -99,7 +99,7 @@ void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t D cbAddFieldInteger(L, OutputPair, "OutputPair"); cbAddFieldInteger(L, Direction, "Direction"); cbAddFieldInteger(L, OutputPower, "OutputPower"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) { @@ -108,28 +108,28 @@ void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t Output cbAddFieldInteger(L, Addr, "Addr"); cbAddFieldInteger(L, Direction, "Direction"); cbAddFieldInteger(L, OutputPower, "OutputPower"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccAccBoardAddrSet( uint16_t BoardAddr) { lua_State* L = lua_getstate(); cbInit(L, DCC_ACCESSORY); cbAddFieldInteger(L, BoardAddr, "BoardAddr"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccAccOutputAddrSet( uint16_t Addr) { lua_State* L = lua_getstate(); cbInit(L, DCC_ACCESSORY); cbAddFieldInteger(L, Addr, "Addr"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccSigOutputState( uint16_t Addr, uint8_t State) { lua_State* L = lua_getstate(); cbInit(L, DCC_ACCESSORY); cbAddFieldInteger(L, State, "State"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyDccMsg( DCC_MSG * Msg ) { @@ -142,14 +142,14 @@ void notifyDccMsg( DCC_MSG * Msg ) { ets_sprintf(field, "Data%d", i); cbAddFieldInteger(L, Msg->Data[i], field); } - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } void notifyServiceMode(bool InServiceMode){ lua_State* L = lua_getstate(); cbInit(L, DCC_SERVICEMODE); cbAddFieldInteger(L, InServiceMode, "InServiceMode"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } // CV handling @@ -163,7 +163,8 @@ uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) { lua_newtable(L); cbAddFieldInteger(L, CV, "CV"); cbAddFieldInteger(L, Writable, "Writable"); - lua_call(L, 2, 1); + if (luaL_pcallx(L, 2, 1) != LUA_OK) + return 0; uint8 result = lua_tointeger(L, -1); lua_pop(L, 1); return result; @@ -177,7 +178,8 @@ uint8_t notifyCVRead( uint16_t CV) { lua_pushinteger(L, CV_READ); lua_newtable(L); cbAddFieldInteger(L, CV, "CV"); - lua_call(L, 2, 1); + if (luaL_pcallx(L, 2, 1) != LUA_OK) + return 0;; uint8 result = lua_tointeger(L, -1); lua_pop(L, 1); return result; @@ -192,7 +194,7 @@ uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) { lua_newtable(L); cbAddFieldInteger(L, CV, "CV"); cbAddFieldInteger(L, Value, "Value"); - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); return Value; } @@ -202,7 +204,7 @@ void notifyCVResetFactoryDefault(void) { return; lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb); lua_pushinteger(L, CV_RESET); - lua_call(L, 1, 0); + luaL_pcallx(L, 1, 0); } static int dcc_lua_setup(lua_State* L) { diff --git a/app/modules/enduser_setup.c b/app/modules/enduser_setup.c index 05f15a87..ed64504a 100644 --- a/app/modules/enduser_setup.c +++ b/app/modules/enduser_setup.c @@ -181,7 +181,7 @@ static void enduser_setup_debug(int line, const char *str) { lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_dbg_cb_ref); lua_pushfstring(L, "%d: \t%s", line, str); - lua_call(L, 1, 0); + luaL_pcallx(L, 1, 0); } } @@ -196,7 +196,7 @@ static void enduser_setup_error(int line, const char *str, int err) lua_rawgeti (L, LUA_REGISTRYINDEX, state->lua_err_cb_ref); lua_pushnumber(L, err); lua_pushfstring(L, "%d: \t%s", line, str); - lua_call (L, 2, 0); + luaL_pcallx (L, 2, 0); } } @@ -209,7 +209,7 @@ static void enduser_setup_connected_callback() if (state != NULL && state->lua_connected_cb_ref != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_connected_cb_ref); - lua_call(L, 0, 0); + luaL_pcallx(L, 0, 0); } } diff --git a/app/modules/file.c b/app/modules/file.c index 2c27be2e..8ecc7801 100644 --- a/app/modules/file.c +++ b/app/modules/file.c @@ -60,7 +60,8 @@ static sint32_t file_rtc_cb( vfs_time *tm ) lua_State *L = lua_getstate(); lua_rawgeti( L, LUA_REGISTRYINDEX, rtc_cb_ref ); - lua_call( L, 0, 1 ); + if (luaL_pcallx( L, 0, 1 ) != LUA_OK) + return res; if (lua_type( L, lua_gettop( L ) ) == LUA_TTABLE) { table2tm( L, tm ); diff --git a/app/modules/gpio.c b/app/modules/gpio.c index 02db35c2..8466d9d6 100644 --- a/app/modules/gpio.c +++ b/app/modules/gpio.c @@ -77,7 +77,8 @@ static void gpio_intr_callback_task (task_param_t param, uint8 priority) then = system_get_time() & 0x7fffffff; } - lua_call(L, 3, 0); + if(luaL_pcallx(L, 3, 0) != LUA_OK) + return; } if (INTERRUPT_TYPE_IS_LEVEL(pin_int_type[pin])) { @@ -237,10 +238,7 @@ static void seroutasync_done (task_param_t arg) lua_rawgeti (L, LUA_REGISTRYINDEX, serout.lua_done_ref); luaL_unref (L, LUA_REGISTRYINDEX, serout.lua_done_ref); serout.lua_done_ref = LUA_NOREF; - if (lua_pcall(L, 0, 0, 0)) { - // Uncaught Error. Print instead of sudden reset - luaL_error(L, "error: %s", lua_tostring(L, -1)); - } + luaL_pcallx(L, 0, 0); } } diff --git a/app/modules/gpio_pulse.c b/app/modules/gpio_pulse.c index e1f6073a..d08189e5 100644 --- a/app/modules/gpio_pulse.c +++ b/app/modules/gpio_pulse.c @@ -463,7 +463,7 @@ static void gpio_pulse_task(os_param_t param, uint8_t prio) active_pulser_ref = LUA_NOREF; luaL_unref(L, LUA_REGISTRYINDEX, pulser_ref); - lua_call(L, rc, 0); + luaL_pcallx(L, rc, 0); } } diff --git a/app/modules/http.c b/app/modules/http.c index 9bb24020..426e6a84 100644 --- a/app/modules/http.c +++ b/app/modules/http.c @@ -100,7 +100,7 @@ static void http_callback( char * response, int http_status, char ** full_respon luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry); http_callback_registry = LUA_NOREF; - lua_call(L, 3, 0); // With 3 arguments and 0 result + luaL_pcallx(L, 3, 0); // With 3 arguments and 0 result } } diff --git a/app/modules/hx711.c b/app/modules/hx711.c index e77c414b..0eb32d91 100644 --- a/app/modules/hx711.c +++ b/app/modules/hx711.c @@ -258,7 +258,7 @@ static void hx711_task(platform_task_param_t param, uint8_t prio) control->freed = param; - lua_call(L, 3, 0); + luaL_pcallx(L, 3, 0); } } #endif diff --git a/app/modules/node.c b/app/modules/node.c index 2821a7ac..bb73469c 100644 --- a/app/modules/node.c +++ b/app/modules/node.c @@ -21,6 +21,39 @@ #define CPU80MHZ 80 #define CPU160MHZ 160 +#define DELAY2SEC 2000 + +static void restart_callback(void *arg) { + UNUSED(arg); + system_restart(); +} +static int default_onerror(lua_State *L) { + static os_timer_t restart_timer = {0}; + /* Use Lua print to print the ToS */ + lua_settop(L, 1); + lua_getglobal(L, "print"); + lua_insert(L, 1); + lua_pcall(L, 1, 0, 0); + /* One first time through set automatic restart after 2s delay */ + if (!restart_timer.timer_func) { + os_timer_setfn(&restart_timer, restart_callback, NULL); + os_timer_arm(&restart_timer, DELAY2SEC, 0); + } + return 0; +} + +// Lua: setonerror([function]) +static int node_setonerror( lua_State* L ) { + lua_settop(L, 1); + if (!lua_isfunction(L, 1)) { + lua_pop(L, 1); + lua_pushcfunction(L, default_onerror); + } + lua_setfield(L, LUA_REGISTRYINDEX, "onerror"); + return 0; +} + + // Lua: startupcommand(string) static int node_startupcommand( lua_State* L ) { size_t l, lrcr; @@ -229,12 +262,17 @@ static int node_input( lua_State* L ) { lua_rawgeti(L, -1, 1); /* get the pipe_write func from stdin[1] */ lua_insert(L, -2); /* and move above the pipe ref */ lua_pushvalue(L, 1); - lua_call(L, 2, 0); /* stdin:write(line) */ + lua_call(L, 2, 0); /* stdin:write(line); errors are thrown to caller */ return 0; } static int serial_debug = 1; +/* +** Output redirector. Note that panics in the output callback cannot be processed +** using luaL_pcallx() as this would create an infinite error loop, so they are +** reported direct to the UART. +*/ void output_redirect(const char *str, size_t l) { lua_State *L = lua_getstate(); int n = lua_gettop(L); @@ -247,8 +285,10 @@ void output_redirect(const char *str, size_t l) { lua_rawgeti(L, -1, 1); /* get the pipe_write func from stdout[1] */ lua_insert(L, -2); /* and move above the pipe ref */ lua_pushlstring(L, str, l); - lua_call(L, 2, 0); /* Reg.stdout:write(str) */ - + if (lua_pcall(L, 2, 0, 0) != LUA_OK) { /* Reg.stdout:write(str) */ + lua_writestringerror("error calling stdout:write(%s)\n", lua_tostring(L, -1)); + system_restart(); + } } else { /* reg.stdout == nil */ uart0_sendStrn(str, l); } @@ -266,7 +306,7 @@ static int node_output( lua_State* L ) lua_pushcfunction(L, pipe_create); lua_insert(L, 1); lua_pushinteger(L, LUA_TASK_MEDIUM); - lua_call(L, 2, 1); /* T[1] = pipe.create(CB, medium_priority) */ + lua_call(L, 2, 1); /* Any pipe.create() errors thrown back to caller */ } else { // remove the stdout pipe lua_pop(L,1); lua_pushnil(L); /* T[1] = nil */ @@ -786,8 +826,9 @@ LROT_BEGIN(node, NULL, 0) LROT_FUNCENTRY( heap, node_heap ) LROT_FUNCENTRY( info, node_info ) LROT_TABENTRY( task, node_task ) - LROT_FUNCENTRY( flashreload, luaN_reload_reboot ) - LROT_FUNCENTRY( flashindex, luaN_index ) + LROT_FUNCENTRY( flashreload, lua_lfsreload ) + LROT_FUNCENTRY( flashindex, lua_lfsindex ) + LROT_FUNCENTRY( setonerror, node_setonerror ) LROT_FUNCENTRY( startupcommand, node_startupcommand ) LROT_FUNCENTRY( restart, node_restart ) LROT_FUNCENTRY( dsleep, node_deepsleep ) @@ -831,5 +872,9 @@ LROT_BEGIN(node, NULL, 0) // LROT_FUNCENTRY( dsleepsetoption, node_deepsleep_setoption ) LROT_END(node, NULL, 0) +int luaopen_node( lua_State *L ) { + lua_settop(L, 0); + return node_setonerror(L); /* set default onerror action */ +} -NODEMCU_MODULE(NODE, "node", node, NULL); +NODEMCU_MODULE(NODE, "node", node, luaopen_node); diff --git a/app/modules/pcm.c b/app/modules/pcm.c index f8548be7..193ab062 100644 --- a/app/modules/pcm.c +++ b/app/modules/pcm.c @@ -27,7 +27,7 @@ static void dispatch_callback( lua_State *L, int self_ref, int cb_ref, int retur if (cb_ref != LUA_NOREF) { lua_rawgeti( L, LUA_REGISTRYINDEX, cb_ref ); lua_rawgeti( L, LUA_REGISTRYINDEX, self_ref ); - lua_call( L, 1, returns ); + luaL_pcallx( L, 1, returns ); } } diff --git a/app/modules/pipe.c b/app/modules/pipe.c index 433e55a7..5e548b48 100644 --- a/app/modules/pipe.c +++ b/app/modules/pipe.c @@ -185,7 +185,7 @@ static int pipe_write_and_read_poster (lua_State *L) { lua_replace(L, UVstate); lua_pushvalue(L, UVfunc); /* Lua CB function */ lua_pushvalue(L, UVpipe); /* pipe table */ - lua_call(L, 1, 1); + lua_call(L, 1, 1); /* Errors are thrown back to caller */ /* * On return from the Lua CB, the task is never reposted if the pipe is empty. * If it is not empty then the Lua CB return status determines when reposting diff --git a/app/modules/rotary.c b/app/modules/rotary.c index f24260cb..fbef3843 100644 --- a/app/modules/rotary.c +++ b/app/modules/rotary.c @@ -114,7 +114,7 @@ static void callback_callOne(lua_State* L, int cb, int mask, int arg, uint32_t t lua_pushinteger(L, arg); lua_pushinteger(L, time); - lua_call(L, 3, 0); + luaL_pcallx(L, 3, 0); } } diff --git a/app/modules/sntp.c b/app/modules/sntp.c index eda23fb6..a21e7ec7 100644 --- a/app/modules/sntp.c +++ b/app/modules/sntp.c @@ -211,7 +211,7 @@ static void handle_error (lua_State *L, ntp_err_t err, const char *msg) lua_pushinteger (L, err); lua_pushstring (L, msg); cleanup (L); - lua_call (L, 2, 0); + luaL_pcallx (L, 2, 0); } else cleanup (L); @@ -319,7 +319,7 @@ static void sntp_handle_result(lua_State *L) { if (have_cb) { - lua_call (L, 4, 0); + luaL_pcallx (L, 4, 0); } } diff --git a/app/modules/softuart.c b/app/modules/softuart.c index f2e018f5..ee09b998 100644 --- a/app/modules/softuart.c +++ b/app/modules/softuart.c @@ -287,7 +287,7 @@ static void softuart_rx_callback(task_param_t arg) } lua_pushlstring(L, softuart_rx_buffer, buffer_lenght); softuart->armed = 1; - lua_call(L, 1, 0); + luaL_pcallx(L, 1, 0); } // Arguments: event name, minimum buffer filled to run callback, callback function diff --git a/app/modules/somfy.c b/app/modules/somfy.c index 429f571f..7b31a679 100644 --- a/app/modules/somfy.c +++ b/app/modules/somfy.c @@ -92,7 +92,7 @@ static void somfy_transmissionDone (task_param_t arg) lua_rawgeti (L, LUA_REGISTRYINDEX, lua_done_ref); luaL_unref (L, LUA_REGISTRYINDEX, lua_done_ref); lua_done_ref = LUA_NOREF; - lua_call (L, 0, 0); + luaL_pcallx (L, 0, 0); } static void ICACHE_RAM_ATTR sendCommand(os_param_t p) { diff --git a/app/modules/switec.c b/app/modules/switec.c index 7b030fff..ee952d60 100644 --- a/app/modules/switec.c +++ b/app/modules/switec.c @@ -47,7 +47,7 @@ static void callback_execute(lua_State* L, unsigned int id) lua_rawgeti(L, LUA_REGISTRYINDEX, callback); callback_free(L, id); - lua_call(L, 0, 0); + luaL_pcallx(L, 0, 0); } } diff --git a/app/modules/tcs34725.c b/app/modules/tcs34725.c index 376c80f8..ee00d6e3 100644 --- a/app/modules/tcs34725.c +++ b/app/modules/tcs34725.c @@ -188,7 +188,7 @@ uint8_t tcs34725EnableDone() lua_rawgeti(L, LUA_REGISTRYINDEX, cb_tcs_en); // Get the callback to call luaL_unref(L, LUA_REGISTRYINDEX, cb_tcs_en); // Unregister the callback to avoid leak cb_tcs_en = LUA_NOREF; - lua_call(L, 0, 0); + luaL_pcallx(L, 0, 0); return 0; } diff --git a/app/modules/tls.c b/app/modules/tls.c index dae5e6a5..d4b40e80 100644 --- a/app/modules/tls.c +++ b/app/modules/tls.c @@ -10,8 +10,9 @@ #include #include - #include +#include + #include "mem.h" #include "lwip/ip_addr.h" #include "espconn.h" @@ -463,12 +464,11 @@ static const char *fill_page_with_pem(lua_State *L, const unsigned char *flash_m static int tls_cert_auth(lua_State *L) { if (ssl_client_options.cert_auth_callback != LUA_NOREF) { - lua_unref(L, ssl_client_options.cert_auth_callback); + luaL_unref(L, LUA_REGISTRYINDEX, ssl_client_options.cert_auth_callback); ssl_client_options.cert_auth_callback = LUA_NOREF; } - if ((lua_type(L, 1) == LUA_TFUNCTION) - || (lua_type(L, 1) == LUA_TLIGHTFUNCTION)) { - ssl_client_options.cert_auth_callback = lua_ref(L, 1); + if (lua_type(L, 1) == LUA_TFUNCTION) { + ssl_client_options.cert_auth_callback = luaL_ref(L, LUA_REGISTRYINDEX); lua_pushboolean(L, true); return 1; } @@ -518,12 +518,11 @@ static int tls_cert_auth(lua_State *L) static int tls_cert_verify(lua_State *L) { if (ssl_client_options.cert_verify_callback != LUA_NOREF) { - lua_unref(L, ssl_client_options.cert_verify_callback); + luaL_unref(L, LUA_REGISTRYINDEX, ssl_client_options.cert_verify_callback); ssl_client_options.cert_verify_callback = LUA_NOREF; } - if ((lua_type(L, 1) == LUA_TFUNCTION) - || (lua_type(L, 1) == LUA_TLIGHTFUNCTION)) { - ssl_client_options.cert_verify_callback = lua_ref(L, 1); + if (lua_type(L, 1) == LUA_TFUNCTION) { + ssl_client_options.cert_verify_callback = luaL_ref(L, LUA_REGISTRYINDEX); lua_pushboolean(L, true); return 1; } diff --git a/app/modules/tmr.c b/app/modules/tmr.c index 39a30a57..d96a51dc 100644 --- a/app/modules/tmr.c +++ b/app/modules/tmr.c @@ -5,48 +5,7 @@ #pragma GCC diagnostic ignored "-Wunused-parameter" #endif -/*------------------------------------- -NEW TIMER API ---------------------------------------- - -tmr.wdclr() -- not changed -tmr.now() -- not changed -tmr.time() -- not changed -tmr.delay() -- not changed -tmr.alarm() -- not changed -tmr.stop() -- changed, see below. use tmr.unregister for old functionality - -tmr.register(ref, interval, mode, function) - bind function with timer and set the interval in ms - the mode can be: - tmr.ALARM_SINGLE for a single run alarm - tmr.ALARM_SEMI for a multiple single run alarm - tmr.ALARM_AUTO for a repating alarm - tmr.register does NOT start the timer - tmr.alarm is a tmr.register & tmr.start macro -tmr.unregister(ref) - stop alarm, unbind function and clean up memory - not needed for ALARM_SINGLE, as it unregisters itself -tmr.start(ref) - ret: bool - start a alarm, returns true on success -tmr.stop(ref) - ret: bool - stops a alarm, returns true on success - this call dose not free any memory, to do so use tmr.unregister - stopped alarms can be started with start -tmr.interval(ref, interval) - set alarm interval, running alarm will be restarted -tmr.state(ref) - ret: (bool, int) or nil - returns alarm status (true=started/false=stopped) and mode - nil if timer is unregistered -tmr.softwd(int) - set a negative value to stop the timer - any other value starts the timer, when the - countdown reaches zero, the device restarts - the timer units are seconds -*/ +/* See docs/modules/tmr.md for documentaiton o current API */ #include "module.h" #include "lauxlib.h" @@ -55,40 +14,40 @@ tmr.softwd(int) #include "user_interface.h" #include "pm/swtimer.h" -#define TIMER_MODE_OFF 3 #define TIMER_MODE_SINGLE 0 -#define TIMER_MODE_SEMI 2 -#define TIMER_MODE_AUTO 1 +#define TIMER_MODE_AUTO 1 +#define TIMER_MODE_SEMI 2 +#define TIMER_MODE_OFF 3 #define TIMER_IDLE_FLAG (1<<7) - #define STRINGIFY_VAL(x) #x #define STRINGIFY(x) STRINGIFY_VAL(x) // assuming system_timer_reinit() has *not* been called -#define MAX_TIMEOUT_DEF 6870947 //SDK 1.5.3 limit (0x68D7A3) +#define MAX_TIMEOUT_DEF 0x68D7A3 // SDK specfied limit static const uint32 MAX_TIMEOUT=MAX_TIMEOUT_DEF; static const char* MAX_TIMEOUT_ERR_STR = "Range: 1-"STRINGIFY(MAX_TIMEOUT_DEF); typedef struct{ os_timer_t os; - sint32_t lua_ref; /* Reference to the callback function */ - sint32_t self_ref; /* Reference to this structure as userdata */ + sint32_t lua_ref; /* Reference to registered callback function */ + sint32_t self_ref; /* Reference to UD registered slot */ uint32_t interval; uint8_t mode; -}timer_struct_t; -typedef timer_struct_t* tmr_t; +} tmr_t; // The previous implementation extended the rtc counter to 64 bits, and then // applied rtc2sec with the current calibration value to that 64 bit value. -// This means that *ALL* clock ticks since bootup are counted with the *current* -// clock period. In extreme cases (long uptime, sudden temperature change), this -// could result in tmr.time() going backwards.... -// This implementation instead applies rtc2usec to short time intervals only (the -// longest being around 1 second), and then accumulates the resulting microseconds -// in a 64 bit counter. That's guaranteed to be monotonic, and should be a lot closer -// to representing an actual uptime. +// This means that *ALL* clock ticks since bootup are counted with the +// *current* clock period. In extreme cases (long uptime, sudden temperature +// change), this could result in tmr.time() going backwards.... +// +// This implementation instead applies rtc2usec to short time intervals only +// (the longest being around 1 second), and then accumulates the resulting +// microseconds in a 64 bit counter. That's guaranteed to be monotonic, and +// should be a lot closer to representing an actual uptime. + static uint32_t rtc_time_cali=0; static uint32_t last_rtc_time=0; static uint64_t last_rtc_time_us=0; @@ -97,180 +56,137 @@ static sint32_t soft_watchdog = -1; static os_timer_t rtc_timer; static void alarm_timer_common(void* arg){ - tmr_t tmr = (tmr_t)arg; - lua_State* L = lua_getstate(); - if(tmr->lua_ref == LUA_NOREF) - return; - lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref); - lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->self_ref); - //if the timer was set to single run we clean up after it - if(tmr->mode == TIMER_MODE_SINGLE){ - luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref); - tmr->lua_ref = LUA_NOREF; - tmr->mode = TIMER_MODE_OFF; - }else if(tmr->mode == TIMER_MODE_SEMI){ - tmr->mode |= TIMER_IDLE_FLAG; - } - if (tmr->mode != TIMER_MODE_AUTO && tmr->self_ref != LUA_REFNIL) { - luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref); - tmr->self_ref = LUA_NOREF; - } - lua_call(L, 1, 0); + tmr_t *tmr = (tmr_t *) arg; + if(tmr->lua_ref > 0) { + lua_State* L = lua_getstate(); + lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref); + lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->self_ref); + if (tmr->mode != TIMER_MODE_AUTO) { + if(tmr->mode == TIMER_MODE_SINGLE) { + luaL_unref2(L, LUA_REGISTRYINDEX, tmr->lua_ref); + luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref); + tmr->mode = TIMER_MODE_OFF; + } else if (tmr->mode == TIMER_MODE_SEMI) { + tmr->mode |= TIMER_IDLE_FLAG; + luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref); + } + } + luaL_pcallx(L, 1, 0); + } } // Lua: tmr.delay( us ) static int tmr_delay( lua_State* L ){ sint32_t us = luaL_checkinteger(L, 1); - if(us <= 0) - return luaL_error(L, "wrong arg range"); - while(us >= 1000000){ - us -= 1000000; - os_delay_us(1000000); - system_soft_wdt_feed (); + luaL_argcheck(L, us>0, 1, "wrong arg range"); + while(us > 0){ + os_delay_us(us >= 1000000 ? 1000000 : us); + system_soft_wdt_feed (); + us -= 1000000; } - if(us>0){ - os_delay_us(us); - system_soft_wdt_feed (); - } - return 0; + return 0; } // Lua: tmr.now() , return system timer in us static int tmr_now(lua_State* L){ - uint32_t now = 0x7FFFFFFF & system_get_time(); - lua_pushinteger(L, now); + lua_pushinteger(L, (uint32_t) (0x7FFFFFFF & system_get_time())); return 1; } // Lua: tmr.ccount() , returns CCOUNT register -static int tmr_ccount( lua_State* L ) -{ +static int tmr_ccount(lua_State* L){ lua_pushinteger(L, CCOUNT_REG); return 1; } -static tmr_t tmr_get( lua_State *L, int stack ) { - tmr_t t = (tmr_t)luaL_checkudata(L, stack, "tmr.timer"); - if (t == NULL) - return (tmr_t)luaL_error(L, "timer object expected"); - return t; -} - -// Lua: tmr.register( ref, interval, mode, function ) -static int tmr_register(lua_State* L){ - tmr_t tmr = tmr_get(L, 1); +/* +** Health warning: this is also called DIRECTLY from alarm() which assumes that the Lua +** stack is preserved for the following start(), so the stack MUST be balanced here. +*/ +// Lua: t:register( interval, mode, function ) +static int tmr_register(lua_State* L) { + tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer"); uint32_t interval = luaL_checkinteger(L, 2); uint8_t mode = luaL_checkinteger(L, 3); luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR); luaL_argcheck(L, (mode == TIMER_MODE_SINGLE || mode == TIMER_MODE_SEMI || mode == TIMER_MODE_AUTO), 3, "Invalid mode"); luaL_argcheck(L, lua_isfunction(L, 4), 4, "Must be function"); + //get the lua function reference lua_pushvalue(L, 4); - sint32_t ref = luaL_ref(L, LUA_REGISTRYINDEX); if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF) os_timer_disarm(&tmr->os); - //there was a bug in this part, the second part of the following condition was missing - if(tmr->lua_ref != LUA_NOREF && tmr->lua_ref != ref) - luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref); - tmr->lua_ref = ref; + luaL_reref(L, LUA_REGISTRYINDEX, &tmr->lua_ref); tmr->mode = mode|TIMER_IDLE_FLAG; tmr->interval = interval; os_timer_setfn(&tmr->os, alarm_timer_common, tmr); return 0; } -// Lua: tmr.start( id / ref ) +// Lua: t:start() static int tmr_start(lua_State* L){ - tmr_t tmr = tmr_get(L, 1); + tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer"); + int idle = tmr->mode & TIMER_IDLE_FLAG; - if (tmr->self_ref == LUA_NOREF) { - lua_pushvalue(L, 1); + lua_settop(L, 1); /* ignore any args after the userdata */ + if (tmr->self_ref == LUA_NOREF) tmr->self_ref = luaL_ref(L, LUA_REGISTRYINDEX); - } - //we return false if the timer is not idle - if(!(tmr->mode&TIMER_IDLE_FLAG)){ - lua_pushboolean(L, 0); - }else{ - tmr->mode &= ~TIMER_IDLE_FLAG; + if(idle) { + tmr->mode &= ~TIMER_IDLE_FLAG; os_timer_arm(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO); - lua_pushboolean(L, 1); - } + } + lua_pushboolean(L, !idle); /* false if the timer is not idle */ return 1; } -// Lua: tmr.alarm( id / ref, interval, repeat, function ) +// Lua: t:alarm( interval, repeat, function ) static int tmr_alarm(lua_State* L){ tmr_register(L); return tmr_start(L); } -// Lua: tmr.stop( id / ref ) +// Lua: t:stop() static int tmr_stop(lua_State* L){ - tmr_t tmr = tmr_get(L, 1); + tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer"); + int idle = tmr->mode == TIMER_MODE_OFF || (tmr->mode & TIMER_IDLE_FLAG); + luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref); - if (tmr->self_ref != LUA_REFNIL) { - luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref); - tmr->self_ref = LUA_NOREF; - } - - //we return false if the timer is idle (of not registered) - if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF){ - tmr->mode |= TIMER_IDLE_FLAG; + if(!idle) os_timer_disarm(&tmr->os); - lua_pushboolean(L, 1); - }else{ - lua_pushboolean(L, 0); - } + tmr->mode |= TIMER_IDLE_FLAG; + lua_pushboolean(L, !idle); /* return false if the timer is idle (or not registered) */ return 1; } #ifdef TIMER_SUSPEND_ENABLE #define TMR_SUSPEND_REMOVED_MSG "This feature has been removed, we apologize for any inconvenience this may have caused." -static int tmr_suspend(lua_State* L){ +#define tmr_suspend tmr_suspend_removed +#define tmr_resume tmr_suspend_removed +#define tmr_suspend_all tmr_suspend_removed +#define tmr_resume_all tmr_suspend_removed +static int tmr_suspend_removed(lua_State* L){ return luaL_error(L, TMR_SUSPEND_REMOVED_MSG); } - -static int tmr_resume(lua_State* L){ - return luaL_error(L, TMR_SUSPEND_REMOVED_MSG); -} - -static int tmr_suspend_all (lua_State *L){ - return luaL_error(L, TMR_SUSPEND_REMOVED_MSG); -} - -static int tmr_resume_all (lua_State *L){ - return luaL_error(L, TMR_SUSPEND_REMOVED_MSG); -} - - #endif -// Lua: tmr.unregister( id / ref ) +// Lua: t:unregister() static int tmr_unregister(lua_State* L){ - tmr_t tmr = tmr_get(L, 1); - - if (tmr->self_ref != LUA_REFNIL) { - luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref); - tmr->self_ref = LUA_NOREF; - } - + tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer"); + luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref); + luaL_unref2(L, LUA_REGISTRYINDEX, tmr->lua_ref); if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF) os_timer_disarm(&tmr->os); - if(tmr->lua_ref != LUA_NOREF) - luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref); - tmr->lua_ref = LUA_NOREF; tmr->mode = TIMER_MODE_OFF; return 0; } -// Lua: tmr.interval( id / ref, interval ) +// Lua: t:interval( interval ) static int tmr_interval(lua_State* L){ - tmr_t tmr = tmr_get(L, 1); - + tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer"); uint32_t interval = luaL_checkinteger(L, 2); luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR); if(tmr->mode != TIMER_MODE_OFF){ @@ -283,10 +199,9 @@ static int tmr_interval(lua_State* L){ return 0; } -// Lua: tmr.state( id / ref ) +// Lua: t:state() static int tmr_state(lua_State* L){ - tmr_t tmr = tmr_get(L, 1); - + tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer"); if(tmr->mode == TIMER_MODE_OFF){ lua_pushnil(L); return 1; @@ -297,28 +212,21 @@ static int tmr_state(lua_State* L){ return 2; } -/*I left the led comments 'couse I don't know -why they are here*/ - -// extern void update_key_led(); // Lua: tmr.wdclr() static int tmr_wdclr( lua_State* L ){ system_soft_wdt_feed (); - // update_key_led(); return 0; } -//system_rtc_clock_cali_proc() returns -//a fixed point value (12 bit fraction part) -//it tells how many rtc clock ticks represent 1us. -//the high 64 bits of the uint64_t multiplication -//are unnedded (I did the math) +// The on ESP8266 system_rtc_clock_cali_proc() returns a fixed point value +// (12 bit fraction part), giving how many rtc clock ticks represent 1us. +// The high 64 bits of the uint64_t multiplication are not needed) static uint32_t rtc2usec(uint64_t rtc){ return (rtc*rtc_time_cali)>>12; } -// This returns the number of microseconds uptime. Note that it relies on the rtc clock, -// which is notoriously temperature dependent +// This returns the number of microseconds uptime. Note that it relies on +// the rtc clock, which is notoriously temperature dependent inline static uint64_t rtc_timer_update(bool do_calibration){ if (do_calibration || rtc_time_cali==0) rtc_time_cali=system_rtc_clock_cali_proc(); @@ -330,8 +238,7 @@ inline static uint64_t rtc_timer_update(bool do_calibration){ // Only update if at least 100ms has passed since we last updated. // This prevents the rounding errors in rtc2usec from accumulating - if (us_since_last>=100000) - { + if (us_since_last>=100000){ last_rtc_time=current; last_rtc_time_us=now; } @@ -356,20 +263,18 @@ static int tmr_time( lua_State* L ){ // Lua: tmr.softwd( value ) static int tmr_softwd( lua_State* L ){ - soft_watchdog = luaL_checkinteger(L, 1); + int t = luaL_checkinteger(L, 1); + luaL_argcheck(L, t>0 , 2, "invalid time"); + soft_watchdog = t; return 0; } // Lua: tmr.create() static int tmr_create( lua_State *L ) { - tmr_t ud = (tmr_t)lua_newuserdata(L, sizeof(timer_struct_t)); - if (!ud) return luaL_error(L, "not enough memory"); + tmr_t *ud = (tmr_t *)lua_newuserdata(L, sizeof(*ud)); luaL_getmetatable(L, "tmr.timer"); lua_setmetatable(L, -2); - ud->lua_ref = LUA_NOREF; - ud->self_ref = LUA_NOREF; - ud->mode = TIMER_MODE_OFF; - os_timer_disarm(&ud->os); + *ud = (tmr_t) {{0}, LUA_NOREF, LUA_NOREF, 0, TIMER_MODE_OFF}; return 1; } @@ -422,13 +327,14 @@ int luaopen_tmr( lua_State *L ){ os_timer_setfn(&rtc_timer, rtc_callback, NULL); os_timer_arm(&rtc_timer, 1000, 1); + // The function rtc_callback calls the a function that calibrates the SoftRTC + // for drift in the esp8266's clock. My guess: after the duration of light_sleep + // there is bound to be some drift in the clock, so a calibration is due. SWTIMER_REG_CB(rtc_callback, SWTIMER_RESUME); - //The function rtc_callback calls the a function that calibrates the SoftRTC for drift in the esp8266's clock. - //My guess: after the duration of light_sleep there's bound to be some drift in the clock, so a calibration is due. - SWTIMER_REG_CB(alarm_timer_common, SWTIMER_RESUME); - //The function alarm_timer_common handles timers created by the developer via tmr.create(). - //No reason not to resume the timers, so resume em'. + // The function alarm_timer_common handles timers created by the developer via + // tmr.create(). No reason not to resume the timers, so resume em'. + SWTIMER_REG_CB(alarm_timer_common, SWTIMER_RESUME); return 0; } diff --git a/app/modules/websocket.c b/app/modules/websocket.c index 060567fa..ee4c8c91 100644 --- a/app/modules/websocket.c +++ b/app/modules/websocket.c @@ -41,7 +41,7 @@ static void websocketclient_onConnectionCallback(ws_info *ws) { if (data->onConnection != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, data->onConnection); // load the callback function lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument - lua_call(L, 1, 0); + luaL_pcallx(L, 1, 0); } } @@ -61,7 +61,7 @@ static void websocketclient_onReceiveCallback(ws_info *ws, int len, char *messag lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument lua_pushlstring(L, message, len); // #2 callback argument lua_pushnumber(L, opCode); // #3 callback argument - lua_call(L, 3, 0); + luaL_pcallx(L, 3, 0); } } @@ -80,7 +80,7 @@ static void websocketclient_onCloseCallback(ws_info *ws, int errorCode) { lua_rawgeti(L, LUA_REGISTRYINDEX, data->onClose); // load the callback function lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument lua_pushnumber(L, errorCode); // pass the error code, #2 callback argument - lua_call(L, 2, 0); + luaL_pcallx(L, 2, 0); } // free self-reference to allow gc (no futher callback will be called until next ws:connect()) @@ -285,7 +285,7 @@ static int websocketclient_gc(lua_State *L) { lua_rawgeti(L, LUA_REGISTRYINDEX, data->onClose); lua_pushnumber(L, -100); - lua_call(L, 1, 0); + luaL_pcallx(L, 1, 0); } luaL_unref(L, LUA_REGISTRYINDEX, data->onClose); } diff --git a/app/modules/wifi.c b/app/modules/wifi.c index 0bb20cef..1f3e6321 100644 --- a/app/modules/wifi.c +++ b/app/modules/wifi.c @@ -46,7 +46,7 @@ static void wifi_smart_succeed_cb(sc_status status, void *pdata){ lua_State* L = (lua_State *)arg; lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_smart_succeed); - lua_call(L, 0, 0); + luaL_pcallx(L, 0, 0); #else @@ -64,9 +64,8 @@ static void wifi_smart_succeed_cb(sc_status status, void *pdata){ lua_pushstring(L, sta_conf->ssid); lua_pushstring(L, sta_conf->password); - lua_call(L, 2, 0); - unregister_lua_cb(L, &wifi_smart_succeed); + luaL_pcallx(L, 2, 0); } #endif // defined( NODE_SMART_OLDSTYLE ) @@ -125,8 +124,8 @@ static void wifi_scan_done(void *arg, STATUS status) { lua_newtable( L ); } - lua_call(L, 1, 0); unregister_lua_cb(L, &wifi_scan_succeed); + luaL_pcallx(L, 1, 0); } #ifdef WIFI_SMART_ENABLE @@ -438,9 +437,9 @@ void wifi_pmSleep_suspend_CB(void) { lua_State* L = lua_getstate(); // Get main Lua thread pointer lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_suspend_cb_ref); // Push suspend callback onto stack - luaL_unref(L, LUA_REGISTRYINDEX, wifi_suspend_cb_ref); // remove suspend callback from LUA_REGISTRY + luaL_unref(L, wifi_suspend_cb_ref); // remove suspend callback from LUA_REGISTRY wifi_suspend_cb_ref = LUA_NOREF; // Update variable since reference is no longer valid - lua_call(L, 0, 0); // Execute suspend callback + luaL_pcallx(L, 0, 0); // Execute suspend callback } else { diff --git a/app/modules/wifi_eventmon.c b/app/modules/wifi_eventmon.c index 010b6f44..fb5639bf 100644 --- a/app/modules/wifi_eventmon.c +++ b/app/modules/wifi_eventmon.c @@ -242,7 +242,7 @@ static void wifi_event_monitor_process_event_queue(task_param_t param, uint8 pri luaL_unref(L, LUA_REGISTRYINDEX, event_ref); //the userdata containing event info is no longer needed event_ref = LUA_NOREF; - lua_call(L, 1, 0); //execute user's callback and pass Lua table + luaL_pcallx(L, 1, 0); //execute user's callback and pass Lua table return; } diff --git a/app/modules/wifi_monitor.c b/app/modules/wifi_monitor.c index d28fa6d4..498029c4 100644 --- a/app/modules/wifi_monitor.c +++ b/app/modules/wifi_monitor.c @@ -321,7 +321,7 @@ static void monitor_task(os_param_t param, uint8_t prio) free(input); - lua_call(L, 1, 0); + luaL_pcallx(L, 1, 0); } else { free(input); } diff --git a/app/modules/wps.c b/app/modules/wps.c index d13194a3..9f4ca691 100644 --- a/app/modules/wps.c +++ b/app/modules/wps.c @@ -30,7 +30,7 @@ LOCAL void ICACHE_FLASH_ATTR user_wps_status_cb(int status) if (wps_callback_ref != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, wps_callback_ref); lua_pushinteger(L, status); - lua_call(L, 1, 0); + luaL_pcallx(L, 1, 0); } } diff --git a/app/pcm/pcm_core.c b/app/pcm/pcm_core.c index 0d347dd4..ae6e6d8b 100644 --- a/app/pcm/pcm_core.c +++ b/app/pcm/pcm_core.c @@ -18,13 +18,14 @@ #include "pcm.h" -static void dispatch_callback( lua_State *L, int self_ref, int cb_ref, int returns ) +static int dispatch_callback( lua_State *L, int self_ref, int cb_ref, int returns ) { if (cb_ref != LUA_NOREF) { lua_rawgeti( L, LUA_REGISTRYINDEX, cb_ref ); lua_rawgeti( L, LUA_REGISTRYINDEX, self_ref ); - lua_call( L, 1, returns ); + return luaL_pcallx( L, 1, returns ); } + return LUA_OK; } void pcm_data_vu( task_param_t param, uint8 prio ) @@ -36,7 +37,7 @@ void pcm_data_vu( task_param_t param, uint8 prio ) lua_rawgeti( L, LUA_REGISTRYINDEX, cfg->cb_vu_ref ); lua_rawgeti( L, LUA_REGISTRYINDEX, cfg->self_ref ); lua_pushnumber( L, (LUA_NUMBER)(cfg->vu_peak) ); - lua_call( L, 2, 0 ); + luaL_pcallx( L, 2, 0 ); } } @@ -52,7 +53,8 @@ void pcm_data_play( task_param_t param, uint8 prio ) // retrieve new data from callback if ((cfg->isr_throttled >= 0) && (cfg->cb_data_ref != LUA_NOREF)) { - dispatch_callback( L, cfg->self_ref, cfg->cb_data_ref, 1 ); + if(dispatch_callback( L, cfg->self_ref, cfg->cb_data_ref, 1 ) != LUA_OK) + return; need_pop = TRUE; if (lua_type( L, -1 ) == LUA_TSTRING) { diff --git a/app/platform/platform.c b/app/platform/platform.c index b203dc36..ee7a759d 100644 --- a/app/platform/platform.c +++ b/app/platform/platform.c @@ -26,12 +26,12 @@ struct gpio_hook_entry { uint32_t bits; }; struct gpio_hook { - struct gpio_hook_entry *entry; uint32_t all_bits; uint32_t count; + struct gpio_hook_entry entry[1]; }; -static struct gpio_hook platform_gpio_hook; +static struct gpio_hook *platform_gpio_hook; #endif #endif @@ -218,10 +218,10 @@ static void ICACHE_RAM_ATTR platform_gpio_intr_dispatcher (void *dummy){ UNUSED(dummy); #ifdef GPIO_INTERRUPT_HOOK_ENABLE - if (gpio_status & platform_gpio_hook.all_bits) { - for (j = 0; j < platform_gpio_hook.count; j++) { - if (gpio_status & platform_gpio_hook.entry[j].bits) - gpio_status = (platform_gpio_hook.entry[j].func)(gpio_status); + if (gpio_status & platform_gpio_hook->all_bits) { + for (j = 0; j < platform_gpio_hook->count; j++) { + if (gpio_status & platform_gpio_hook->entry[j].bits) + gpio_status = (platform_gpio_hook->entry[j].func)(gpio_status); } } #endif @@ -266,7 +266,8 @@ static void ICACHE_RAM_ATTR platform_gpio_intr_dispatcher (void *dummy){ void platform_gpio_init( platform_task_handle_t gpio_task ) { gpio_task_handle = gpio_task; - + // No error handling but this is called at startup when there is a lot of free RAM + platform_gpio_hook = calloc (1, sizeof(*platform_gpio_hook) - sizeof(struct gpio_hook_entry)); ETS_GPIO_INTR_ATTACH(platform_gpio_intr_dispatcher, NULL); } @@ -281,78 +282,53 @@ void platform_gpio_init( platform_task_handle_t gpio_task ) */ int platform_gpio_register_intr_hook(uint32_t bits, platform_hook_function hook) { - struct gpio_hook nh, oh = platform_gpio_hook; - int i, j; + struct gpio_hook *oh = platform_gpio_hook; + int i, j, cur = -1; - if (!hook) { - // Cannot register or unregister null hook + if (!hook) // Cannot register or unregister null hook return 0; - } - int delete_slot = -1; - - // If hook already registered, just update the bits - for (i=0; icount; i++) { + if (hook == oh->entry[i].func) { + cur = i; + break; } } - // This must be the register new hook / delete old hook + // return error status if there is a bits clash + if (oh->all_bits & ~(cur < 0 ? 0 : oh->entry[cur].bits) & bits) + return 0; - if (delete_slot < 0) { - if (bits & oh.all_bits) { - return 0; // Attempt to hook already hooked bits - } - nh.count = oh.count + 1; // register a new hook - } else { - nh.count = oh.count - 1; // unregister an old hook + // Allocate replacement hook block and return 0 on alloc failure + int count = oh->count + (cur < 0 ? 1 : (bits == 0 ? -1 : 0)); + struct gpio_hook *nh = malloc (sizeof *oh + (count -1)*sizeof(struct gpio_hook_entry)); + if (!oh) + return 0; + + nh->all_bits = 0; + nh->count = count; + + for (i=0, j=0; icount; i++) { + if (i == cur && !bits) + continue; /* unregister entry is a no-op */ + nh->entry[j] = oh->entry[i]; /* copy existing entry */ + if (i == cur) + nh->entry[j].bits = bits; /* update bits if this is a replacement */ + nh->all_bits |= nh->entry[j++].bits; } - - // These return NULL if the count = 0 so only error check if > 0) - nh.entry = malloc( nh.count * sizeof(*(nh.entry)) ); - if (nh.count && !(nh.entry)) { - return 0; // Allocation failure - } - - for (i=0, j=0; ientry[j].func = hook; + nh->entry[j].bits = bits; + nh->all_bits |= bits; + } + ETS_GPIO_INTR_DISABLE(); - // This is a structure copy, so interrupts need to be disabled platform_gpio_hook = nh; ETS_GPIO_INTR_ENABLE(); - free(oh.entry); + free(oh); return 1; } #endif // GPIO_INTERRUPT_HOOK_ENABLE diff --git a/app/pm/pmSleep.c b/app/pm/pmSleep.c index c7d67829..4a5a4615 100644 --- a/app/pm/pmSleep.c +++ b/app/pm/pmSleep.c @@ -162,7 +162,7 @@ void pmSleep_execute_lua_cb(int* cb_ref){ lua_rawgeti(L, LUA_REGISTRYINDEX, *cb_ref); // Push resume callback onto the stack lua_unref(L, *cb_ref); // Remove resume callback from registry *cb_ref = LUA_NOREF; // Update variable since reference is no longer valid - lua_call(L, 0, 0); // Execute resume callback + luaL_pcallx(L, 0, 0); // Execute resume callback } } diff --git a/app/pm/swtimer.c b/app/pm/swtimer.c index a58db14a..c3fb31b7 100644 --- a/app/pm/swtimer.c +++ b/app/pm/swtimer.c @@ -8,33 +8,33 @@ * The SDK software timer API executes in a task. The priority of this task in relation to the * application level tasks is unknown (at time of writing). * - * * To determine when a timer's callback should be executed, the respective timer's `timer_expire` - * variable is compared to the hardware counter(FRC2), then, if the timer's `timer_expire` is - * less than the current FRC2 count, the timer's callback is fired. + * variable is compared to the hardware counter(FRC2), then, if the timer's `timer_expire` is + * less than the current FRC2 count, the timer's callback is fired. * * The timers in this list are organized in an ascending order starting with the timer * with the lowest timer_expire. * - * When a timer expires that has a timer_period greater than 0, timer_expire is changed to - * current FRC2 + timer_period, then the timer is inserted back in to the list in the correct position. + * When a timer expires that has a timer_period greater than 0, timer_expire is changed to current + * FRC2 + timer_period, then the timer is inserted back in to the list in the correct position. * - * when using millisecond(default) timers, FRC2 resolution is 312.5 ticks per millisecond. + * When using millisecond(default) timers, FRC2 resolution is 312.5 ticks per millisecond. * * * TIMER SUSPEND API INFO: * - * Timer suspension is achieved by first finding any non-SDK timers by comparing the timer function callback pointer - * of each timer in "timer_list" to a list of registered timer callback pointers stored in the Lua registry. - * If a timer with a corresponding registered callback pointer is found, the timer's timer_expire field is is compared - * to the current FRC2 count and the difference is saved along with the other timer parameters to temporary variables. - * The timer is then disarmed and the parameters are copied back, the timer pointer is then - * added to a separate linked list of which the head pointer is stored as a lightuserdata in the lua registry. + * Timer suspension is achieved by first finding any non-SDK timers by comparing the timer function + * callback pointer of each timer in "timer_list" to a list of registered timer callback pointers + * stored in the Lua registry. If a timer with a corresponding registered callback pointer is found, + * the timer's timer_expire field is is compared to the current FRC2 count and the difference is + * saved along with the other timer parameters to temporary variables. The timer is then disarmed + * and the parameters are copied back, the timer pointer is then added to a separate linked list of + * which the head pointer is stored as a lightuserdata in the lua registry. * - * Resuming the timers is achieved by first retrieving the lightuserdata holding the suspended timer list head pointer. - * Then, starting with the beginning of the list the current FRC2 count is added back to the timer's timer_expire, then - * the timer is manually added back to "timer_list" in an ascending order. - * Once there are no more suspended timers, the function returns + * Resuming the timers is achieved by first retrieving the lightuserdata holding the suspended timer + * list head pointer. Then, starting with the beginning of the list the current FRC2 count is added + * back to the timer's timer_expire, then the timer is manually added back to "timer_list" in an + * ascending order. Once there are no more suspended timers, the function returns. * * */ @@ -57,17 +57,24 @@ #define SWTMR_DEBUG #endif -//this section specifies which lua registry to use. LUA_GLOBALSINDEX or LUA_REGISTRYINDEX +// The SWTMR table is either normally stored in the Lua registry, but at _G.SWTMR_registry_key +// when in debug. THe CB and suspend lists have different names depending of debugging mode. +// Also #ifdef SWTMR_DEBUG #define SWTMR_DBG(fmt, ...) dbg_printf("\n SWTMR_DBG(%s): "fmt"\n", __FUNCTION__, ##__VA_ARGS__) -#define L_REGISTRY LUA_GLOBALSINDEX #define CB_LIST_STR "timer_cb_ptrs" #define SUSP_LIST_STR "suspended_tmr_LL_head" +#define get_swtmr_registry(L) lua_getglobal(L, "SWTMR_registry_key") +#define set_swtmr_registry(L) lua_setglobal(L, "SWTMR_registry_key") #else #define SWTMR_DBG(...) -#define L_REGISTRY LUA_REGISTRYINDEX #define CB_LIST_STR "cb" #define SUSP_LIST_STR "st" +#define get_swtmr_registry(L) lua_pushlightuserdata(L, ®ister_queue); \ + lua_rawget(L, LUA_REGISTRYINDEX) +#define set_swtmr_registry(L) lua_pushlightuserdata(L, ®ister_queue); \ + lua_insert(L, -2); \ + lua_rawset(L, LUA_REGISTRYINDEX) #endif @@ -92,32 +99,21 @@ static task_handle_t cb_register_task_id = 0; //variable to hold task id for tas static void add_to_reg_queue(void* timer_cb_ptr, uint8 suspend_policy); static void process_cb_register_queue(task_param_t param, uint8 priority); - -#ifdef SWTMR_DEBUG -#define push_swtmr_registry_key(L) lua_pushstring(L, "SWTMR_registry_key") -#else -#define push_swtmr_registry_key(L) lua_pushlightuserdata(L, ®ister_queue); -#endif - #include void swtmr_suspend_timers(){ lua_State* L = lua_getstate(); //get swtimer table - push_swtmr_registry_key(L); - lua_rawget(L, L_REGISTRY); + get_swtmr_registry(L); + if(!lua_istable(L, -1)) {lua_pop(L, 1); return;} //get cb_list table lua_pushstring(L, CB_LIST_STR); lua_rawget(L, -2); - //check for existence of the swtimer table and the cb_list table, return if not found - if(!lua_istable(L, -2) || !lua_istable(L, -1)){ - // not necessarily an error maybe there are legitimately no timers to suspend - lua_pop(L, 2); - return; - } + //check for existence of the cb_list table, return if not found + if(!lua_istable(L, -1)) {lua_pop(L, 2); return;} os_timer_t* suspended_timer_list_head = NULL; os_timer_t* suspended_timer_list_tail = NULL; @@ -168,10 +164,10 @@ void swtmr_suspend_timers(){ uint32 period_temp = 0; void* arg_temp = NULL; - /* In this section, the SDK's timer_list is traversed to find any timers that have a registered callback pointer. - * If a registered callback is found, the timer is suspended by saving the difference - * between frc2_count and timer_expire then the timer is disarmed and placed into suspended_timer_list - * so it can later be resumed. + /* In this section, the SDK's timer_list is traversed to find any timers that have a registered + * callback pointer. If a registered callback is found, the timer is suspended by saving the + * difference between frc2_count and timer_expire then the timer is disarmed and placed into + * suspended_timer_list so it can later be resumed. */ while(timer_ptr != NULL){ os_timer_t* next_timer = (os_timer_t*)0xffffffff; @@ -190,7 +186,8 @@ void swtmr_suspend_timers(){ arg_temp = timer_ptr->timer_arg; if(timer_ptr->timer_period == 0 && cb_reg_array[i]->suspend_policy == SWTIMER_RESTART){ - SWTMR_DBG("Warning: suspend_policy(RESTART) is not compatible with single-shot timer(%p), changing suspend_policy to (RESUME)", timer_ptr); + SWTMR_DBG("Warning: suspend_policy(RESTART) is not compatible with single-shot timer(%p), " + "changing suspend_policy to (RESUME)", timer_ptr); cb_reg_array[i]->suspend_policy = SWTIMER_RESUME; } @@ -260,19 +257,15 @@ void swtmr_resume_timers(){ lua_State* L = lua_getstate(); //get swtimer table - push_swtmr_registry_key(L); - lua_rawget(L, L_REGISTRY); + get_swtmr_registry(L); + if(!lua_istable(L, -1)) {lua_pop(L, 1); return;} //get suspended_timer_list lightuserdata lua_pushstring(L, SUSP_LIST_STR); lua_rawget(L, -2); - //check for existence of swtimer table and the suspended_timer_list pointer userdata, return if not found - if(!lua_istable(L, -2) || !lua_isuserdata(L, -1)){ - // not necessarily an error maybe there are legitimately no timers to resume - lua_pop(L, 2); - return; - } + //check for existence of the suspended_timer_list pointer userdata, return if not found + if(!lua_isuserdata(L, -1)) {lua_pop(L, 2); return;} os_timer_t* suspended_timer_list_ptr = lua_touserdata(L, -1); lua_pop(L, 1); //pop suspended timer list userdata from stack @@ -339,25 +332,21 @@ void swtmr_resume_timers(){ void swtmr_cb_register(void* timer_cb_ptr, uint8 suspend_policy){ lua_State* L = lua_getstate(); if(!L){ - //Lua has not started yet, therefore L_REGISTRY is not available. - //add timer cb to queue for later processing after Lua has started + // If Lua has not started yet, then add timer cb to queue for later processing after Lua has started add_to_reg_queue(timer_cb_ptr, suspend_policy); return; } if(timer_cb_ptr){ size_t cb_list_last_idx = 0; - push_swtmr_registry_key(L); - lua_rawget(L, L_REGISTRY); + get_swtmr_registry(L); if(!lua_istable(L, -1)){ - //swtmr does not exist, create and add to registry + //swtmr does not exist, create and add to registry and leave table as ToS lua_pop(L, 1); - lua_newtable(L);//push new table for swtmr.timer_cb_list - // add swtimer table to L_REGISTRY - push_swtmr_registry_key(L); - lua_pushvalue(L, -2); - lua_rawset(L, L_REGISTRY); + lua_newtable(L); + lua_pushvalue(L, -1); + set_swtmr_registry(L); } lua_pushstring(L, CB_LIST_STR); @@ -439,41 +428,40 @@ static void process_cb_register_queue(task_param_t param, uint8 priority) #ifdef SWTMR_DEBUG int print_timer_list(lua_State* L){ - push_swtmr_registry_key(L); - lua_rawget(L, L_REGISTRY); - lua_pushstring(L, CB_LIST_STR); - lua_rawget(L, -2); - if(!lua_istable(L, -2) || !lua_istable(L, -1)){ - lua_pop(L, 2); - return 0; + get_swtmr_registry(L); + if(!lua_istable(L, -1)) {lua_pop(L, 1); return 0;} + + lua_pushstring(L, CB_LIST_STR); + lua_rawget(L, -2); + if(!lua_istable(L, -1)) {lua_pop(L, 2); return 0;} + + os_timer_t* suspended_timer_list_head = NULL; + os_timer_t* suspended_timer_list_tail = NULL; + lua_pushstring(L, SUSP_LIST_STR); + lua_rawget(L, -3); + if(lua_isuserdata(L, -1)){ + suspended_timer_list_head = suspended_timer_list_tail = lua_touserdata(L, -1); + while(suspended_timer_list_tail->timer_next != NULL){ + suspended_timer_list_tail = suspended_timer_list_tail->timer_next; } - os_timer_t* suspended_timer_list_head = NULL; - os_timer_t* suspended_timer_list_tail = NULL; - lua_pushstring(L, SUSP_LIST_STR); - lua_rawget(L, -3); + } + lua_pop(L, 1); + size_t registered_cb_qty = lua_objlen(L, -1); + cb_registry_item_t** cb_reg_array = calloc(1,sizeof(cb_registry_item_t*)*registered_cb_qty); + if(!cb_reg_array){ + luaL_error(L, "%s: unable to suspend timers, out of memory!", __func__); + return 0; + } + uint8 index = 0; + lua_pushnil(L); + while(lua_next(L, -2) != 0){ if(lua_isuserdata(L, -1)){ - suspended_timer_list_head = suspended_timer_list_tail = lua_touserdata(L, -1); - while(suspended_timer_list_tail->timer_next != NULL){ - suspended_timer_list_tail = suspended_timer_list_tail->timer_next; - } - } - lua_pop(L, 1); - size_t registered_cb_qty = lua_objlen(L, -1); - cb_registry_item_t** cb_reg_array = calloc(1,sizeof(cb_registry_item_t*)*registered_cb_qty); - if(!cb_reg_array){ - luaL_error(L, "%s: unable to suspend timers, out of memory!", __func__); - return 0; - } - uint8 index = 0; - lua_pushnil(L); - while(lua_next(L, -2) != 0){ - if(lua_isuserdata(L, -1)){ - cb_reg_array[index] = lua_touserdata(L, -1); - } - lua_pop(L, 1); - index++; + cb_reg_array[index] = lua_touserdata(L, -1); } lua_pop(L, 1); + index++; + } + lua_pop(L, 1); os_timer_t* timer_list_ptr = timer_list; @@ -499,9 +487,7 @@ int print_timer_list(lua_State* L){ } int print_susp_timer_list(lua_State* L){ - push_swtmr_registry_key(L); - lua_rawget(L, L_REGISTRY); - + get_swtmr_registry(L); if(!lua_istable(L, -1)){ return luaL_error(L, "swtmr table not found!"); } @@ -516,7 +502,9 @@ int print_susp_timer_list(lua_State* L){ os_timer_t* susp_timer_list_ptr = lua_touserdata(L, -1); dbg_printf("\n\tsuspended_timer_list:\n"); while(susp_timer_list_ptr != NULL){ - dbg_printf("\tptr:%p\tcb:%p\texpire:%8u\tperiod:%8u\tnext:%p\n",susp_timer_list_ptr, susp_timer_list_ptr->timer_func, susp_timer_list_ptr->timer_expire, susp_timer_list_ptr->timer_period, susp_timer_list_ptr->timer_next); + dbg_printf("\tptr:%p\tcb:%p\texpire:%8u\tperiod:%8u\tnext:%p\n",susp_timer_list_ptr, + susp_timer_list_ptr->timer_func, susp_timer_list_ptr->timer_expire, + susp_timer_list_ptr->timer_period, susp_timer_list_ptr->timer_next); susp_timer_list_ptr = susp_timer_list_ptr->timer_next; } return 0; @@ -542,5 +530,5 @@ LROT_END(test_swtimer_debug, NULL, 0) NODEMCU_MODULE(SWTMR_DBG, "SWTMR_DBG", test_swtimer_debug, NULL); -#endif +#endif /* SWTMR_DEBUG */ diff --git a/app/spiffs/nodemcu_spiffs.h b/app/spiffs/nodemcu_spiffs.h index 3a8b2c45..959a1cab 100644 --- a/app/spiffs/nodemcu_spiffs.h +++ b/app/spiffs/nodemcu_spiffs.h @@ -22,4 +22,5 @@ // Reduce the chance of returning disk full #define SPIFFS_GC_MAX_RUNS 256 +#define SPIFFS_SECURE_ERASE 0 #endif diff --git a/app/spiffs/spiffs.c b/app/spiffs/spiffs.c index 2bebb6e0..50a80f18 100644 --- a/app/spiffs/spiffs.c +++ b/app/spiffs/spiffs.c @@ -93,7 +93,7 @@ static bool myspiffs_set_cfg(spiffs_config *cfg, bool force_create) { if (cfg->phys_size < MIN_BLOCKS_FS * LOG_BLOCK_SIZE_SMALL_FS) { return FALSE; - } else if (cfg->phys_size < MIN_BLOCKS_FS * LOG_BLOCK_SIZE_SMALL_FS) { + } else if (cfg->phys_size < MIN_BLOCKS_FS * LOG_BLOCK_SIZE) { cfg->log_block_size = LOG_BLOCK_SIZE_SMALL_FS; } else { cfg->log_block_size = LOG_BLOCK_SIZE; diff --git a/app/spiffs/spiffs_nucleus.c b/app/spiffs/spiffs_nucleus.c index 6b052b0e..911447cd 100644 --- a/app/spiffs/spiffs_nucleus.c +++ b/app/spiffs/spiffs_nucleus.c @@ -889,6 +889,16 @@ s32_t spiffs_page_delete( fs->stats_p_deleted++; fs->stats_p_allocated--; +#if SPIFFS_SECURE_ERASE + // Secure erase + unsigned char data[SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header)]; + bzero(data, sizeof(data)); + res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_DELE, + 0, + SPIFFS_PAGE_TO_PADDR(fs, pix) + sizeof(spiffs_page_header), sizeof(data), data); + SPIFFS_CHECK_RES(res); +#endif + // mark deleted in source page u8_t flags = 0xff; #if SPIFFS_NO_BLIND_WRITES @@ -2030,7 +2040,7 @@ s32_t spiffs_object_read( // remaining data in page len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs))); // remaining data in file - len_to_read = MIN(len_to_read, fd->size); + len_to_read = MIN(len_to_read, fd->size - cur_offset); SPIFFS_DBG("read: offset:"_SPIPRIi" rd:"_SPIPRIi" data spix:"_SPIPRIsp" is data_pix:"_SPIPRIpg" addr:"_SPIPRIad"\n", cur_offset, len_to_read, data_spix, data_pix, (u32_t)(SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)))); if (len_to_read <= 0) { diff --git a/app/spiffs/spiffs_nucleus.h b/app/spiffs/spiffs_nucleus.h index c4a0729b..42c9f1f0 100644 --- a/app/spiffs/spiffs_nucleus.h +++ b/app/spiffs/spiffs_nucleus.h @@ -262,8 +262,8 @@ #define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0) #define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0) #else -#define SPIFFS_FH_OFFS(fs, fh) (fh) -#define SPIFFS_FH_UNOFFS(fs, fh) (fh) +#define SPIFFS_FH_OFFS(fs, fh) ((spiffs_file)(fh)) +#define SPIFFS_FH_UNOFFS(fs, fh) ((spiffs_file)(fh)) #endif @@ -476,9 +476,6 @@ typedef struct { // object structs -#ifdef _MSC_VER -#pragma pack ( push, 1 ) -#endif // page header, part of each page except object lookup pages // NB: this is always aligned when the data page is an object index, @@ -496,10 +493,9 @@ typedef struct SPIFFS_PACKED { typedef struct SPIFFS_PACKED #if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES #ifdef _MSC_VER -//Note: the following needs to track the sizeof(spiffs_page_ix), which is defined in spiffs_config.h - __declspec( align( 2 ) ) + __declspec( align( 2 ) ) // must track sizeof(spiffs_page_ix) in spiffs_config.h #else - __attribute(( aligned(sizeof(spiffs_page_ix)) )) + __attribute(( aligned(sizeof(spiffs_page_ix)) )) #endif #endif { @@ -525,10 +521,6 @@ typedef struct SPIFFS_PACKED { u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))]; } spiffs_page_object_ix; -#ifdef _MSC_VER -#pragma pack ( pop ) -#endif - // callback func for object lookup visitor typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry, const void *user_const_p, void *user_var_p); diff --git a/app/u8g2lib/u8x8_d_fbrle.c b/app/u8g2lib/u8x8_d_fbrle.c index 8dd74360..1914be82 100644 --- a/app/u8g2lib/u8x8_d_fbrle.c +++ b/app/u8g2lib/u8x8_d_fbrle.c @@ -86,7 +86,7 @@ static uint8_t u8x8_d_fbrle(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *ar lua_State *L = lua_getstate(); lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref ); lua_pushnil( L ); - lua_call( L, 1, 0 ); + luaL_pcallx( L, 1, 0 ); } // and note ongoing framebuffer update ext_u8g2->overlay.fb_update_ongoing = 1; @@ -143,7 +143,7 @@ static uint8_t u8x8_d_fbrle(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *ar lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref ); lua_pushlstring( L, (const char *)fbrle_line, fbrle_line_size ); - lua_call( L, 1, 0 ); + luaL_pcallx( L, 1, 0 ); } } diff --git a/lua_modules/liquidcrystal/lc-gpio4bit.lua b/lua_modules/liquidcrystal/lc-gpio4bit.lua index 4a682dbc..9870bfa0 100644 --- a/lua_modules/liquidcrystal/lc-gpio4bit.lua +++ b/lua_modules/liquidcrystal/lc-gpio4bit.lua @@ -1,4 +1,4 @@ -local gpio, bit = gpio, bit +local gpio, bit = gpio, bit --luacheck: read globals gpio bit return function(bus_args) local rs = bus_args.rs or 0 diff --git a/lua_modules/liquidcrystal/lc-gpio8bit.lua b/lua_modules/liquidcrystal/lc-gpio8bit.lua index 43b7ffd3..cd38a7e0 100644 --- a/lua_modules/liquidcrystal/lc-gpio8bit.lua +++ b/lua_modules/liquidcrystal/lc-gpio8bit.lua @@ -1,4 +1,4 @@ -local gpio, bit = gpio, bit +local gpio, bit = gpio, bit --luacheck: read globals gpio bit return function(bus_args) local rs = bus_args.rs or 0 diff --git a/lua_modules/liquidcrystal/lc-i2c4bit.lua b/lua_modules/liquidcrystal/lc-i2c4bit.lua index 5036026a..dc4011b6 100644 --- a/lua_modules/liquidcrystal/lc-i2c4bit.lua +++ b/lua_modules/liquidcrystal/lc-i2c4bit.lua @@ -1,4 +1,4 @@ -local i2c, bit = i2c, bit +local i2c, bit = i2c, bit --luacheck: read globals i2c bit return function(bus_args) local busid = bus_args.id or 0 diff --git a/lua_modules/liquidcrystal/liquidcrystal.lua b/lua_modules/liquidcrystal/liquidcrystal.lua index d711e57a..ce13834b 100644 --- a/lua_modules/liquidcrystal/liquidcrystal.lua +++ b/lua_modules/liquidcrystal/liquidcrystal.lua @@ -1,4 +1,4 @@ -local bit = bit +local bit = bit --luacheck: read globals bit -- metatable local LiquidCrystal = {} LiquidCrystal.__index = LiquidCrystal