diff --git a/radio/src/Makefile b/radio/src/Makefile index 9d1e9627d..6e1c66853 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -289,6 +289,10 @@ USB = JOYSTICK # NO - normal behaviour, show real channel values CHANNELS_MONITOR_INV_HIDE = NO +# Use newlib-nano +# Values = NO, YES +NANO = YES + #------- END BUILD OPTIONS --------------------------- # Define programs and commands. @@ -1116,6 +1120,12 @@ MATH_LIB = -lm LDFLAGS = -Wl,-Map=$(TARGET).map,--cref LDFLAGS += $(MATH_LIB) +ifeq ($(NANO), YES) + # use newlib-nano for linking + NEWLIB_NANO_FLAGS = --specs=nano.specs -u _printf_float + CPPDEFS += -DNANO +endif + # Define Messages # English MSG_BEGIN = -------- begin -------- @@ -1324,7 +1334,7 @@ FOXLIB=-L/usr/local/lib \ -Wl,-rpath,$(FOXPATH)/src/.libs simu: $(LUADEP) stamp_header $(BOARDSRC) $(CPPSRC) Makefile simu.cpp targets/simu/simpgmspace.cpp *.h tra lbm eeprom.bin - g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) $(LUASRC) targets/simu/simpgmspace.cpp -MD -DSIMU -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions + g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) $(LUASRC) targets/simu/simpgmspace.cpp -MD -DSIMU -DLUA_USE_APICHECK -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions eeprom.bin: dd if=/dev/zero of=$@ bs=1 count=2048 @@ -1390,7 +1400,7 @@ OBJS = $(TMP:.s=.o) @echo @echo $(MSG_COMPILING) $@ $(CC) $(ARMCPPFLAGS) $< -o allsrc.o - $(CC) $(OBJS) allsrc.o -mcpu=cortex-m3 -mthumb -nostartfiles -lm -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref,--no-warn-mismatch,--gc-sections -o $@ + $(CC) $(OBJS) allsrc.o -mcpu=cortex-m3 -mthumb -nostartfiles -lm -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref,--no-warn-mismatch,--gc-sections $(NEWLIB_NANO_FLAGS) -o $@ endif # Target: clean project. diff --git a/radio/src/lua.cpp b/radio/src/lua.cpp index cbac308a2..f101760c6 100644 --- a/radio/src/lua.cpp +++ b/radio/src/lua.cpp @@ -76,6 +76,19 @@ uint16_t maxLuaDuration = 0; #define SCRIPTS_MAX_HEAP 50 #define SET_LUA_INSTRUCTIONS_COUNT(x) (instructionsPercent=0, lua_sethook(L, hook, LUA_MASKCOUNT, x)) +struct our_longjmp * global_lj = 0; + +/* custom panic handler */ +static int custom_lua_atpanic(lua_State *lua) +{ + TRACE("PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1)); + if (global_lj) { + longjmp(global_lj->b, 1); + /* will never return */ + } + return 0; +} + static int instructionsPercent = 0; void hook(lua_State* L, lua_Debug *ar) { @@ -268,9 +281,10 @@ static int luaPlayFile(lua_State *L) strncpy(str, filename, AUDIO_FILENAME_MAXLEN - (str-file)); file[AUDIO_FILENAME_MAXLEN] = 0; PLAY_FILE(file, 0, 0); - return 0; } - PLAY_FILE(filename, 0, 0); + else { + PLAY_FILE(filename, 0, 0); + } return 0; } @@ -1358,14 +1372,29 @@ static const luaL_Reg lcdLib[] = { { NULL, NULL } /* sentinel */ }; -void luaInit() +void luaDisable() +{ + POPUP_WARNING("Lua disabled!"); + luaState = INTERPRETER_PANIC; +} + +void luaClose() { if (L) { - lua_close(L); + PROTECT_LUA() { + lua_close(L); // this should not panic, but we make sure anyway + } + else { + // we can only disable Lua for the rest of the session + luaDisable(); + } + UNPROTECT_LUA(); + L = NULL; } +} - L = luaL_newstate(); - +void luaRegisterAll() +{ // Init lua luaL_openlibs(L); @@ -1441,13 +1470,50 @@ void luaInit() lua_registerint(L, "TIMEHOUR", TIMEHOUR); } +void luaInit() +{ + luaClose(); + if (luaState != INTERPRETER_PANIC) { + L = luaL_newstate(); + if (L) { + // install our panic handler + lua_atpanic(L, &custom_lua_atpanic); + + // protect libs and constants registration + PROTECT_LUA() { + luaRegisterAll(); + } + else { + // if we got panic during registration + // we disable Lua for this session + luaDisable(); + } + UNPROTECT_LUA(); + } + else { + /* log error and return */ + luaDisable(); + } + } +} + void luaFree(ScriptInternalData & sid) { - if (sid.run) { - luaL_unref(L, LUA_REGISTRYINDEX, sid.run); - sid.run = 0; + PROTECT_LUA() { + if (sid.run) { + luaL_unref(L, LUA_REGISTRYINDEX, sid.run); + sid.run = 0; + } + if (sid.background) { + luaL_unref(L, LUA_REGISTRYINDEX, sid.background); + sid.background = 0; + } lua_gc(L, LUA_GCCOLLECT, 0); } + else { + luaDisable(); + } + UNPROTECT_LUA(); } int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs * sio=NULL) @@ -1461,47 +1527,55 @@ int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS); - if (luaL_loadfile(L, filename) == 0 && - lua_pcall(L, 0, 1, 0) == 0 && - lua_istable(L, -1)) { + PROTECT_LUA() { + if (luaL_loadfile(L, filename) == 0 && + lua_pcall(L, 0, 1, 0) == 0 && + lua_istable(L, -1)) { - luaL_checktype(L, -1, LUA_TTABLE); + luaL_checktype(L, -1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - const char *key = lua_tostring(L, -2); - if (!strcmp(key, "init")) { - init = luaL_ref(L, LUA_REGISTRYINDEX); - lua_pushnil(L); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + const char *key = lua_tostring(L, -2); + if (!strcmp(key, "init")) { + init = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pushnil(L); + } + else if (!strcmp(key, "run")) { + sid.run = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pushnil(L); + } + else if (!strcmp(key, "background")) { + sid.background = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pushnil(L); + } + else if (sio && !strcmp(key, "input")) { + luaGetInputs(*sio); + } + else if (sio && !strcmp(key, "output")) { + luaGetOutputs(*sio); + } } - else if (!strcmp(key, "run")) { - sid.run = luaL_ref(L, LUA_REGISTRYINDEX); - lua_pushnil(L); - } - else if (!strcmp(key, "background")) { - sid.background = luaL_ref(L, LUA_REGISTRYINDEX); - lua_pushnil(L); - } - else if (sio && !strcmp(key, "input")) { - luaGetInputs(*sio); - } - else if (sio && !strcmp(key, "output")) { - luaGetOutputs(*sio); + + if (init) { + lua_rawgeti(L, LUA_REGISTRYINDEX, init); + if (lua_pcall(L, 0, 0, 0) != 0) { + TRACE("Error in script %s init: %s", filename, lua_tostring(L, -1)); + sid.state = SCRIPT_SYNTAX_ERROR; + } + luaL_unref(L, LUA_REGISTRYINDEX, init); + lua_gc(L, LUA_GCCOLLECT, 0); } } - - if (init) { - lua_rawgeti(L, LUA_REGISTRYINDEX, init); - luaL_unref(L, LUA_REGISTRYINDEX, init); - if (lua_pcall(L, 0, 0, 0) != 0) { - TRACE("Error in script %s init: %s", filename, lua_tostring(L, -1)); - sid.state = SCRIPT_SYNTAX_ERROR; - } + else { + TRACE("Error in script %s: %s", filename, lua_tostring(L, -1)); + sid.state = SCRIPT_SYNTAX_ERROR; } } else { - TRACE("Error in script %s: %s", filename, lua_tostring(L, -1)); - sid.state = SCRIPT_SYNTAX_ERROR; + TRACE("Panic in script %s: %s", filename, lua_tostring(L, -1)); + sid.state = SCRIPT_PANIC; } + UNPROTECT_LUA(); if (sid.state != SCRIPT_OK) { luaFree(sid); @@ -1663,6 +1737,9 @@ void luaError(uint8_t error) case SCRIPT_KILLED: msg = "Script killed"; break; + case SCRIPT_PANIC: + msg = "Script panic"; + break; } POPUP_WARNING(msg); } @@ -1670,22 +1747,198 @@ void luaError(uint8_t error) void luaExec(const char *filename) { - LUA_RESET(); + luaInit(); + standaloneScript.state = SCRIPT_NOFILE; int result = luaLoad(filename, standaloneScript); // TODO the same with run ... if (result == SCRIPT_OK) { - luaState = LUASTATE_STANDALONE_SCRIPT_RUNNING; + luaState = INTERPRETER_RUNNING_STANDALONE_SCRIPT; } else { luaError(result); + luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS; } } +void luaDoOneRunStandalone(uint8_t evt) +{ + static uint8_t luaDisplayStatistics = false; + + if (standaloneScript.state == SCRIPT_OK && standaloneScript.run) { + SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS); + lua_rawgeti(L, LUA_REGISTRYINDEX, standaloneScript.run); + lua_pushinteger(L, evt); + if (lua_pcall(L, 1, 1, 0) == 0) { + if (!lua_isnumber(L, -1)) { + if (instructionsPercent > 100) { + TRACE("Script killed"); + standaloneScript.state = SCRIPT_KILLED; + luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS; + } + else if (lua_isstring(L, -1)) { + char nextScript[_MAX_LFN+1]; + strncpy(nextScript, lua_tostring(L, -1), _MAX_LFN); + nextScript[_MAX_LFN] = '\0'; + luaExec(nextScript); + } + else { + TRACE("Script error"); + standaloneScript.state = SCRIPT_SYNTAX_ERROR; + luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS; + } + } + else { + int scriptResult = lua_tointeger(L, -1); + lua_pop(L, 1); /* pop returned value */ + if (scriptResult != 0) { + TRACE("Script finished with status %d", scriptResult); + standaloneScript.state = SCRIPT_NOFILE; + luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS; + } + else if (luaDisplayStatistics) { + lcd_hline(0, 7*FH-1, lcdLastPos+FW, ERASE); + lcd_puts(0, 7*FH, "GV Use: "); + lcd_outdezAtt(lcdLastPos, 7*FH, luaGetMemUsed(), LEFT); + lcd_putc(lcdLastPos, 7*FH, 'b'); + lcd_hline(0, 7*FH-2, lcdLastPos+FW, FORCE); + lcd_vlineStip(lcdLastPos+FW, 7*FH-2, FH+2, SOLID, FORCE); + } + } + } + else { + TRACE("Script error: %s", lua_tostring(L, -1)); + standaloneScript.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR); + luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS; + } + + if (standaloneScript.state != SCRIPT_OK) { + luaError(standaloneScript.state); + luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS; + } + + if (evt == EVT_KEY_LONG(KEY_EXIT)) { + TRACE("Script force exit"); + killEvents(evt); + standaloneScript.state = SCRIPT_NOFILE; + luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS; + } + else if (evt == EVT_KEY_LONG(KEY_MENU)) { + killEvents(evt); + luaDisplayStatistics = !luaDisplayStatistics; + } + } +} + +void luaDoOneRunPermanentScript(uint8_t evt, int i) +{ + ScriptInternalData & sid = scriptInternalData[i]; + if (sid.state == SCRIPT_OK) { + SET_LUA_INSTRUCTIONS_COUNT(PERMANENT_SCRIPTS_MAX_INSTRUCTIONS); + int inputsCount = 0; +#if defined(SIMU) || defined(DEBUG) + const char *filename; +#endif + ScriptInputsOutputs * sio = NULL; + if (sid.reference >= SCRIPT_MIX_FIRST && sid.reference <= SCRIPT_MIX_LAST) { + ScriptData & sd = g_model.scriptsData[sid.reference-SCRIPT_MIX_FIRST]; + sio = &scriptInputsOutputs[sid.reference-SCRIPT_MIX_FIRST]; + inputsCount = sio->inputsCount; +#if defined(SIMU) || defined(DEBUG) + filename = sd.file; +#endif + lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); + for (int j=0; jinputsCount; j++) { + if (sio->inputs[j].type == 1) + luaGetValueAndPush((uint8_t)sd.inputs[j]); + else + lua_pushinteger(L, sd.inputs[j] + sio->inputs[j].def); + } + } + else if (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST) { + CustomFnData & fn = g_model.funcSw[sid.reference-SCRIPT_FUNC_FIRST]; + if (!getSwitch(fn.swtch)) { + return; + } +#if defined(SIMU) || defined(DEBUG) + filename = fn.play.name; +#endif + lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); + } + else { +#if defined(SIMU) || defined(DEBUG) + filename = "[telem]"; +#endif + if (g_menuStack[0]==menuTelemetryFrsky && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view) { + lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); + lua_pushinteger(L, evt); + inputsCount = 1; + } + else if (sid.background) { + lua_rawgeti(L, LUA_REGISTRYINDEX, sid.background); + } + else { + return; + } + } + if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) { + if (sio) { + for (int j=sio->outputsCount-1; j>=0; j--) { + if (!lua_isnumber(L, -1)) { + sid.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR); + TRACE("Script %8s disabled", filename); + break; + } + sio->outputs[j].value = lua_tointeger(L, -1); + lua_pop(L, 1); + } + } + } + else { + if (instructionsPercent > 100) { + TRACE("Script %8s killed", filename); + sid.state = SCRIPT_KILLED; + } + else { + TRACE("Script %8s error: %s", filename, lua_tostring(L, -1)); + sid.state = SCRIPT_SYNTAX_ERROR; + } + } + + if (sid.state != SCRIPT_OK) { + luaFree(sid); + } + else { + if (instructionsPercent > sid.instructions) { + sid.instructions = instructionsPercent; + } + } + } +} + +void luaDoGc() +{ + PROTECT_LUA() { + lua_gc(L, LUA_GCSTEP /*LUA_GCCOLLECT*/, 0); // LUA_GCSTEP is enough +#if defined(SIMU) || defined(DEBUG) + static int lastgc = 0; + int gc = luaGetMemUsed(); + if (gc != lastgc) { + lastgc = gc; + TRACE("GC Use: %dbytes", gc); + } +#endif + } + else { + // we disable Lua for the rest of the session + luaDisable(); + } + UNPROTECT_LUA(); +} + void luaTask(uint8_t evt) { lcd_locked = false; - static uint8_t luaDisplayStatistics = false; uint32_t t0 = get_tmr10ms(); static uint32_t lastLuaTime = 0; @@ -1695,176 +1948,40 @@ void luaTask(uint8_t evt) maxLuaInterval = interval; } - if (luaState & LUASTATE_STANDALONE_SCRIPT_RUNNING) { - // standalone script - if (standaloneScript.state == SCRIPT_OK && standaloneScript.run) { - SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS); - lua_rawgeti(L, LUA_REGISTRYINDEX, standaloneScript.run); - lua_pushinteger(L, evt); - if (lua_pcall(L, 1, 1, 0) == 0) { - if (!lua_isnumber(L, -1)) { - if (instructionsPercent > 100) { - TRACE("Script killed"); - standaloneScript.state = SCRIPT_KILLED; - luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; - } - else if (lua_isstring(L, -1)) { - char nextScript[_MAX_LFN+1]; - strncpy(nextScript, lua_tostring(L, -1), _MAX_LFN); - nextScript[_MAX_LFN] = '\0'; - luaExec(nextScript); - } - else { - TRACE("Script error"); - standaloneScript.state = SCRIPT_SYNTAX_ERROR; - luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; - } - } - else { - int scriptResult = lua_tointeger(L, -1); - lua_pop(L, 1); /* pop returned value */ - if (scriptResult != 0) { - TRACE("Script finished with status %d", scriptResult); - standaloneScript.state = SCRIPT_NOFILE; - luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; - } - else if (luaDisplayStatistics) { - int gc = 1000*lua_gc(L, LUA_GCCOUNT, 0) + lua_gc(L, LUA_GCCOUNTB, 0); - lcd_hline(0, 7*FH-1, lcdLastPos+FW, ERASE); - lcd_puts(0, 7*FH, "GV Use: "); - lcd_outdezAtt(lcdLastPos, 7*FH, gc, LEFT); - lcd_putc(lcdLastPos, 7*FH, 'b'); - lcd_hline(0, 7*FH-2, lcdLastPos+FW, FORCE); - lcd_vlineStip(lcdLastPos+FW, 7*FH-2, FH+2, SOLID, FORCE); - } - } - } - else { - TRACE("Script error: %s", lua_tostring(L, -1)); - standaloneScript.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR); - luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; - } - - if (standaloneScript.state != SCRIPT_OK) { - luaError(standaloneScript.state); - } - - if (evt == EVT_KEY_LONG(KEY_EXIT)) { - TRACE("Script force exit"); - killEvents(evt); - standaloneScript.state = SCRIPT_NOFILE; - luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; - } - else if (evt == EVT_KEY_LONG(KEY_MENU)) { - killEvents(evt); - luaDisplayStatistics = !luaDisplayStatistics; - } + if (luaState & INTERPRETER_RUNNING_STANDALONE_SCRIPT) { + PROTECT_LUA() { + luaDoOneRunStandalone(evt); } + else { + POPUP_WARNING("Script Panic!"); + luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS; + } + UNPROTECT_LUA(); } else { // model scripts - if (luaState & LUASTATE_RELOAD_MODEL_SCRIPTS) { + if (luaState & INTERPRETER_RELOAD_PERMANENT_SCRIPTS) { luaState = 0; - LUA_RESET(); + luaInit(); + if (!L) return; luaLoadPermanentScripts(); } for (int i=0; i= SCRIPT_MIX_FIRST && sid.reference <= SCRIPT_MIX_LAST) { - ScriptData & sd = g_model.scriptsData[sid.reference-SCRIPT_MIX_FIRST]; - sio = &scriptInputsOutputs[sid.reference-SCRIPT_MIX_FIRST]; - inputsCount = sio->inputsCount; -#if defined(SIMU) || defined(DEBUG) - filename = sd.file; -#endif - lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); - for (int j=0; jinputsCount; j++) { - if (sio->inputs[j].type == 1) - luaGetValueAndPush((uint8_t)sd.inputs[j]); - else - lua_pushinteger(L, sd.inputs[j] + sio->inputs[j].def); - } - } - else if (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST) { - CustomFnData & fn = g_model.funcSw[sid.reference-SCRIPT_FUNC_FIRST]; - if (!getSwitch(fn.swtch)) { - continue; - } -#if defined(SIMU) || defined(DEBUG) - filename = fn.play.name; -#endif - lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); - } - else { -#if defined(SIMU) || defined(DEBUG) - filename = "[telem]"; -#endif - if (g_menuStack[0]==menuTelemetryFrsky && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view) { - lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); - lua_pushinteger(L, evt); - inputsCount = 1; - } - else if (sid.background) { - lua_rawgeti(L, LUA_REGISTRYINDEX, sid.background); - } - else { - continue; - } - } - if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) { - if (sio) { - for (int j=sio->outputsCount-1; j>=0; j--) { - if (!lua_isnumber(L, -1)) { - sid.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR); - TRACE("Script %8s disabled", filename); - break; - } - sio->outputs[j].value = lua_tointeger(L, -1); - lua_pop(L, 1); - } - } - } - else { - if (instructionsPercent > 100) { - TRACE("Script %8s killed", filename); - sid.state = SCRIPT_KILLED; - } - else { - TRACE("Script %8s error: %s", filename, lua_tostring(L, -1)); - sid.state = SCRIPT_SYNTAX_ERROR; - } - } - - if (sid.state != SCRIPT_OK) { - luaFree(sid); - } - else { - if (instructionsPercent > sid.instructions) { - sid.instructions = instructionsPercent; - } - } + PROTECT_LUA() { + luaDoOneRunPermanentScript(evt, i); } + else { + // we disable this script for the rest of the session + ScriptInternalData & sid = scriptInternalData[i]; + sid.state = SCRIPT_PANIC; + luaFree(sid); + } + UNPROTECT_LUA(); } } - lua_gc(L, LUA_GCCOLLECT, 0); - -#if defined(SIMU) || defined(DEBUG) - static int lastgc = 0; - int gc = luaGetMemUsed(); - if (gc != lastgc) { - lastgc = gc; - TRACE("GC Use: %dbytes", gc); - } -#endif + luaDoGc(); t0 = get_tmr10ms() - t0; if (t0 > maxLuaDuration) { @@ -1874,5 +1991,5 @@ void luaTask(uint8_t evt) int luaGetMemUsed() { - return 1000*lua_gc(L, LUA_GCCOUNT, 0) + lua_gc(L, LUA_GCCOUNTB, 0); + return (lua_gc(L, LUA_GCCOUNT, 0) << 10) + lua_gc(L, LUA_GCCOUNTB, 0); } diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 22525814f..e3db50581 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2505,6 +2505,10 @@ void opentxClose() // TODO needed? telemetryEnd(); #endif +#if defined(LUA) + luaClose(); +#endif + #if defined(SDCARD) closeLogs(); sdDone(); @@ -3352,8 +3356,6 @@ void opentxInit(OPENTX_INIT_ARGS) rtcInit(); #endif - LUA_INIT(); - if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on if (UNEXPECTED_SHUTDOWN()) { diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 0ebf25d19..7f98f5a8b 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1475,7 +1475,8 @@ enum AUDIO_SOUNDS { SCRIPT_OK, SCRIPT_NOFILE, SCRIPT_SYNTAX_ERROR, - SCRIPT_KILLED + SCRIPT_PANIC, + SCRIPT_KILLED, }; enum ScriptReference { SCRIPT_MIX_FIRST, @@ -1498,13 +1499,18 @@ enum AUDIO_SOUNDS { uint8_t outputsCount; ScriptOutput outputs[MAX_SCRIPT_OUTPUTS]; }; - #define LUASTATE_STANDALONE_SCRIPT_RUNNING 1 - #define LUASTATE_RELOAD_MODEL_SCRIPTS 2 + enum InterpreterState { + INTERPRETER_RUNNING_PERMANENT_SCRIPTS, + INTERPRETER_RUNNING_STANDALONE_SCRIPT, + INTERPRETER_RELOAD_PERMANENT_SCRIPTS, + INTERPRETER_PANIC, + }; extern uint8_t luaState; extern uint8_t luaScriptsCount; extern ScriptInternalData standaloneScript; extern ScriptInternalData scriptInternalData[MAX_SCRIPTS]; extern ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS]; + void luaClose(); void luaInit(); void luaTask(uint8_t evt); void luaExec(const char *filename); @@ -1513,13 +1519,23 @@ enum AUDIO_SOUNDS { int luaGetMemUsed(); #define luaGetCpuUsed(idx) scriptInternalData[idx].instructions bool isTelemetryScriptAvailable(uint8_t index); - #define LUA_INIT() - #define LUA_RESET() luaInit() - #define LUA_LOAD_MODEL_SCRIPTS() luaState |= LUASTATE_RELOAD_MODEL_SCRIPTS - #define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= LUASTATE_RELOAD_MODEL_SCRIPTS + #define LUA_LOAD_MODEL_SCRIPTS() luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS + #define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS + + // Lua PROTECT/UNPROTECT + #include + struct our_longjmp { + struct our_longjmp *previous; + jmp_buf b; + volatile int status; /* error code */ + }; + extern struct our_longjmp * global_lj; + #define PROTECT_LUA() { struct our_longjmp lj; \ + lj.previous = global_lj; /* chain new error handler */ \ + global_lj = &lj; \ + if (setjmp(lj.b) == 0) + #define UNPROTECT_LUA() global_lj = lj.previous; } /* restore old error handler */ #else - #define LUA_INIT() - #define LUA_RESET() #define LUA_LOAD_MODEL_SCRIPTS() #define LUA_LOAD_MODEL_SCRIPT(idx) #endif diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index d69992eb4..51575164b 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -309,8 +309,6 @@ void *main_thread(void *) if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on - LUA_INIT(); - if (main_thread_running == 1) { opentxStart(); } diff --git a/radio/src/tasks_arm.cpp b/radio/src/tasks_arm.cpp index 219776b49..3c9be1f81 100755 --- a/radio/src/tasks_arm.cpp +++ b/radio/src/tasks_arm.cpp @@ -99,6 +99,13 @@ uint32_t stack_free(uint32_t tid) stack = audioStack; size = AUDIO_STACK_SIZE; break; +#if defined(PCBTARANIS) + case 255: + // main stack + stack = (OS_STK *)&_main_stack_start; + size = ((unsigned char *)&_estack - (unsigned char *)&_main_stack_start) / 4; + break; +#endif default: return 0; } @@ -107,7 +114,7 @@ uint32_t stack_free(uint32_t tid) for (; ib, 1); + } + else { + //we should come here + passed = true; + } + UNPROTECT_LUA(); + } + else { + // an not here + // TRACE("testLuaProtection: test 1 FAILED"); + FAIL() << "Failed test 1"; + } + UNPROTECT_LUA() + + EXPECT_EQ(passed, true); + + passed = false; + + PROTECT_LUA() { + PROTECT_LUA() { + int a = 5; + a = a; // avoids the warning + } + else { + //we should not come here + // TRACE("testLuaProtection: test 2 FAILED"); + FAIL() << "Failed test 2"; + } + UNPROTECT_LUA() + //simulate panic + longjmp(global_lj->b, 1); + } + else { + // we should come here + passed = true; + } + UNPROTECT_LUA() + + EXPECT_EQ(passed, true); +} #endif