Implement panic call handling for all modules (#3163)

This commit is contained in:
Terry Ellison 2020-06-16 08:19:55 +01:00 committed by GitHub
parent 4e689e9839
commit 1f2e5bba4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 609 additions and 629 deletions

View File

@ -50,32 +50,25 @@ define prTV
printf "Boolean: %u\n", $val.n printf "Boolean: %u\n", $val.n
end end
if $type == 2 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 # Light User Data
printf "Light Udata: %p\n", $val.p printf "Light Udata: %p\n", $val.p
end end
if $type == 5 if $type == 3
# Number # Number
printf "Number: %u\n", $val.n printf "Number: %u\n", $val.n
end end
if $type == 6 if $type == 4
prTS $arg0 # String
printf "String: %s\n", (char *)($val.p)+16
end end
if $type == 7 if $type == 5
# Table # Table
set $o = &($val->gc.h) set $o = &($val->gc.h)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked
printf "Nodes: %4i %p\n", 2<<($o->lsizenode), $o->node printf "Nodes: %4i %p\n", 2<<($o->lsizenode), $o->node
printf "Arry: %4i %p\n", $o->sizearray, $o->array printf "Arry: %4i %p\n", $o->sizearray, $o->array
end end
if $type == 8 if $type == 6
# Function # Function
set $o = &($val->gc.cl.c) set $o = &($val->gc.cl.c)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked 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 $o->nupvalues, $o->gclist, $o->env, $o->f
end end
end end
if $type == 9 if $type == 7
# UserData # UserData
set $o = &($val->gc.u.uv) set $o = &($val->gc.u.uv)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked
printf "UD = %p Userdata: metatable = ", ($o+1)) printf "UD = %p Userdata: metatable = ", ($o+1))
print ($o)->metatable print ($o)->metatable
end end
if $type == 10 if $type == 8
# Thread # Thread
end 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
end end

View File

@ -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 * 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. * 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_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; static int repeat_entry = 0;
if (repeat_entry == 0) { if (repeat_entry == 0) {
dbg_printf("Start up the gdb stub if not already started\n"); dbg_printf("Start up the gdb stub if not already started\n");
gdbstub_init(); gdbstub_init();
gdbstub_redirect_output(1);
repeat_entry = 1; repeat_entry = 1;
} }
asm("break 0,0" ::); asm("break 0,0" ::);
}
#endif #endif
}
#endif #endif

View File

@ -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 int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); 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); 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_pcallx (lua_State *L, int narg, int nres);
LUALIB_API int luaL_posttask( lua_State* L, int prio ); LUALIB_API int luaL_posttask( lua_State* L, int prio );

View File

@ -668,7 +668,7 @@ static int isinstack (CallInfo *ci, const TValue *o) {
void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
const char *name = NULL; 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)) ? const char *kind = (isinstack(L->ci, o)) ?
getobjname(L, L->ci, cast_int(o - L->base), &name) : getobjname(L, L->ci, cast_int(o - L->base), &name) :
NULL; 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) { int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = luaT_typenames[ttype(p1)]; const char *t1 = luaT_typenames[basettype(p1)];
const char *t2 = luaT_typenames[ttype(p2)]; const char *t2 = luaT_typenames[basettype(p2)];
if (t1[2] == t2[2]) if (t1[2] == t2[2])
luaG_runerror(L, "attempt to compare two %s values", t1); luaG_runerror(L, "attempt to compare two %s values", t1);
else else

View File

@ -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 * The first is the startup hook used in lstate.c and the last two are
* implementations of the node.flash API calls. * implementations of the node.flash API calls.
*/ */
@ -194,10 +194,12 @@ static int loadLFS (lua_State *L);
static int loadLFSgc (lua_State *L); static int loadLFSgc (lua_State *L);
static void procFirstPass (void); static void procFirstPass (void);
/* lua_lfsreload() and lua_lfsindex() are exported via lua.h */
/* /*
* Library function called by node.flashreload(filename). * 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 = ""; const char *fn = lua_tostring(L, 1), *msg = "";
int status; int status;
@ -266,7 +268,7 @@ LUALIB_API int luaN_reload_reboot (lua_State *L) {
* - The base address and length of the LFS * - The base address and length of the LFS
* - An array of the module names in 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); int n = lua_gettop(L);
/* Return nil + the LFS base address if the LFS size > 0 and it isn't loaded */ /* Return nil + the LFS base address if the LFS size > 0 and it isn't loaded */

View File

@ -26,27 +26,31 @@
** directly through the task interface the call is wrapped in a C closure with ** 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. ** the error string as an Upval and this is posted to call the Lua reporter.
*/ */
static int report_traceback (lua_State *L) { static int errhandler_aux (lua_State *L) {
// **Temp** lua_rawgeti(L, LUA_REGISTRYINDEX, G(L)->error_reporter); lua_getfield(L, LUA_REGISTRYINDEX, "onerror");
lua_getglobal(L, "print"); if (!lua_isfunction(L, -1)) {
lua_pop(L, 1);
lua_getglobal(L, "print");
}
lua_pushvalue(L, lua_upvalueindex(1)); lua_pushvalue(L, lua_upvalueindex(1));
lua_call(L, 1, 0); /* Using an error handler would cause an infinite loop! */ lua_call(L, 1, 0); /* Using an error handler would cause an infinite loop! */
return 0; return 0;
} }
/* /*
** Catch all error handler for CB calls. This uses debug.traceback() to ** Error handler for luaL_pcallx(), called from the lua_pcall() with a single
** generate a full Lua traceback. ** 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) { static int errhandler (lua_State *L) {
if (lua_isstring(L, 1)) { lua_getglobal(L, "debug");
lua_getglobal(L, "debug"); lua_getfield(L, -1, "traceback");
lua_getfield(L, -1, "traceback"); if (lua_isfunction(L, -1)) {
lua_remove(L, -2); lua_insert(L, 1); /* insert tracback function above error */
lua_pushvalue(L, 1); /* pass error message */ lua_pop(L, 1); /* dump the debug table entry */
lua_pushinteger(L, 2); /* skip this function and traceback */ lua_pushinteger(L, 2); /* skip this function and traceback */
lua_call(L, 2, 1); /* call debug.traceback and return it as a string */ 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); luaL_posttask(L, LUA_TASK_HIGH);
} }
return 0; 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] LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { // [-narg, +0, v]
int status; int status;
int base = lua_gettop(L) - narg; int base = lua_gettop(L) - narg;
lua_pushcfunction(L, luaL_traceback); lua_pushcfunction(L, errhandler);
lua_insert(L, base); /* put under args */ 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 */ lua_remove(L, base); /* remove traceback function */
if (status && nres >=0) if (status != LUA_OK && status != LUA_ERRRUN) {
lua_settop(L, base + nres); /* balance the stack on error */ 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; return status;
} }

View File

@ -1,5 +1,6 @@
/* Read-only tables for Lua */ /*
* NodeMCU extensions to Lua 5.1 for readonly Flash memory support
*/
#ifndef lnodemcu_h #ifndef lnodemcu_h
#define lnodemcu_h #define lnodemcu_h
@ -16,7 +17,8 @@
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s))) #define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s)))
#endif #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_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
#define LRO_LUDATA(v) {{.p = cast(void*,v)}, LUA_TLIGHTUSERDATA} #define LRO_LUDATA(v) {{.p = cast(void*,v)}, LUA_TLIGHTUSERDATA}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL} #define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
@ -25,7 +27,7 @@
#define LRO_FLOATVAL(v) LRO_NUMVAL(v) #define LRO_FLOATVAL(v) LRO_NUMVAL(v)
#define LRO_ROVAL(v) {{.gc = cast(GCObject *, &(v ## _ROTable))}, LUA_TROTABLE} #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_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)},
#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA(x)}, #define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA(x)},
@ -38,9 +40,9 @@
#define LROT_ENTRYREF(rt) (rt ##_entries) #define LROT_ENTRYREF(rt) (rt ##_entries)
#define LROT_TABLEREF(rt) (&rt ##_ROTable) #define LROT_TABLEREF(rt) (&rt ##_ROTable)
#define LROT_BEGIN(rt,mt,f) LROT_TABLE(rt); \ #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) \ #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} }; \ #define LROT_END(rt,mt,f) {NULL, LRO_NILVAL} }; \
const ROTable rt ## _ROTable = { \ const ROTable rt ## _ROTable = { \
(GCObject *)1, LUA_TROTABLE, LROT_MARKED, \ (GCObject *)1, LUA_TROTABLE, LROT_MARKED, \
@ -64,4 +66,9 @@
#define LROT_MASK_GC_INDEX (LROT_MASK_GC | LROT_MASK_INDEX) #define LROT_MASK_GC_INDEX (LROT_MASK_GC | LROT_MASK_INDEX)
/* Maximum length of a rotable name and of a string key*/ /* Maximum length of a rotable name and of a string key*/
#ifdef LUA_CORE
#endif #endif
#endif

View File

@ -410,7 +410,7 @@ typedef struct Table {
GET_BYTE_FN(flags,Table,4,16) GET_BYTE_FN(flags,Table,4,16)
GET_BYTE_FN(lsizenode,Table,4,24) GET_BYTE_FN(lsizenode,Table,4,24)
typedef struct ROTable_entry { typedef const struct ROTable_entry {
const char *key; const char *key;
const TValue value; const TValue value;
} ROTable_entry; } ROTable_entry;

View File

@ -383,10 +383,13 @@ struct lua_Debug {
/* }====================================================================== */ /* }====================================================================== */
typedef struct ROTable ROTable; 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_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_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_NOT_ACTIVE 0 // EGC disabled
#define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure #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 #define dbg_printf printf
#endif #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 // EGC operations modes
#define EGC_NOT_ACTIVE 0 // EGC disabled #define EGC_NOT_ACTIVE 0 // EGC disabled

View File

@ -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; 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) { static int errhandler (lua_State *L) {
if (lua_isnil(L, -1)) lua_getglobal(L, "debug");
return 0; lua_getfield(L, -1, "traceback");
if (lua_type(L, -1) != LUA_TSTRING) { /* is error object not a string? */ if (lua_isfunction(L, -1)) {
if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ lua_insert(L, 1); /* insert tracback function above error */
lua_type(L, -1) == LUA_TSTRING) { /* that produces a string? */ lua_pop(L, 1); /* dump the debug table entry */
lua_remove(L, 1); /* replace ToS with this */ lua_pushinteger(L, 2); /* skip this function and traceback */
} else if (!lua_isnil(L,-1)) { lua_call(L, 2, 1); /* call debug.traceback and return it as a string */
lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1)); lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */
lua_remove(L, 1); /* replace ToS with error object is type value */ luaL_posttask(L, LUA_TASK_HIGH);
}
} }
luaL_traceback(L, L, lua_tostring(L, 1), 1); /* append a standard traceback */ return 0;
lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */
luaL_posttask(L, LUA_TASK_HIGH);
return 1; /* return the traceback */
} }
/* /*
@ -1155,11 +1174,17 @@ static int errhandler (lua_State *L) {
*/ */
LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) {
int status; int status;
int base = lua_gettop(L) - narg; /* function index */ int base = lua_gettop(L) - narg; /* function index */
lua_pushcfunction(L, errhandler); /* push message handler */ lua_pushcfunction(L, errhandler); /* push message handler */
lua_insert(L, base); /* put it under function and args */ lua_insert(L, base); /* put it under function and args */
status = lua_pcall(L, narg, nres, base); 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; 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_checktype(L, -1, LUA_TFUNCTION);
luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref); luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
lua_pushinteger(L, prio); lua_pushinteger(L, prio);
luaL_pcallx (L, 1, 0); luaL_pcallx(L, 1, 0);
} }
/* /*

View File

@ -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 int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); 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, LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode); const char *mode);

View File

@ -83,7 +83,6 @@ typedef LUAI_UACNUMBER l_uacNumber;
typedef LUAI_UACINT l_uacInt; typedef LUAI_UACINT l_uacInt;
#if defined(DEVELOPMENT_USE_GDB) && !defined(lua_assert) #if defined(DEVELOPMENT_USE_GDB) && !defined(lua_assert)
extern void (lua_debugbreak)(void);
# define lua_assert(c) ((c) ? (void) 0 : lua_debugbreak()) # define lua_assert(c) ((c) ? (void) 0 : lua_debugbreak())
#endif #endif

View File

@ -202,8 +202,6 @@ LUALIB_API void lua_debugbreak(void) {
asm("break 0,0" ::); asm("break 0,0" ::);
#endif #endif
} }
#else
#define lua_debugbreak() (void)(0)
#endif #endif
//== NodeMCU lua.h API extensions ============================================// //== NodeMCU lua.h API extensions ============================================//
@ -567,7 +565,7 @@ LUAI_FUNC int luaN_init (lua_State *L) {
#define getfield(L,t,f) \ #define getfield(L,t,f) \
lua_getglobal(L, #t); luaL_getmetafield( L, 1, #f ); lua_remove(L, -2); 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; int n = 0;
#ifdef LUA_USE_ESP #ifdef LUA_USE_ESP
size_t l; size_t l;
@ -579,6 +577,10 @@ LUAI_FUNC int luaN_reload_reboot (lua_State *L) {
#endif #endif
lua_settop(L, 1); lua_settop(L, 1);
lua_getglobal(L, "file"); lua_getglobal(L, "file");
if (lua_isnil(L, 2)) {
lua_pushstring(L, "No file system mounted");
return 1;
}
lua_getfield(L, 2, "exists"); lua_getfield(L, 2, "exists");
lua_pushstring(L, img + off); lua_pushstring(L, img + off);
lua_call(L, 1, 1); lua_call(L, 1, 1);
@ -594,7 +596,7 @@ LUAI_FUNC int luaN_reload_reboot (lua_State *L) {
return 1; return 1;
} }
LUAI_FUNC int luaN_index (lua_State *L) { LUAI_FUNC int lua_lfsindex (lua_State *L) {
lua_settop(L,1); lua_settop(L,1);
if (lua_isstring(L, 1)){ if (lua_isstring(L, 1)){
lua_getglobal(L, "LFS"); lua_getglobal(L, "LFS");

View File

@ -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 #ifndef lnodemcu_h
#define lnodemcu_h #define lnodemcu_h
@ -27,7 +27,7 @@
#define LRO_FLOATVAL(v) {{.n = v}, LUA_TNUMFLT} #define LRO_FLOATVAL(v) {{.n = v}, LUA_TNUMFLT}
#define LRO_ROVAL(v) {{.gc = cast(GCObject *, &(v ## _ROTable))}, LUA_TTBLROF} #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_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)},
#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA(x)}, #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_NEWINDEX LROT_MASK(NEWINDEX)
#define LROT_MASK_GC_INDEX (LROT_MASK_GC | LROT_MASK_INDEX) #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 #ifdef LUA_CORE
#include "lstate.h" #include "lstate.h"
#include "lzio.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_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_writeFlash (void *data, const void *rec, size_t n);
LUAI_FUNC void luaN_flushFlash (void *); LUAI_FUNC void luaN_flushFlash (void *);
LUAI_FUNC void luaN_setFlash (void *, unsigned int o); LUAI_FUNC void luaN_setFlash (void *, unsigned int o);
#endif #endif
#endif #endif

View File

@ -64,9 +64,10 @@ static void l_print (lua_State *L, int n) {
luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
lua_getglobal(L, "print"); lua_getglobal(L, "print");
lua_insert(L, -n-1); lua_insert(L, -n-1);
if (lua_pcall(L, n, 0, 0) != LUA_OK) if (lua_pcall(L, n, 0, 0) != LUA_OK) {
lua_writestringerror( "error calling 'print' (%s)\n", lua_writestringerror("error calling 'print' (%s)\n", lua_tostring(L, -1));
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 ** Message handler is used with all chunks calls. Returns the traceback on ToS
*/ */
static int msghandler (lua_State *L) { static int msghandler (lua_State *L) {
const char *msg = lua_tostring(L, 1); lua_getglobal(L, "debug");
if (msg == NULL) { /* is error object not a string? */ lua_getfield(L, -1, "traceback");
if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ if (lua_isfunction(L, -1)) {
lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ lua_insert(L, 1); /* insert tracback function above error */
return 1; /* that is the message */ lua_pop(L, 1); /* dump the debug table entry */
msg = lua_pushfstring(L, "(error object is a %s value)", lua_pushinteger(L, 2); /* skip this function and traceback */
luaL_typename(L, 1)); lua_call(L, 2, 1); /* call debug.traceback and return it as a string */
lua_remove(L, -2); /* otherwise swap with printable error */
} }
#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 */ return 1; /* return the traceback */
} }
/* /*
** Interface to 'lua_pcall', which sets appropriate message function ** Interface to 'lua_pcall', which sets appropriate message function and error
** and error handler. Used to run all chunks. ** 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 status;
int base = lua_gettop(L) - narg; /* function index */ int base = lua_gettop(L) - narg; /* function index */
lua_pushcfunction(L, msghandler); /* push message handler */ lua_pushcfunction(L, msghandler); /* push message handler */
lua_insert(L, base); /* put it under chunk and args */ 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 */ lua_remove(L, base); /* remove message handler from the stack */
/* force a complete garbage collection in case of errors */ /* force a complete garbage collection in case of errors */
if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
return status; return status;
} }
#ifndef DISABLE_STARTUP_BANNER
static void print_version (lua_State *L) { static void print_version (lua_State *L) {
#ifndef DISABLE_STARTUP_BANNER
lua_writestringerror( "\n" NODE_VERSION " build " BUILD_DATE lua_writestringerror( "\n" NODE_VERSION " build " BUILD_DATE
" powered by " LUA_RELEASE " on SDK %s\n", SDK_VERSION); " powered by " LUA_RELEASE " on SDK %s\n", SDK_VERSION);
#endif
} }
#endif
/* /*
** Returns the string to be used as a prompt by the interpreter. ** 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 ** 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. ** 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 void dojob (lua_State *L) {
static int MLref = LUA_NOREF; /* Lua Reg entry for cached multi-line */ static int MLref = LUA_NOREF; /* Lua Reg entry for cached multi-line */
int status; int status;
@ -204,21 +195,18 @@ static void dojob (lua_State *L) {
} }
/* Execute the compiled chunk of successful */ /* Execute the compiled chunk of successful */
if (status == 0) if (status == 0)
status = docall(L, 0, 0); status = docall(L, 0);
/* print any returned results or error message */ /* print any returned results or error message */
if (status && !lua_isnil(L, -1)) if (status && !lua_isnil(L, -1)) {
lua_writestringerror("Lua error: %s\n", lua_tostring(L, -1)); lua_pushliteral(L, "Lua error: ");
if (status == 0 && lua_gettop(L) - 1) lua_insert(L , -2);
l_print(L, lua_gettop(L) - 1); }
l_print(L, lua_gettop(L) - 1); /* print error or results one stack */
lua_settop(L, 2);
if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
} }
prompt = get_prompt(L, MLref!= LUA_NOREF ? 0 : 1); prompt = get_prompt(L, MLref!= LUA_NOREF ? 0 : 1);
input_setprompt(prompt); input_setprompt(prompt);
lua_writestring(prompt,strlen(prompt)); lua_writestring(prompt,strlen(prompt));
lua_pushnil(L);
} }
@ -241,7 +229,9 @@ static int pmain (lua_State *L) {
input_setup(LUA_MAXINPUT, get_prompt(L, 1)); input_setup(LUA_MAXINPUT, get_prompt(L, 1));
lua_input_string(" \n", 2); /* queue CR to issue first prompt */ lua_input_string(" \n", 2); /* queue CR to issue first prompt */
#ifndef DISABLE_STARTUP_BANNER
print_version(L); print_version(L);
#endif
/* /*
* And last of all, kick off application initialisation. Note that if * And last of all, kick off application initialisation. Note that if
* LUA_INIT_STRING is a file reference and the file system is uninitialised * 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_loadfile(L, init+1) :
luaL_loadbuffer(L, init, strlen(init), "=INIT"); luaL_loadbuffer(L, init, strlen(init), "=INIT");
if (status == LUA_OK) if (status == LUA_OK)
status = docall(L, 0, 0); status = docall(L, 0);
if (status != LUA_OK) if (status != LUA_OK)
l_print (L, 1); l_print (L, 1);
return 0; return 0;
@ -274,7 +264,7 @@ int lua_main (void) {
} }
globalL = L; globalL = L;
lua_pushcfunction(L, pmain); lua_pushcfunction(L, pmain);
if (docall(L, 0, 0) != LUA_OK) { if (docall(L, 0) != LUA_OK) {
if (strstr(lua_tostring(L, -1),"!LFSrestart!")) { if (strstr(lua_tostring(L, -1),"!LFSrestart!")) {
lua_close(L); lua_close(L);
return 1; /* non-zero return to flag LFS reload */ 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 */ /* likewise if not CR terminated, then unread and ditto */
lua_insert(L, 1); /* insert false return above the pipe */ lua_insert(L, 1); /* insert false return above the pipe */
lua_getfield(L, 2, "unread"); 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) */ lua_call(L, 2, 0); /* pobj:unread(line) */
return 1; /* return false */ return 1; /* return false */
} }

View File

@ -467,16 +467,15 @@ typedef struct ROTable ROTable;
typedef const struct ROTable_entry ROTable_entry; typedef const struct ROTable_entry ROTable_entry;
typedef size_t KeyCache; 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 void (lua_createrotable) (lua_State *L, ROTable *t, const ROTable_entry *e, ROTable *mt);
LUA_API lua_State *(lua_getstate) (void); LUA_API lua_State *(lua_getstate) (void);
LUA_API KeyCache *(lua_getcache) (int cl); LUA_API KeyCache *(lua_getcache) (int cl);
LUA_API int (lua_getstrings) (lua_State *L, int opt); LUA_API int (lua_getstrings) (lua_State *L, int opt);
LUA_API int (lua_freeheap) (void); LUA_API int (lua_freeheap) (void);
LUAI_FUNC int luaN_flashSetup (lua_State *L); LUAI_FUNC int lua_lfsreload (lua_State *L);
LUAI_FUNC int luaN_reload_reboot (lua_State *L); LUAI_FUNC int lua_lfsindex (lua_State *L);
LUAI_FUNC int luaN_index (lua_State *L);
#define luaN_freearray(L,a,l) luaM_freearray(L,a,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; typedef struct Proto Proto;
#ifdef DEVELOPMENT_USE_GDB #ifdef DEVELOPMENT_USE_GDB
LUALIB_API void lua_debugbreak(void); LUALIB_API void (lua_debugbreak)(void);
#define ASSERT(s) if (!(s)) {();} #define ASSERT(s) if (!(s)) {lua_debugbreak();}
#else #else
#define ASSERT(s) #define lua_debugbreak() (void)(0)
#define ASSERT(s) (void)(0)
#endif #endif
LUAI_FUNC int luaG_stripdebug (lua_State *L, Proto *f, int level, int recv); LUAI_FUNC int luaG_stripdebug (lua_State *L, Proto *f, int level, int recv);

View File

@ -48,4 +48,46 @@ LUAI_FUNC int luaU_DumpAllProtos(lua_State *L, const Proto *m, lua_Writer w,
void *data, int strip); void *data, int strip);
LUAI_FUNC int luaU_undumpLFS(lua_State *L, ZIO *Z, int isabs); 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 #endif

View File

@ -499,7 +499,7 @@ static int ads1115_lua_readoutdone(void * param) {
luaL_unref(L, LUA_REGISTRYINDEX, ads_ctrl->timer_ref); luaL_unref(L, LUA_REGISTRYINDEX, ads_ctrl->timer_ref);
ads_ctrl->timer_ref = LUA_NOREF; ads_ctrl->timer_ref = LUA_NOREF;
read_common(ads_ctrl, raw, L); read_common(ads_ctrl, raw, L);
lua_call(L, 4, 0); luaL_pcallx(L, 4, 0);
} }
// Read the conversion register from the ADC device // Read the conversion register from the ADC device

View File

@ -320,9 +320,9 @@ static void bme280_readoutdone (void *arg)
NODE_DBG("timer out\n"); NODE_DBG("timer out\n");
lua_State *L = lua_getstate(); lua_State *L = lua_getstate();
lua_rawgeti (L, LUA_REGISTRYINDEX, lua_connected_readout_ref); lua_rawgeti (L, LUA_REGISTRYINDEX, lua_connected_readout_ref);
lua_call (L, 0, 0);
luaL_unref (L, LUA_REGISTRYINDEX, lua_connected_readout_ref); luaL_unref (L, LUA_REGISTRYINDEX, lua_connected_readout_ref);
os_timer_disarm (&bme280_timer); os_timer_disarm (&bme280_timer);
luaL_pcallx (L, 0, 0);
} }
static int bme280_lua_startreadout(lua_State* L) { static int bme280_lua_startreadout(lua_State* L) {

View File

@ -430,9 +430,9 @@ static void bme280_readoutdone (void *arg)
NODE_DBG("timer out\n"); NODE_DBG("timer out\n");
lua_State *L = lua_getstate(); lua_State *L = lua_getstate();
lua_rawgeti (L, LUA_REGISTRYINDEX, lua_connected_readout_ref); lua_rawgeti (L, LUA_REGISTRYINDEX, lua_connected_readout_ref);
lua_call (L, 0, 0);
luaL_unref (L, LUA_REGISTRYINDEX, lua_connected_readout_ref); luaL_unref (L, LUA_REGISTRYINDEX, lua_connected_readout_ref);
os_timer_disarm (&bme680_timer); os_timer_disarm (&bme680_timer);
luaL_pcallx (L, 0, 0);
} }
static int bme680_lua_startreadout(lua_State* L) { static int bme680_lua_startreadout(lua_State* L) {

View File

@ -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; if ((ent->desc.min & desc.min ) == 0) continue;
lua_rawgeti(L, LUA_REGISTRYINDEX, ent->cb_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ent->cb_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, cronent_list[i]); lua_rawgeti(L, LUA_REGISTRYINDEX, cronent_list[i]);
lua_call(L, 1, 0); luaL_pcallx(L, 1, 0);
} }
} }

View File

@ -54,7 +54,8 @@ static int call_encoder( lua_State* L, const char *function ) {
lua_getfield(L, -1, function); lua_getfield(L, -1, function);
lua_insert(L, 1); //move function below the argument lua_insert(L, 1); //move function below the argument
lua_pop(L, 1); //and dump the encoder rotable from stack. 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; return 1;
} }

View File

@ -53,13 +53,13 @@ void notifyDccReset(uint8_t hardReset ) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
cbInit(L, DCC_RESET); cbInit(L, DCC_RESET);
cbAddFieldInteger(L, hardReset, "hardReset"); cbAddFieldInteger(L, hardReset, "hardReset");
lua_call(L, 2, 0); luaL_pcallx(L, 2, 0);
} }
void notifyDccIdle(void) { void notifyDccIdle(void) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
cbInit(L, DCC_IDLE); 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 ) { 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, Speed, "Speed");
cbAddFieldInteger(L, Dir, "Dir"); cbAddFieldInteger(L, Dir, "Dir");
cbAddFieldInteger(L, SpeedSteps, "SpeedSteps"); 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) { 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, Addr, "Addr");
cbAddFieldInteger(L, AddrType, "AddrType"); cbAddFieldInteger(L, AddrType, "AddrType");
cbAddFieldInteger(L, Raw, "Raw"); 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) { 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, AddrType, "AddrType");
cbAddFieldInteger(L, FuncGrp, "FuncGrp"); cbAddFieldInteger(L, FuncGrp, "FuncGrp");
cbAddFieldInteger(L, FuncState, "FuncState"); 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 ) { 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, OutputPair, "OutputPair");
cbAddFieldInteger(L, Direction, "Direction"); cbAddFieldInteger(L, Direction, "Direction");
cbAddFieldInteger(L, OutputPower, "OutputPower"); 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 ) { 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, Addr, "Addr");
cbAddFieldInteger(L, Direction, "Direction"); cbAddFieldInteger(L, Direction, "Direction");
cbAddFieldInteger(L, OutputPower, "OutputPower"); cbAddFieldInteger(L, OutputPower, "OutputPower");
lua_call(L, 2, 0); luaL_pcallx(L, 2, 0);
} }
void notifyDccAccBoardAddrSet( uint16_t BoardAddr) { void notifyDccAccBoardAddrSet( uint16_t BoardAddr) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
cbInit(L, DCC_ACCESSORY); cbInit(L, DCC_ACCESSORY);
cbAddFieldInteger(L, BoardAddr, "BoardAddr"); cbAddFieldInteger(L, BoardAddr, "BoardAddr");
lua_call(L, 2, 0); luaL_pcallx(L, 2, 0);
} }
void notifyDccAccOutputAddrSet( uint16_t Addr) { void notifyDccAccOutputAddrSet( uint16_t Addr) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
cbInit(L, DCC_ACCESSORY); cbInit(L, DCC_ACCESSORY);
cbAddFieldInteger(L, Addr, "Addr"); cbAddFieldInteger(L, Addr, "Addr");
lua_call(L, 2, 0); luaL_pcallx(L, 2, 0);
} }
void notifyDccSigOutputState( uint16_t Addr, uint8_t State) { void notifyDccSigOutputState( uint16_t Addr, uint8_t State) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
cbInit(L, DCC_ACCESSORY); cbInit(L, DCC_ACCESSORY);
cbAddFieldInteger(L, State, "State"); cbAddFieldInteger(L, State, "State");
lua_call(L, 2, 0); luaL_pcallx(L, 2, 0);
} }
void notifyDccMsg( DCC_MSG * Msg ) { void notifyDccMsg( DCC_MSG * Msg ) {
@ -142,14 +142,14 @@ void notifyDccMsg( DCC_MSG * Msg ) {
ets_sprintf(field, "Data%d", i); ets_sprintf(field, "Data%d", i);
cbAddFieldInteger(L, Msg->Data[i], field); cbAddFieldInteger(L, Msg->Data[i], field);
} }
lua_call(L, 2, 0); luaL_pcallx(L, 2, 0);
} }
void notifyServiceMode(bool InServiceMode){ void notifyServiceMode(bool InServiceMode){
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
cbInit(L, DCC_SERVICEMODE); cbInit(L, DCC_SERVICEMODE);
cbAddFieldInteger(L, InServiceMode, "InServiceMode"); cbAddFieldInteger(L, InServiceMode, "InServiceMode");
lua_call(L, 2, 0); luaL_pcallx(L, 2, 0);
} }
// CV handling // CV handling
@ -163,7 +163,8 @@ uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) {
lua_newtable(L); lua_newtable(L);
cbAddFieldInteger(L, CV, "CV"); cbAddFieldInteger(L, CV, "CV");
cbAddFieldInteger(L, Writable, "Writable"); 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); uint8 result = lua_tointeger(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
return result; return result;
@ -177,7 +178,8 @@ uint8_t notifyCVRead( uint16_t CV) {
lua_pushinteger(L, CV_READ); lua_pushinteger(L, CV_READ);
lua_newtable(L); lua_newtable(L);
cbAddFieldInteger(L, CV, "CV"); 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); uint8 result = lua_tointeger(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
return result; return result;
@ -192,7 +194,7 @@ uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) {
lua_newtable(L); lua_newtable(L);
cbAddFieldInteger(L, CV, "CV"); cbAddFieldInteger(L, CV, "CV");
cbAddFieldInteger(L, Value, "Value"); cbAddFieldInteger(L, Value, "Value");
lua_call(L, 2, 0); luaL_pcallx(L, 2, 0);
return Value; return Value;
} }
@ -202,7 +204,7 @@ void notifyCVResetFactoryDefault(void) {
return; return;
lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb); lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb);
lua_pushinteger(L, CV_RESET); lua_pushinteger(L, CV_RESET);
lua_call(L, 1, 0); luaL_pcallx(L, 1, 0);
} }
static int dcc_lua_setup(lua_State* L) { static int dcc_lua_setup(lua_State* L) {

View File

@ -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_rawgeti(L, LUA_REGISTRYINDEX, state->lua_dbg_cb_ref);
lua_pushfstring(L, "%d: \t%s", line, str); 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_rawgeti (L, LUA_REGISTRYINDEX, state->lua_err_cb_ref);
lua_pushnumber(L, err); lua_pushnumber(L, err);
lua_pushfstring(L, "%d: \t%s", line, str); 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) if (state != NULL && state->lua_connected_cb_ref != LUA_NOREF)
{ {
lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_connected_cb_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_connected_cb_ref);
lua_call(L, 0, 0); luaL_pcallx(L, 0, 0);
} }
} }

View File

@ -60,7 +60,8 @@ static sint32_t file_rtc_cb( vfs_time *tm )
lua_State *L = lua_getstate(); lua_State *L = lua_getstate();
lua_rawgeti( L, LUA_REGISTRYINDEX, rtc_cb_ref ); 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) { if (lua_type( L, lua_gettop( L ) ) == LUA_TTABLE) {
table2tm( L, tm ); table2tm( L, tm );

View File

@ -77,7 +77,8 @@ static void gpio_intr_callback_task (task_param_t param, uint8 priority)
then = system_get_time() & 0x7fffffff; 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])) { 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); lua_rawgeti (L, LUA_REGISTRYINDEX, serout.lua_done_ref);
luaL_unref (L, LUA_REGISTRYINDEX, serout.lua_done_ref); luaL_unref (L, LUA_REGISTRYINDEX, serout.lua_done_ref);
serout.lua_done_ref = LUA_NOREF; serout.lua_done_ref = LUA_NOREF;
if (lua_pcall(L, 0, 0, 0)) { luaL_pcallx(L, 0, 0);
// Uncaught Error. Print instead of sudden reset
luaL_error(L, "error: %s", lua_tostring(L, -1));
}
} }
} }

View File

@ -463,7 +463,7 @@ static void gpio_pulse_task(os_param_t param, uint8_t prio)
active_pulser_ref = LUA_NOREF; active_pulser_ref = LUA_NOREF;
luaL_unref(L, LUA_REGISTRYINDEX, pulser_ref); luaL_unref(L, LUA_REGISTRYINDEX, pulser_ref);
lua_call(L, rc, 0); luaL_pcallx(L, rc, 0);
} }
} }

View File

@ -100,7 +100,7 @@ static void http_callback( char * response, int http_status, char ** full_respon
luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry); luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry);
http_callback_registry = LUA_NOREF; 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
} }
} }

View File

@ -258,7 +258,7 @@ static void hx711_task(platform_task_param_t param, uint8_t prio)
control->freed = param; control->freed = param;
lua_call(L, 3, 0); luaL_pcallx(L, 3, 0);
} }
} }
#endif #endif

View File

@ -21,6 +21,39 @@
#define CPU80MHZ 80 #define CPU80MHZ 80
#define CPU160MHZ 160 #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) // Lua: startupcommand(string)
static int node_startupcommand( lua_State* L ) { static int node_startupcommand( lua_State* L ) {
size_t l, lrcr; 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_rawgeti(L, -1, 1); /* get the pipe_write func from stdin[1] */
lua_insert(L, -2); /* and move above the pipe ref */ lua_insert(L, -2); /* and move above the pipe ref */
lua_pushvalue(L, 1); 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; return 0;
} }
static int serial_debug = 1; 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) { void output_redirect(const char *str, size_t l) {
lua_State *L = lua_getstate(); lua_State *L = lua_getstate();
int n = lua_gettop(L); 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_rawgeti(L, -1, 1); /* get the pipe_write func from stdout[1] */
lua_insert(L, -2); /* and move above the pipe ref */ lua_insert(L, -2); /* and move above the pipe ref */
lua_pushlstring(L, str, l); 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 */ } else { /* reg.stdout == nil */
uart0_sendStrn(str, l); uart0_sendStrn(str, l);
} }
@ -266,7 +306,7 @@ static int node_output( lua_State* L )
lua_pushcfunction(L, pipe_create); lua_pushcfunction(L, pipe_create);
lua_insert(L, 1); lua_insert(L, 1);
lua_pushinteger(L, LUA_TASK_MEDIUM); 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 } else { // remove the stdout pipe
lua_pop(L,1); lua_pop(L,1);
lua_pushnil(L); /* T[1] = nil */ lua_pushnil(L); /* T[1] = nil */
@ -786,8 +826,9 @@ LROT_BEGIN(node, NULL, 0)
LROT_FUNCENTRY( heap, node_heap ) LROT_FUNCENTRY( heap, node_heap )
LROT_FUNCENTRY( info, node_info ) LROT_FUNCENTRY( info, node_info )
LROT_TABENTRY( task, node_task ) LROT_TABENTRY( task, node_task )
LROT_FUNCENTRY( flashreload, luaN_reload_reboot ) LROT_FUNCENTRY( flashreload, lua_lfsreload )
LROT_FUNCENTRY( flashindex, luaN_index ) LROT_FUNCENTRY( flashindex, lua_lfsindex )
LROT_FUNCENTRY( setonerror, node_setonerror )
LROT_FUNCENTRY( startupcommand, node_startupcommand ) LROT_FUNCENTRY( startupcommand, node_startupcommand )
LROT_FUNCENTRY( restart, node_restart ) LROT_FUNCENTRY( restart, node_restart )
LROT_FUNCENTRY( dsleep, node_deepsleep ) LROT_FUNCENTRY( dsleep, node_deepsleep )
@ -831,5 +872,9 @@ LROT_BEGIN(node, NULL, 0)
// LROT_FUNCENTRY( dsleepsetoption, node_deepsleep_setoption ) // LROT_FUNCENTRY( dsleepsetoption, node_deepsleep_setoption )
LROT_END(node, NULL, 0) 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);

View File

@ -27,7 +27,7 @@ static void dispatch_callback( lua_State *L, int self_ref, int cb_ref, int retur
if (cb_ref != LUA_NOREF) { if (cb_ref != LUA_NOREF) {
lua_rawgeti( L, LUA_REGISTRYINDEX, cb_ref ); lua_rawgeti( L, LUA_REGISTRYINDEX, cb_ref );
lua_rawgeti( L, LUA_REGISTRYINDEX, self_ref ); lua_rawgeti( L, LUA_REGISTRYINDEX, self_ref );
lua_call( L, 1, returns ); luaL_pcallx( L, 1, returns );
} }
} }

View File

@ -185,7 +185,7 @@ static int pipe_write_and_read_poster (lua_State *L) {
lua_replace(L, UVstate); lua_replace(L, UVstate);
lua_pushvalue(L, UVfunc); /* Lua CB function */ lua_pushvalue(L, UVfunc); /* Lua CB function */
lua_pushvalue(L, UVpipe); /* pipe table */ 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. * 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 * If it is not empty then the Lua CB return status determines when reposting

View File

@ -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, arg);
lua_pushinteger(L, time); lua_pushinteger(L, time);
lua_call(L, 3, 0); luaL_pcallx(L, 3, 0);
} }
} }

View File

@ -211,7 +211,7 @@ static void handle_error (lua_State *L, ntp_err_t err, const char *msg)
lua_pushinteger (L, err); lua_pushinteger (L, err);
lua_pushstring (L, msg); lua_pushstring (L, msg);
cleanup (L); cleanup (L);
lua_call (L, 2, 0); luaL_pcallx (L, 2, 0);
} }
else else
cleanup (L); cleanup (L);
@ -319,7 +319,7 @@ static void sntp_handle_result(lua_State *L) {
if (have_cb) if (have_cb)
{ {
lua_call (L, 4, 0); luaL_pcallx (L, 4, 0);
} }
} }

View File

@ -287,7 +287,7 @@ static void softuart_rx_callback(task_param_t arg)
} }
lua_pushlstring(L, softuart_rx_buffer, buffer_lenght); lua_pushlstring(L, softuart_rx_buffer, buffer_lenght);
softuart->armed = 1; softuart->armed = 1;
lua_call(L, 1, 0); luaL_pcallx(L, 1, 0);
} }
// Arguments: event name, minimum buffer filled to run callback, callback function // Arguments: event name, minimum buffer filled to run callback, callback function

View File

@ -92,7 +92,7 @@ static void somfy_transmissionDone (task_param_t arg)
lua_rawgeti (L, LUA_REGISTRYINDEX, lua_done_ref); lua_rawgeti (L, LUA_REGISTRYINDEX, lua_done_ref);
luaL_unref (L, LUA_REGISTRYINDEX, lua_done_ref); luaL_unref (L, LUA_REGISTRYINDEX, lua_done_ref);
lua_done_ref = LUA_NOREF; 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) { static void ICACHE_RAM_ATTR sendCommand(os_param_t p) {

View File

@ -47,7 +47,7 @@ static void callback_execute(lua_State* L, unsigned int id)
lua_rawgeti(L, LUA_REGISTRYINDEX, callback); lua_rawgeti(L, LUA_REGISTRYINDEX, callback);
callback_free(L, id); callback_free(L, id);
lua_call(L, 0, 0); luaL_pcallx(L, 0, 0);
} }
} }

View File

@ -188,7 +188,7 @@ uint8_t tcs34725EnableDone()
lua_rawgeti(L, LUA_REGISTRYINDEX, cb_tcs_en); // Get the callback to call 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 luaL_unref(L, LUA_REGISTRYINDEX, cb_tcs_en); // Unregister the callback to avoid leak
cb_tcs_en = LUA_NOREF; cb_tcs_en = LUA_NOREF;
lua_call(L, 0, 0); luaL_pcallx(L, 0, 0);
return 0; return 0;
} }

View File

@ -10,8 +10,9 @@
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <ctype.h>
#include "mem.h" #include "mem.h"
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "espconn.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) static int tls_cert_auth(lua_State *L)
{ {
if (ssl_client_options.cert_auth_callback != LUA_NOREF) { 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; ssl_client_options.cert_auth_callback = LUA_NOREF;
} }
if ((lua_type(L, 1) == LUA_TFUNCTION) if (lua_type(L, 1) == LUA_TFUNCTION) {
|| (lua_type(L, 1) == LUA_TLIGHTFUNCTION)) { ssl_client_options.cert_auth_callback = luaL_ref(L, LUA_REGISTRYINDEX);
ssl_client_options.cert_auth_callback = lua_ref(L, 1);
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 1; return 1;
} }
@ -518,12 +518,11 @@ static int tls_cert_auth(lua_State *L)
static int tls_cert_verify(lua_State *L) static int tls_cert_verify(lua_State *L)
{ {
if (ssl_client_options.cert_verify_callback != LUA_NOREF) { 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; ssl_client_options.cert_verify_callback = LUA_NOREF;
} }
if ((lua_type(L, 1) == LUA_TFUNCTION) if (lua_type(L, 1) == LUA_TFUNCTION) {
|| (lua_type(L, 1) == LUA_TLIGHTFUNCTION)) { ssl_client_options.cert_verify_callback = luaL_ref(L, LUA_REGISTRYINDEX);
ssl_client_options.cert_verify_callback = lua_ref(L, 1);
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 1; return 1;
} }

View File

@ -5,48 +5,7 @@
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
#endif #endif
/*------------------------------------- /* See docs/modules/tmr.md for documentaiton o current API */
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
*/
#include "module.h" #include "module.h"
#include "lauxlib.h" #include "lauxlib.h"
@ -55,40 +14,40 @@ tmr.softwd(int)
#include "user_interface.h" #include "user_interface.h"
#include "pm/swtimer.h" #include "pm/swtimer.h"
#define TIMER_MODE_OFF 3
#define TIMER_MODE_SINGLE 0 #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 TIMER_IDLE_FLAG (1<<7)
#define STRINGIFY_VAL(x) #x #define STRINGIFY_VAL(x) #x
#define STRINGIFY(x) STRINGIFY_VAL(x) #define STRINGIFY(x) STRINGIFY_VAL(x)
// assuming system_timer_reinit() has *not* been called // 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 uint32 MAX_TIMEOUT=MAX_TIMEOUT_DEF;
static const char* MAX_TIMEOUT_ERR_STR = "Range: 1-"STRINGIFY(MAX_TIMEOUT_DEF); static const char* MAX_TIMEOUT_ERR_STR = "Range: 1-"STRINGIFY(MAX_TIMEOUT_DEF);
typedef struct{ typedef struct{
os_timer_t os; os_timer_t os;
sint32_t lua_ref; /* Reference to the callback function */ sint32_t lua_ref; /* Reference to registered callback function */
sint32_t self_ref; /* Reference to this structure as userdata */ sint32_t self_ref; /* Reference to UD registered slot */
uint32_t interval; uint32_t interval;
uint8_t mode; uint8_t mode;
}timer_struct_t; } tmr_t;
typedef timer_struct_t* tmr_t;
// The previous implementation extended the rtc counter to 64 bits, and then // The previous implementation extended the rtc counter to 64 bits, and then
// applied rtc2sec with the current calibration value to that 64 bit value. // 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* // This means that *ALL* clock ticks since bootup are counted with the
// clock period. In extreme cases (long uptime, sudden temperature change), this // *current* clock period. In extreme cases (long uptime, sudden temperature
// could result in tmr.time() going backwards.... // 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 // This implementation instead applies rtc2usec to short time intervals only
// in a 64 bit counter. That's guaranteed to be monotonic, and should be a lot closer // (the longest being around 1 second), and then accumulates the resulting
// to representing an actual uptime. // 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 rtc_time_cali=0;
static uint32_t last_rtc_time=0; static uint32_t last_rtc_time=0;
static uint64_t last_rtc_time_us=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 os_timer_t rtc_timer;
static void alarm_timer_common(void* arg){ static void alarm_timer_common(void* arg){
tmr_t tmr = (tmr_t)arg; tmr_t *tmr = (tmr_t *) arg;
lua_State* L = lua_getstate(); if(tmr->lua_ref > 0) {
if(tmr->lua_ref == LUA_NOREF) lua_State* L = lua_getstate();
return; lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->self_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->self_ref); if (tmr->mode != TIMER_MODE_AUTO) {
//if the timer was set to single run we clean up after it if(tmr->mode == TIMER_MODE_SINGLE) {
if(tmr->mode == TIMER_MODE_SINGLE){ luaL_unref2(L, LUA_REGISTRYINDEX, tmr->lua_ref);
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref); luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->lua_ref = LUA_NOREF; tmr->mode = TIMER_MODE_OFF;
tmr->mode = TIMER_MODE_OFF; } else if (tmr->mode == TIMER_MODE_SEMI) {
}else if(tmr->mode == TIMER_MODE_SEMI){ tmr->mode |= TIMER_IDLE_FLAG;
tmr->mode |= TIMER_IDLE_FLAG; luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref);
} }
if (tmr->mode != TIMER_MODE_AUTO && tmr->self_ref != LUA_REFNIL) { }
luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref); luaL_pcallx(L, 1, 0);
tmr->self_ref = LUA_NOREF; }
}
lua_call(L, 1, 0);
} }
// Lua: tmr.delay( us ) // Lua: tmr.delay( us )
static int tmr_delay( lua_State* L ){ static int tmr_delay( lua_State* L ){
sint32_t us = luaL_checkinteger(L, 1); sint32_t us = luaL_checkinteger(L, 1);
if(us <= 0) luaL_argcheck(L, us>0, 1, "wrong arg range");
return luaL_error(L, "wrong arg range"); while(us > 0){
while(us >= 1000000){ os_delay_us(us >= 1000000 ? 1000000 : us);
us -= 1000000; system_soft_wdt_feed ();
os_delay_us(1000000); us -= 1000000;
system_soft_wdt_feed ();
} }
if(us>0){ return 0;
os_delay_us(us);
system_soft_wdt_feed ();
}
return 0;
} }
// Lua: tmr.now() , return system timer in us // Lua: tmr.now() , return system timer in us
static int tmr_now(lua_State* L){ static int tmr_now(lua_State* L){
uint32_t now = 0x7FFFFFFF & system_get_time(); lua_pushinteger(L, (uint32_t) (0x7FFFFFFF & system_get_time()));
lua_pushinteger(L, now);
return 1; return 1;
} }
// Lua: tmr.ccount() , returns CCOUNT register // 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); lua_pushinteger(L, CCOUNT_REG);
return 1; return 1;
} }
static tmr_t tmr_get( lua_State *L, int stack ) { /*
tmr_t t = (tmr_t)luaL_checkudata(L, stack, "tmr.timer"); ** Health warning: this is also called DIRECTLY from alarm() which assumes that the Lua
if (t == NULL) ** stack is preserved for the following start(), so the stack MUST be balanced here.
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);
// 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); uint32_t interval = luaL_checkinteger(L, 2);
uint8_t mode = luaL_checkinteger(L, 3); uint8_t mode = luaL_checkinteger(L, 3);
luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR); 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, (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"); luaL_argcheck(L, lua_isfunction(L, 4), 4, "Must be function");
//get the lua function reference //get the lua function reference
lua_pushvalue(L, 4); lua_pushvalue(L, 4);
sint32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF) if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
os_timer_disarm(&tmr->os); os_timer_disarm(&tmr->os);
//there was a bug in this part, the second part of the following condition was missing luaL_reref(L, LUA_REGISTRYINDEX, &tmr->lua_ref);
if(tmr->lua_ref != LUA_NOREF && tmr->lua_ref != ref)
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = ref;
tmr->mode = mode|TIMER_IDLE_FLAG; tmr->mode = mode|TIMER_IDLE_FLAG;
tmr->interval = interval; tmr->interval = interval;
os_timer_setfn(&tmr->os, alarm_timer_common, tmr); os_timer_setfn(&tmr->os, alarm_timer_common, tmr);
return 0; return 0;
} }
// Lua: tmr.start( id / ref ) // Lua: t:start()
static int tmr_start(lua_State* L){ 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_settop(L, 1); /* ignore any args after the userdata */
lua_pushvalue(L, 1); if (tmr->self_ref == LUA_NOREF)
tmr->self_ref = luaL_ref(L, LUA_REGISTRYINDEX); tmr->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
//we return false if the timer is not idle if(idle) {
if(!(tmr->mode&TIMER_IDLE_FLAG)){ tmr->mode &= ~TIMER_IDLE_FLAG;
lua_pushboolean(L, 0);
}else{
tmr->mode &= ~TIMER_IDLE_FLAG;
os_timer_arm(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO); 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; return 1;
} }
// Lua: tmr.alarm( id / ref, interval, repeat, function ) // Lua: t:alarm( interval, repeat, function )
static int tmr_alarm(lua_State* L){ static int tmr_alarm(lua_State* L){
tmr_register(L); tmr_register(L);
return tmr_start(L); return tmr_start(L);
} }
// Lua: tmr.stop( id / ref ) // Lua: t:stop()
static int tmr_stop(lua_State* L){ 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) { if(!idle)
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;
os_timer_disarm(&tmr->os); os_timer_disarm(&tmr->os);
lua_pushboolean(L, 1); tmr->mode |= TIMER_IDLE_FLAG;
}else{ lua_pushboolean(L, !idle); /* return false if the timer is idle (or not registered) */
lua_pushboolean(L, 0);
}
return 1; return 1;
} }
#ifdef TIMER_SUSPEND_ENABLE #ifdef TIMER_SUSPEND_ENABLE
#define TMR_SUSPEND_REMOVED_MSG "This feature has been removed, we apologize for any inconvenience this may have caused." #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); 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 #endif
// Lua: tmr.unregister( id / ref ) // Lua: t:unregister()
static int tmr_unregister(lua_State* L){ static int tmr_unregister(lua_State* L){
tmr_t tmr = tmr_get(L, 1); tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer");
luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref);
if (tmr->self_ref != LUA_REFNIL) { luaL_unref2(L, LUA_REGISTRYINDEX, tmr->lua_ref);
luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->self_ref = LUA_NOREF;
}
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF) if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
os_timer_disarm(&tmr->os); 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; tmr->mode = TIMER_MODE_OFF;
return 0; return 0;
} }
// Lua: tmr.interval( id / ref, interval ) // Lua: t:interval( interval )
static int tmr_interval(lua_State* L){ 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); uint32_t interval = luaL_checkinteger(L, 2);
luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR); luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR);
if(tmr->mode != TIMER_MODE_OFF){ if(tmr->mode != TIMER_MODE_OFF){
@ -283,10 +199,9 @@ static int tmr_interval(lua_State* L){
return 0; return 0;
} }
// Lua: tmr.state( id / ref ) // Lua: t:state()
static int tmr_state(lua_State* L){ 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){ if(tmr->mode == TIMER_MODE_OFF){
lua_pushnil(L); lua_pushnil(L);
return 1; return 1;
@ -297,28 +212,21 @@ static int tmr_state(lua_State* L){
return 2; return 2;
} }
/*I left the led comments 'couse I don't know
why they are here*/
// extern void update_key_led();
// Lua: tmr.wdclr() // Lua: tmr.wdclr()
static int tmr_wdclr( lua_State* L ){ static int tmr_wdclr( lua_State* L ){
system_soft_wdt_feed (); system_soft_wdt_feed ();
// update_key_led();
return 0; return 0;
} }
//system_rtc_clock_cali_proc() returns // The on ESP8266 system_rtc_clock_cali_proc() returns a fixed point value
//a fixed point value (12 bit fraction part) // (12 bit fraction part), giving how many rtc clock ticks represent 1us.
//it tells how many rtc clock ticks represent 1us. // The high 64 bits of the uint64_t multiplication are not needed)
//the high 64 bits of the uint64_t multiplication
//are unnedded (I did the math)
static uint32_t rtc2usec(uint64_t rtc){ static uint32_t rtc2usec(uint64_t rtc){
return (rtc*rtc_time_cali)>>12; return (rtc*rtc_time_cali)>>12;
} }
// This returns the number of microseconds uptime. Note that it relies on the rtc clock, // This returns the number of microseconds uptime. Note that it relies on
// which is notoriously temperature dependent // the rtc clock, which is notoriously temperature dependent
inline static uint64_t rtc_timer_update(bool do_calibration){ inline static uint64_t rtc_timer_update(bool do_calibration){
if (do_calibration || rtc_time_cali==0) if (do_calibration || rtc_time_cali==0)
rtc_time_cali=system_rtc_clock_cali_proc(); 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. // Only update if at least 100ms has passed since we last updated.
// This prevents the rounding errors in rtc2usec from accumulating // 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=current;
last_rtc_time_us=now; last_rtc_time_us=now;
} }
@ -356,20 +263,18 @@ static int tmr_time( lua_State* L ){
// Lua: tmr.softwd( value ) // Lua: tmr.softwd( value )
static int tmr_softwd( lua_State* L ){ 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; return 0;
} }
// Lua: tmr.create() // Lua: tmr.create()
static int tmr_create( lua_State *L ) { static int tmr_create( lua_State *L ) {
tmr_t ud = (tmr_t)lua_newuserdata(L, sizeof(timer_struct_t)); tmr_t *ud = (tmr_t *)lua_newuserdata(L, sizeof(*ud));
if (!ud) return luaL_error(L, "not enough memory");
luaL_getmetatable(L, "tmr.timer"); luaL_getmetatable(L, "tmr.timer");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
ud->lua_ref = LUA_NOREF; *ud = (tmr_t) {{0}, LUA_NOREF, LUA_NOREF, 0, TIMER_MODE_OFF};
ud->self_ref = LUA_NOREF;
ud->mode = TIMER_MODE_OFF;
os_timer_disarm(&ud->os);
return 1; return 1;
} }
@ -422,13 +327,14 @@ int luaopen_tmr( lua_State *L ){
os_timer_setfn(&rtc_timer, rtc_callback, NULL); os_timer_setfn(&rtc_timer, rtc_callback, NULL);
os_timer_arm(&rtc_timer, 1000, 1); 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); 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; return 0;
} }

View File

@ -41,7 +41,7 @@ static void websocketclient_onConnectionCallback(ws_info *ws) {
if (data->onConnection != LUA_NOREF) { if (data->onConnection != LUA_NOREF) {
lua_rawgeti(L, LUA_REGISTRYINDEX, data->onConnection); // load the callback function 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_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_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument
lua_pushlstring(L, message, len); // #2 callback argument lua_pushlstring(L, message, len); // #2 callback argument
lua_pushnumber(L, opCode); // #3 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->onClose); // load the callback function
lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument 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_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()) // 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_rawgeti(L, LUA_REGISTRYINDEX, data->onClose);
lua_pushnumber(L, -100); lua_pushnumber(L, -100);
lua_call(L, 1, 0); luaL_pcallx(L, 1, 0);
} }
luaL_unref(L, LUA_REGISTRYINDEX, data->onClose); luaL_unref(L, LUA_REGISTRYINDEX, data->onClose);
} }

View File

@ -46,7 +46,7 @@ static void wifi_smart_succeed_cb(sc_status status, void *pdata){
lua_State* L = (lua_State *)arg; lua_State* L = (lua_State *)arg;
lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_smart_succeed); lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_smart_succeed);
lua_call(L, 0, 0); luaL_pcallx(L, 0, 0);
#else #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->ssid);
lua_pushstring(L, sta_conf->password); lua_pushstring(L, sta_conf->password);
lua_call(L, 2, 0);
unregister_lua_cb(L, &wifi_smart_succeed); unregister_lua_cb(L, &wifi_smart_succeed);
luaL_pcallx(L, 2, 0);
} }
#endif // defined( NODE_SMART_OLDSTYLE ) #endif // defined( NODE_SMART_OLDSTYLE )
@ -125,8 +124,8 @@ static void wifi_scan_done(void *arg, STATUS status)
{ {
lua_newtable( L ); lua_newtable( L );
} }
lua_call(L, 1, 0);
unregister_lua_cb(L, &wifi_scan_succeed); unregister_lua_cb(L, &wifi_scan_succeed);
luaL_pcallx(L, 1, 0);
} }
#ifdef WIFI_SMART_ENABLE #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_State* L = lua_getstate(); // Get main Lua thread pointer
lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_suspend_cb_ref); // Push suspend callback onto stack 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 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 else
{ {

View File

@ -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 luaL_unref(L, LUA_REGISTRYINDEX, event_ref); //the userdata containing event info is no longer needed
event_ref = LUA_NOREF; 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; return;
} }

View File

@ -321,7 +321,7 @@ static void monitor_task(os_param_t param, uint8_t prio)
free(input); free(input);
lua_call(L, 1, 0); luaL_pcallx(L, 1, 0);
} else { } else {
free(input); free(input);
} }

View File

@ -30,7 +30,7 @@ LOCAL void ICACHE_FLASH_ATTR user_wps_status_cb(int status)
if (wps_callback_ref != LUA_NOREF) { if (wps_callback_ref != LUA_NOREF) {
lua_rawgeti(L, LUA_REGISTRYINDEX, wps_callback_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, wps_callback_ref);
lua_pushinteger(L, status); lua_pushinteger(L, status);
lua_call(L, 1, 0); luaL_pcallx(L, 1, 0);
} }
} }

View File

@ -18,13 +18,14 @@
#include "pcm.h" #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) { if (cb_ref != LUA_NOREF) {
lua_rawgeti( L, LUA_REGISTRYINDEX, cb_ref ); lua_rawgeti( L, LUA_REGISTRYINDEX, cb_ref );
lua_rawgeti( L, LUA_REGISTRYINDEX, self_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 ) 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->cb_vu_ref );
lua_rawgeti( L, LUA_REGISTRYINDEX, cfg->self_ref ); lua_rawgeti( L, LUA_REGISTRYINDEX, cfg->self_ref );
lua_pushnumber( L, (LUA_NUMBER)(cfg->vu_peak) ); 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 // retrieve new data from callback
if ((cfg->isr_throttled >= 0) && if ((cfg->isr_throttled >= 0) &&
(cfg->cb_data_ref != LUA_NOREF)) { (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; need_pop = TRUE;
if (lua_type( L, -1 ) == LUA_TSTRING) { if (lua_type( L, -1 ) == LUA_TSTRING) {

View File

@ -26,12 +26,12 @@ struct gpio_hook_entry {
uint32_t bits; uint32_t bits;
}; };
struct gpio_hook { struct gpio_hook {
struct gpio_hook_entry *entry;
uint32_t all_bits; uint32_t all_bits;
uint32_t count; 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
#endif #endif
@ -218,10 +218,10 @@ static void ICACHE_RAM_ATTR platform_gpio_intr_dispatcher (void *dummy){
UNUSED(dummy); UNUSED(dummy);
#ifdef GPIO_INTERRUPT_HOOK_ENABLE #ifdef GPIO_INTERRUPT_HOOK_ENABLE
if (gpio_status & platform_gpio_hook.all_bits) { if (gpio_status & platform_gpio_hook->all_bits) {
for (j = 0; j < platform_gpio_hook.count; j++) { for (j = 0; j < platform_gpio_hook->count; j++) {
if (gpio_status & platform_gpio_hook.entry[j].bits) if (gpio_status & platform_gpio_hook->entry[j].bits)
gpio_status = (platform_gpio_hook.entry[j].func)(gpio_status); gpio_status = (platform_gpio_hook->entry[j].func)(gpio_status);
} }
} }
#endif #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 ) void platform_gpio_init( platform_task_handle_t gpio_task )
{ {
gpio_task_handle = 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); 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) int platform_gpio_register_intr_hook(uint32_t bits, platform_hook_function hook)
{ {
struct gpio_hook nh, oh = platform_gpio_hook; struct gpio_hook *oh = platform_gpio_hook;
int i, j; int i, j, cur = -1;
if (!hook) { if (!hook) // Cannot register or unregister null hook
// Cannot register or unregister null hook
return 0; return 0;
}
int delete_slot = -1; // Is the hook already registered?
for (i=0; i<oh->count; i++) {
// If hook already registered, just update the bits if (hook == oh->entry[i].func) {
for (i=0; i<oh.count; i++) { cur = i;
if (hook == oh.entry[i].func) { break;
if (!bits) {
// Unregister if move to zero bits
delete_slot = i;
break;
}
if (bits & (oh.all_bits & ~oh.entry[i].bits)) {
// Attempt to hook an already hooked bit
return 0;
}
// Update the hooked bits (in the right order)
uint32_t old_bits = oh.entry[i].bits;
*(volatile uint32_t *) &oh.entry[i].bits = bits;
*(volatile uint32_t *) &oh.all_bits = (oh.all_bits & ~old_bits) | bits;
ETS_GPIO_INTR_DISABLE();
// This is a structure copy, so interrupts need to be disabled
platform_gpio_hook = oh;
ETS_GPIO_INTR_ENABLE();
return 1;
} }
} }
// 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) { // Allocate replacement hook block and return 0 on alloc failure
if (bits & oh.all_bits) { int count = oh->count + (cur < 0 ? 1 : (bits == 0 ? -1 : 0));
return 0; // Attempt to hook already hooked bits struct gpio_hook *nh = malloc (sizeof *oh + (count -1)*sizeof(struct gpio_hook_entry));
} if (!oh)
nh.count = oh.count + 1; // register a new hook return 0;
} else {
nh.count = oh.count - 1; // unregister an old hook nh->all_bits = 0;
nh->count = count;
for (i=0, j=0; i<oh->count; 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) if (cur < 0) { /* append new hook entry */
nh.entry = malloc( nh.count * sizeof(*(nh.entry)) ); nh->entry[j].func = hook;
if (nh.count && !(nh.entry)) { nh->entry[j].bits = bits;
return 0; // Allocation failure nh->all_bits |= bits;
} }
for (i=0, j=0; i<oh.count; i++) {
// Don't copy if this is the entry to delete
if (i != delete_slot) {
nh.entry[j++] = oh.entry[i];
}
}
if (delete_slot < 0) { // for a register add the hook to the tail and set the all bits
nh.entry[j].bits = bits;
nh.entry[j].func = hook;
nh.all_bits = oh.all_bits | bits;
} else { // for an unregister clear the matching all bits
nh.all_bits = oh.all_bits & (~oh.entry[delete_slot].bits);
}
ETS_GPIO_INTR_DISABLE(); ETS_GPIO_INTR_DISABLE();
// This is a structure copy, so interrupts need to be disabled
platform_gpio_hook = nh; platform_gpio_hook = nh;
ETS_GPIO_INTR_ENABLE(); ETS_GPIO_INTR_ENABLE();
free(oh.entry); free(oh);
return 1; return 1;
} }
#endif // GPIO_INTERRUPT_HOOK_ENABLE #endif // GPIO_INTERRUPT_HOOK_ENABLE

View File

@ -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_rawgeti(L, LUA_REGISTRYINDEX, *cb_ref); // Push resume callback onto the stack
lua_unref(L, *cb_ref); // Remove resume callback from registry lua_unref(L, *cb_ref); // Remove resume callback from registry
*cb_ref = LUA_NOREF; // Update variable since reference is no longer valid *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
} }
} }

View File

@ -8,33 +8,33 @@
* The SDK software timer API executes in a task. The priority of this task in relation to the * 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). * 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` * 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 * 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. * 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 * The timers in this list are organized in an ascending order starting with the timer
* with the lowest timer_expire. * with the lowest timer_expire.
* *
* When a timer expires that has a timer_period greater than 0, timer_expire is changed to * When a timer expires that has a timer_period greater than 0, timer_expire is changed to current
* current FRC2 + timer_period, then the timer is inserted back in to the list in the correct position. * 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 SUSPEND API INFO:
* *
* Timer suspension is achieved by first finding any non-SDK timers by comparing the timer function callback pointer * Timer suspension is achieved by first finding any non-SDK timers by comparing the timer function
* of each timer in "timer_list" to a list of registered timer callback pointers stored in the Lua registry. * callback pointer of each timer in "timer_list" to a list of registered timer callback pointers
* If a timer with a corresponding registered callback pointer is found, the timer's timer_expire field is is compared * stored in the Lua registry. If a timer with a corresponding registered callback pointer is found,
* to the current FRC2 count and the difference is saved along with the other timer parameters to temporary variables. * the timer's timer_expire field is is compared to the current FRC2 count and the difference is
* The timer is then disarmed and the parameters are copied back, the timer pointer is then * saved along with the other timer parameters to temporary variables. The timer is then disarmed
* added to a separate linked list of which the head pointer is stored as a lightuserdata in the lua registry. * 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. * Resuming the timers is achieved by first retrieving the lightuserdata holding the suspended timer
* Then, starting with the beginning of the list the current FRC2 count is added back to the timer's timer_expire, then * list head pointer. Then, starting with the beginning of the list the current FRC2 count is added
* the timer is manually added back to "timer_list" in an ascending order. * back to the timer's timer_expire, then the timer is manually added back to "timer_list" in an
* Once there are no more suspended timers, the function returns * ascending order. Once there are no more suspended timers, the function returns.
* *
* *
*/ */
@ -57,17 +57,24 @@
#define SWTMR_DEBUG #define SWTMR_DEBUG
#endif #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 #ifdef SWTMR_DEBUG
#define SWTMR_DBG(fmt, ...) dbg_printf("\n SWTMR_DBG(%s): "fmt"\n", __FUNCTION__, ##__VA_ARGS__) #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 CB_LIST_STR "timer_cb_ptrs"
#define SUSP_LIST_STR "suspended_tmr_LL_head" #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 #else
#define SWTMR_DBG(...) #define SWTMR_DBG(...)
#define L_REGISTRY LUA_REGISTRYINDEX
#define CB_LIST_STR "cb" #define CB_LIST_STR "cb"
#define SUSP_LIST_STR "st" #define SUSP_LIST_STR "st"
#define get_swtmr_registry(L) lua_pushlightuserdata(L, &register_queue); \
lua_rawget(L, LUA_REGISTRYINDEX)
#define set_swtmr_registry(L) lua_pushlightuserdata(L, &register_queue); \
lua_insert(L, -2); \
lua_rawset(L, LUA_REGISTRYINDEX)
#endif #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 add_to_reg_queue(void* timer_cb_ptr, uint8 suspend_policy);
static void process_cb_register_queue(task_param_t param, uint8 priority); 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, &register_queue);
#endif
#include <pm/swtimer.h> #include <pm/swtimer.h>
void swtmr_suspend_timers(){ void swtmr_suspend_timers(){
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
//get swtimer table //get swtimer table
push_swtmr_registry_key(L); get_swtmr_registry(L);
lua_rawget(L, L_REGISTRY); if(!lua_istable(L, -1)) {lua_pop(L, 1); return;}
//get cb_list table //get cb_list table
lua_pushstring(L, CB_LIST_STR); lua_pushstring(L, CB_LIST_STR);
lua_rawget(L, -2); lua_rawget(L, -2);
//check for existence of the swtimer table and the cb_list table, return if not found //check for existence of the cb_list table, return if not found
if(!lua_istable(L, -2) || !lua_istable(L, -1)){ if(!lua_istable(L, -1)) {lua_pop(L, 2); return;}
// not necessarily an error maybe there are legitimately no timers to suspend
lua_pop(L, 2);
return;
}
os_timer_t* suspended_timer_list_head = NULL; os_timer_t* suspended_timer_list_head = NULL;
os_timer_t* suspended_timer_list_tail = NULL; os_timer_t* suspended_timer_list_tail = NULL;
@ -168,10 +164,10 @@ void swtmr_suspend_timers(){
uint32 period_temp = 0; uint32 period_temp = 0;
void* arg_temp = NULL; void* arg_temp = NULL;
/* In this section, the SDK's timer_list is traversed to find any timers that have a registered callback pointer. /* In this section, the SDK's timer_list is traversed to find any timers that have a registered
* If a registered callback is found, the timer is suspended by saving the difference * callback pointer. If a registered callback is found, the timer is suspended by saving the
* between frc2_count and timer_expire then the timer is disarmed and placed into suspended_timer_list * difference between frc2_count and timer_expire then the timer is disarmed and placed into
* so it can later be resumed. * suspended_timer_list so it can later be resumed.
*/ */
while(timer_ptr != NULL){ while(timer_ptr != NULL){
os_timer_t* next_timer = (os_timer_t*)0xffffffff; os_timer_t* next_timer = (os_timer_t*)0xffffffff;
@ -190,7 +186,8 @@ void swtmr_suspend_timers(){
arg_temp = timer_ptr->timer_arg; arg_temp = timer_ptr->timer_arg;
if(timer_ptr->timer_period == 0 && cb_reg_array[i]->suspend_policy == SWTIMER_RESTART){ 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; cb_reg_array[i]->suspend_policy = SWTIMER_RESUME;
} }
@ -260,19 +257,15 @@ void swtmr_resume_timers(){
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
//get swtimer table //get swtimer table
push_swtmr_registry_key(L); get_swtmr_registry(L);
lua_rawget(L, L_REGISTRY); if(!lua_istable(L, -1)) {lua_pop(L, 1); return;}
//get suspended_timer_list lightuserdata //get suspended_timer_list lightuserdata
lua_pushstring(L, SUSP_LIST_STR); lua_pushstring(L, SUSP_LIST_STR);
lua_rawget(L, -2); lua_rawget(L, -2);
//check for existence of swtimer table and the suspended_timer_list pointer userdata, return if not found //check for existence of the suspended_timer_list pointer userdata, return if not found
if(!lua_istable(L, -2) || !lua_isuserdata(L, -1)){ if(!lua_isuserdata(L, -1)) {lua_pop(L, 2); return;}
// not necessarily an error maybe there are legitimately no timers to resume
lua_pop(L, 2);
return;
}
os_timer_t* suspended_timer_list_ptr = lua_touserdata(L, -1); os_timer_t* suspended_timer_list_ptr = lua_touserdata(L, -1);
lua_pop(L, 1); //pop suspended timer list userdata from stack 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){ void swtmr_cb_register(void* timer_cb_ptr, uint8 suspend_policy){
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
if(!L){ if(!L){
//Lua has not started yet, therefore L_REGISTRY is not available. // If Lua has not started yet, then add timer cb to queue for later processing after Lua has started
//add timer cb to queue for later processing after Lua has started
add_to_reg_queue(timer_cb_ptr, suspend_policy); add_to_reg_queue(timer_cb_ptr, suspend_policy);
return; return;
} }
if(timer_cb_ptr){ if(timer_cb_ptr){
size_t cb_list_last_idx = 0; size_t cb_list_last_idx = 0;
push_swtmr_registry_key(L); get_swtmr_registry(L);
lua_rawget(L, L_REGISTRY);
if(!lua_istable(L, -1)){ 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_pop(L, 1);
lua_newtable(L);//push new table for swtmr.timer_cb_list lua_newtable(L);
// add swtimer table to L_REGISTRY lua_pushvalue(L, -1);
push_swtmr_registry_key(L); set_swtmr_registry(L);
lua_pushvalue(L, -2);
lua_rawset(L, L_REGISTRY);
} }
lua_pushstring(L, CB_LIST_STR); 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 #ifdef SWTMR_DEBUG
int print_timer_list(lua_State* L){ int print_timer_list(lua_State* L){
push_swtmr_registry_key(L); get_swtmr_registry(L);
lua_rawget(L, L_REGISTRY); if(!lua_istable(L, -1)) {lua_pop(L, 1); return 0;}
lua_pushstring(L, CB_LIST_STR);
lua_rawget(L, -2); lua_pushstring(L, CB_LIST_STR);
if(!lua_istable(L, -2) || !lua_istable(L, -1)){ lua_rawget(L, -2);
lua_pop(L, 2); if(!lua_istable(L, -1)) {lua_pop(L, 2); return 0;}
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_pop(L, 1);
lua_pushstring(L, SUSP_LIST_STR); size_t registered_cb_qty = lua_objlen(L, -1);
lua_rawget(L, -3); 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)){ if(lua_isuserdata(L, -1)){
suspended_timer_list_head = suspended_timer_list_tail = lua_touserdata(L, -1); cb_reg_array[index] = 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++;
} }
lua_pop(L, 1); lua_pop(L, 1);
index++;
}
lua_pop(L, 1);
os_timer_t* timer_list_ptr = timer_list; 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){ int print_susp_timer_list(lua_State* L){
push_swtmr_registry_key(L); get_swtmr_registry(L);
lua_rawget(L, L_REGISTRY);
if(!lua_istable(L, -1)){ if(!lua_istable(L, -1)){
return luaL_error(L, "swtmr table not found!"); 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); os_timer_t* susp_timer_list_ptr = lua_touserdata(L, -1);
dbg_printf("\n\tsuspended_timer_list:\n"); dbg_printf("\n\tsuspended_timer_list:\n");
while(susp_timer_list_ptr != NULL){ 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; susp_timer_list_ptr = susp_timer_list_ptr->timer_next;
} }
return 0; return 0;
@ -542,5 +530,5 @@ LROT_END(test_swtimer_debug, NULL, 0)
NODEMCU_MODULE(SWTMR_DBG, "SWTMR_DBG", test_swtimer_debug, NULL); NODEMCU_MODULE(SWTMR_DBG, "SWTMR_DBG", test_swtimer_debug, NULL);
#endif #endif /* SWTMR_DEBUG */

View File

@ -22,4 +22,5 @@
// Reduce the chance of returning disk full // Reduce the chance of returning disk full
#define SPIFFS_GC_MAX_RUNS 256 #define SPIFFS_GC_MAX_RUNS 256
#define SPIFFS_SECURE_ERASE 0
#endif #endif

View File

@ -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) { if (cfg->phys_size < MIN_BLOCKS_FS * LOG_BLOCK_SIZE_SMALL_FS) {
return FALSE; 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; cfg->log_block_size = LOG_BLOCK_SIZE_SMALL_FS;
} else { } else {
cfg->log_block_size = LOG_BLOCK_SIZE; cfg->log_block_size = LOG_BLOCK_SIZE;

View File

@ -889,6 +889,16 @@ s32_t spiffs_page_delete(
fs->stats_p_deleted++; fs->stats_p_deleted++;
fs->stats_p_allocated--; 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 // mark deleted in source page
u8_t flags = 0xff; u8_t flags = 0xff;
#if SPIFFS_NO_BLIND_WRITES #if SPIFFS_NO_BLIND_WRITES
@ -2030,7 +2040,7 @@ s32_t spiffs_object_read(
// remaining data in page // remaining data in page
len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs))); len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
// remaining data in file // 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, 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)))); (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) { if (len_to_read <= 0) {

View File

@ -262,8 +262,8 @@
#define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0) #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) #define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0)
#else #else
#define SPIFFS_FH_OFFS(fs, fh) (fh) #define SPIFFS_FH_OFFS(fs, fh) ((spiffs_file)(fh))
#define SPIFFS_FH_UNOFFS(fs, fh) (fh) #define SPIFFS_FH_UNOFFS(fs, fh) ((spiffs_file)(fh))
#endif #endif
@ -476,9 +476,6 @@ typedef struct {
// object structs // object structs
#ifdef _MSC_VER
#pragma pack ( push, 1 )
#endif
// page header, part of each page except object lookup pages // page header, part of each page except object lookup pages
// NB: this is always aligned when the data page is an object index, // 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 typedef struct SPIFFS_PACKED
#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES #if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
#ifdef _MSC_VER #ifdef _MSC_VER
//Note: the following needs to track the sizeof(spiffs_page_ix), which is defined in spiffs_config.h __declspec( align( 2 ) ) // must track sizeof(spiffs_page_ix) in spiffs_config.h
__declspec( align( 2 ) )
#else #else
__attribute(( aligned(sizeof(spiffs_page_ix)) )) __attribute(( aligned(sizeof(spiffs_page_ix)) ))
#endif #endif
#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))]; u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
} spiffs_page_object_ix; } spiffs_page_object_ix;
#ifdef _MSC_VER
#pragma pack ( pop )
#endif
// callback func for object lookup visitor // 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, 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); const void *user_const_p, void *user_var_p);

View File

@ -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_State *L = lua_getstate();
lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref ); lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref );
lua_pushnil( L ); lua_pushnil( L );
lua_call( L, 1, 0 ); luaL_pcallx( L, 1, 0 );
} }
// and note ongoing framebuffer update // and note ongoing framebuffer update
ext_u8g2->overlay.fb_update_ongoing = 1; 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_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref );
lua_pushlstring( L, (const char *)fbrle_line, fbrle_line_size ); lua_pushlstring( L, (const char *)fbrle_line, fbrle_line_size );
lua_call( L, 1, 0 ); luaL_pcallx( L, 1, 0 );
} }
} }

View File

@ -1,4 +1,4 @@
local gpio, bit = gpio, bit local gpio, bit = gpio, bit --luacheck: read globals gpio bit
return function(bus_args) return function(bus_args)
local rs = bus_args.rs or 0 local rs = bus_args.rs or 0

View File

@ -1,4 +1,4 @@
local gpio, bit = gpio, bit local gpio, bit = gpio, bit --luacheck: read globals gpio bit
return function(bus_args) return function(bus_args)
local rs = bus_args.rs or 0 local rs = bus_args.rs or 0

View File

@ -1,4 +1,4 @@
local i2c, bit = i2c, bit local i2c, bit = i2c, bit --luacheck: read globals i2c bit
return function(bus_args) return function(bus_args)
local busid = bus_args.id or 0 local busid = bus_args.id or 0

View File

@ -1,4 +1,4 @@
local bit = bit local bit = bit --luacheck: read globals bit
-- metatable -- metatable
local LiquidCrystal = {} local LiquidCrystal = {}
LiquidCrystal.__index = LiquidCrystal LiquidCrystal.__index = LiquidCrystal