1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-17 21:35:27 +03:00

Fixes #1643 - Thanks to projectkk2glider for his help on this one

Conflicts:
	radio/src/lua.cpp
	radio/src/opentx.cpp
This commit is contained in:
bsongis 2014-09-05 16:23:55 +02:00
parent 04f9eb5c0f
commit 500602e8cc
8 changed files with 417 additions and 219 deletions

View file

@ -289,6 +289,10 @@ USB = JOYSTICK
# NO - normal behaviour, show real channel values # NO - normal behaviour, show real channel values
CHANNELS_MONITOR_INV_HIDE = NO CHANNELS_MONITOR_INV_HIDE = NO
# Use newlib-nano
# Values = NO, YES
NANO = YES
#------- END BUILD OPTIONS --------------------------- #------- END BUILD OPTIONS ---------------------------
# Define programs and commands. # Define programs and commands.
@ -1116,6 +1120,12 @@ MATH_LIB = -lm
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(MATH_LIB) 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 # Define Messages
# English # English
MSG_BEGIN = -------- begin -------- MSG_BEGIN = -------- begin --------
@ -1324,7 +1334,7 @@ FOXLIB=-L/usr/local/lib \
-Wl,-rpath,$(FOXPATH)/src/.libs -Wl,-rpath,$(FOXPATH)/src/.libs
simu: $(LUADEP) stamp_header $(BOARDSRC) $(CPPSRC) Makefile simu.cpp targets/simu/simpgmspace.cpp *.h tra lbm eeprom.bin 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: eeprom.bin:
dd if=/dev/zero of=$@ bs=1 count=2048 dd if=/dev/zero of=$@ bs=1 count=2048
@ -1390,7 +1400,7 @@ OBJS = $(TMP:.s=.o)
@echo @echo
@echo $(MSG_COMPILING) $@ @echo $(MSG_COMPILING) $@
$(CC) $(ARMCPPFLAGS) $< -o allsrc.o $(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 endif
# Target: clean project. # Target: clean project.

View file

@ -76,6 +76,19 @@ uint16_t maxLuaDuration = 0;
#define SCRIPTS_MAX_HEAP 50 #define SCRIPTS_MAX_HEAP 50
#define SET_LUA_INSTRUCTIONS_COUNT(x) (instructionsPercent=0, lua_sethook(L, hook, LUA_MASKCOUNT, x)) #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; static int instructionsPercent = 0;
void hook(lua_State* L, lua_Debug *ar) 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)); strncpy(str, filename, AUDIO_FILENAME_MAXLEN - (str-file));
file[AUDIO_FILENAME_MAXLEN] = 0; file[AUDIO_FILENAME_MAXLEN] = 0;
PLAY_FILE(file, 0, 0); PLAY_FILE(file, 0, 0);
return 0;
} }
else {
PLAY_FILE(filename, 0, 0); PLAY_FILE(filename, 0, 0);
}
return 0; return 0;
} }
@ -1358,14 +1372,29 @@ static const luaL_Reg lcdLib[] = {
{ NULL, NULL } /* sentinel */ { NULL, NULL } /* sentinel */
}; };
void luaInit() void luaDisable()
{
POPUP_WARNING("Lua disabled!");
luaState = INTERPRETER_PANIC;
}
void luaClose()
{ {
if (L) { 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 // Init lua
luaL_openlibs(L); luaL_openlibs(L);
@ -1441,13 +1470,50 @@ void luaInit()
lua_registerint(L, "TIMEHOUR", TIMEHOUR); 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) void luaFree(ScriptInternalData & sid)
{ {
PROTECT_LUA() {
if (sid.run) { if (sid.run) {
luaL_unref(L, LUA_REGISTRYINDEX, sid.run); luaL_unref(L, LUA_REGISTRYINDEX, sid.run);
sid.run = 0; sid.run = 0;
}
if (sid.background) {
luaL_unref(L, LUA_REGISTRYINDEX, sid.background);
sid.background = 0;
}
lua_gc(L, LUA_GCCOLLECT, 0); lua_gc(L, LUA_GCCOLLECT, 0);
} }
else {
luaDisable();
}
UNPROTECT_LUA();
} }
int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs * sio=NULL) int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs * sio=NULL)
@ -1461,6 +1527,7 @@ int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs
SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS); SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS);
PROTECT_LUA() {
if (luaL_loadfile(L, filename) == 0 && if (luaL_loadfile(L, filename) == 0 &&
lua_pcall(L, 0, 1, 0) == 0 && lua_pcall(L, 0, 1, 0) == 0 &&
lua_istable(L, -1)) { lua_istable(L, -1)) {
@ -1491,17 +1558,24 @@ int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs
if (init) { if (init) {
lua_rawgeti(L, LUA_REGISTRYINDEX, init); lua_rawgeti(L, LUA_REGISTRYINDEX, init);
luaL_unref(L, LUA_REGISTRYINDEX, init);
if (lua_pcall(L, 0, 0, 0) != 0) { if (lua_pcall(L, 0, 0, 0) != 0) {
TRACE("Error in script %s init: %s", filename, lua_tostring(L, -1)); TRACE("Error in script %s init: %s", filename, lua_tostring(L, -1));
sid.state = SCRIPT_SYNTAX_ERROR; sid.state = SCRIPT_SYNTAX_ERROR;
} }
luaL_unref(L, LUA_REGISTRYINDEX, init);
lua_gc(L, LUA_GCCOLLECT, 0);
} }
} }
else { else {
TRACE("Error in script %s: %s", filename, lua_tostring(L, -1)); TRACE("Error in script %s: %s", filename, lua_tostring(L, -1));
sid.state = SCRIPT_SYNTAX_ERROR; sid.state = SCRIPT_SYNTAX_ERROR;
} }
}
else {
TRACE("Panic in script %s: %s", filename, lua_tostring(L, -1));
sid.state = SCRIPT_PANIC;
}
UNPROTECT_LUA();
if (sid.state != SCRIPT_OK) { if (sid.state != SCRIPT_OK) {
luaFree(sid); luaFree(sid);
@ -1663,6 +1737,9 @@ void luaError(uint8_t error)
case SCRIPT_KILLED: case SCRIPT_KILLED:
msg = "Script killed"; msg = "Script killed";
break; break;
case SCRIPT_PANIC:
msg = "Script panic";
break;
} }
POPUP_WARNING(msg); POPUP_WARNING(msg);
} }
@ -1670,33 +1747,24 @@ void luaError(uint8_t error)
void luaExec(const char *filename) void luaExec(const char *filename)
{ {
LUA_RESET(); luaInit();
standaloneScript.state = SCRIPT_NOFILE; standaloneScript.state = SCRIPT_NOFILE;
int result = luaLoad(filename, standaloneScript); int result = luaLoad(filename, standaloneScript);
// TODO the same with run ... // TODO the same with run ...
if (result == SCRIPT_OK) { if (result == SCRIPT_OK) {
luaState = LUASTATE_STANDALONE_SCRIPT_RUNNING; luaState = INTERPRETER_RUNNING_STANDALONE_SCRIPT;
} }
else { else {
luaError(result); luaError(result);
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
} }
} }
void luaTask(uint8_t evt) void luaDoOneRunStandalone(uint8_t evt)
{ {
lcd_locked = false;
static uint8_t luaDisplayStatistics = false; static uint8_t luaDisplayStatistics = false;
uint32_t t0 = get_tmr10ms();
static uint32_t lastLuaTime = 0;
uint16_t interval = (lastLuaTime == 0 ? 0 : (t0 - lastLuaTime));
lastLuaTime = t0;
if (interval > maxLuaInterval) {
maxLuaInterval = interval;
}
if (luaState & LUASTATE_STANDALONE_SCRIPT_RUNNING) {
// standalone script
if (standaloneScript.state == SCRIPT_OK && standaloneScript.run) { if (standaloneScript.state == SCRIPT_OK && standaloneScript.run) {
SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS); SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS);
lua_rawgeti(L, LUA_REGISTRYINDEX, standaloneScript.run); lua_rawgeti(L, LUA_REGISTRYINDEX, standaloneScript.run);
@ -1706,7 +1774,7 @@ void luaTask(uint8_t evt)
if (instructionsPercent > 100) { if (instructionsPercent > 100) {
TRACE("Script killed"); TRACE("Script killed");
standaloneScript.state = SCRIPT_KILLED; standaloneScript.state = SCRIPT_KILLED;
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
} }
else if (lua_isstring(L, -1)) { else if (lua_isstring(L, -1)) {
char nextScript[_MAX_LFN+1]; char nextScript[_MAX_LFN+1];
@ -1717,7 +1785,7 @@ void luaTask(uint8_t evt)
else { else {
TRACE("Script error"); TRACE("Script error");
standaloneScript.state = SCRIPT_SYNTAX_ERROR; standaloneScript.state = SCRIPT_SYNTAX_ERROR;
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
} }
} }
else { else {
@ -1726,13 +1794,12 @@ void luaTask(uint8_t evt)
if (scriptResult != 0) { if (scriptResult != 0) {
TRACE("Script finished with status %d", scriptResult); TRACE("Script finished with status %d", scriptResult);
standaloneScript.state = SCRIPT_NOFILE; standaloneScript.state = SCRIPT_NOFILE;
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
} }
else if (luaDisplayStatistics) { 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_hline(0, 7*FH-1, lcdLastPos+FW, ERASE);
lcd_puts(0, 7*FH, "GV Use: "); lcd_puts(0, 7*FH, "GV Use: ");
lcd_outdezAtt(lcdLastPos, 7*FH, gc, LEFT); lcd_outdezAtt(lcdLastPos, 7*FH, luaGetMemUsed(), LEFT);
lcd_putc(lcdLastPos, 7*FH, 'b'); lcd_putc(lcdLastPos, 7*FH, 'b');
lcd_hline(0, 7*FH-2, lcdLastPos+FW, FORCE); lcd_hline(0, 7*FH-2, lcdLastPos+FW, FORCE);
lcd_vlineStip(lcdLastPos+FW, 7*FH-2, FH+2, SOLID, FORCE); lcd_vlineStip(lcdLastPos+FW, 7*FH-2, FH+2, SOLID, FORCE);
@ -1742,34 +1809,29 @@ void luaTask(uint8_t evt)
else { else {
TRACE("Script error: %s", lua_tostring(L, -1)); TRACE("Script error: %s", lua_tostring(L, -1));
standaloneScript.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR); standaloneScript.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
} }
if (standaloneScript.state != SCRIPT_OK) { if (standaloneScript.state != SCRIPT_OK) {
luaError(standaloneScript.state); luaError(standaloneScript.state);
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
} }
if (evt == EVT_KEY_LONG(KEY_EXIT)) { if (evt == EVT_KEY_LONG(KEY_EXIT)) {
TRACE("Script force exit"); TRACE("Script force exit");
killEvents(evt); killEvents(evt);
standaloneScript.state = SCRIPT_NOFILE; standaloneScript.state = SCRIPT_NOFILE;
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
} }
else if (evt == EVT_KEY_LONG(KEY_MENU)) { else if (evt == EVT_KEY_LONG(KEY_MENU)) {
killEvents(evt); killEvents(evt);
luaDisplayStatistics = !luaDisplayStatistics; luaDisplayStatistics = !luaDisplayStatistics;
} }
} }
} }
else {
// model scripts
if (luaState & LUASTATE_RELOAD_MODEL_SCRIPTS) {
luaState = 0;
LUA_RESET();
luaLoadPermanentScripts();
}
for (int i=0; i<luaScriptsCount; i++) { void luaDoOneRunPermanentScript(uint8_t evt, int i)
{
ScriptInternalData & sid = scriptInternalData[i]; ScriptInternalData & sid = scriptInternalData[i];
if (sid.state == SCRIPT_OK) { if (sid.state == SCRIPT_OK) {
SET_LUA_INSTRUCTIONS_COUNT(PERMANENT_SCRIPTS_MAX_INSTRUCTIONS); SET_LUA_INSTRUCTIONS_COUNT(PERMANENT_SCRIPTS_MAX_INSTRUCTIONS);
@ -1796,7 +1858,7 @@ void luaTask(uint8_t evt)
else if (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST) { else if (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST) {
CustomFnData & fn = g_model.funcSw[sid.reference-SCRIPT_FUNC_FIRST]; CustomFnData & fn = g_model.funcSw[sid.reference-SCRIPT_FUNC_FIRST];
if (!getSwitch(fn.swtch)) { if (!getSwitch(fn.swtch)) {
continue; return;
} }
#if defined(SIMU) || defined(DEBUG) #if defined(SIMU) || defined(DEBUG)
filename = fn.play.name; filename = fn.play.name;
@ -1816,7 +1878,7 @@ void luaTask(uint8_t evt)
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.background); lua_rawgeti(L, LUA_REGISTRYINDEX, sid.background);
} }
else { else {
continue; return;
} }
} }
if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) { if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) {
@ -1852,11 +1914,12 @@ void luaTask(uint8_t evt)
} }
} }
} }
} }
}
lua_gc(L, LUA_GCCOLLECT, 0);
void luaDoGc()
{
PROTECT_LUA() {
lua_gc(L, LUA_GCSTEP /*LUA_GCCOLLECT*/, 0); // LUA_GCSTEP is enough
#if defined(SIMU) || defined(DEBUG) #if defined(SIMU) || defined(DEBUG)
static int lastgc = 0; static int lastgc = 0;
int gc = luaGetMemUsed(); int gc = luaGetMemUsed();
@ -1865,6 +1928,60 @@ void luaTask(uint8_t evt)
TRACE("GC Use: %dbytes", gc); TRACE("GC Use: %dbytes", gc);
} }
#endif #endif
}
else {
// we disable Lua for the rest of the session
luaDisable();
}
UNPROTECT_LUA();
}
void luaTask(uint8_t evt)
{
lcd_locked = false;
uint32_t t0 = get_tmr10ms();
static uint32_t lastLuaTime = 0;
uint16_t interval = (lastLuaTime == 0 ? 0 : (t0 - lastLuaTime));
lastLuaTime = t0;
if (interval > maxLuaInterval) {
maxLuaInterval = interval;
}
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 & INTERPRETER_RELOAD_PERMANENT_SCRIPTS) {
luaState = 0;
luaInit();
if (!L) return;
luaLoadPermanentScripts();
}
for (int i=0; i<luaScriptsCount; i++) {
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();
}
}
luaDoGc();
t0 = get_tmr10ms() - t0; t0 = get_tmr10ms() - t0;
if (t0 > maxLuaDuration) { if (t0 > maxLuaDuration) {
@ -1874,5 +1991,5 @@ void luaTask(uint8_t evt)
int luaGetMemUsed() 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);
} }

View file

@ -2505,6 +2505,10 @@ void opentxClose()
// TODO needed? telemetryEnd(); // TODO needed? telemetryEnd();
#endif #endif
#if defined(LUA)
luaClose();
#endif
#if defined(SDCARD) #if defined(SDCARD)
closeLogs(); closeLogs();
sdDone(); sdDone();
@ -3352,8 +3356,6 @@ void opentxInit(OPENTX_INIT_ARGS)
rtcInit(); rtcInit();
#endif #endif
LUA_INIT();
if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on
if (UNEXPECTED_SHUTDOWN()) { if (UNEXPECTED_SHUTDOWN()) {

View file

@ -1475,7 +1475,8 @@ enum AUDIO_SOUNDS {
SCRIPT_OK, SCRIPT_OK,
SCRIPT_NOFILE, SCRIPT_NOFILE,
SCRIPT_SYNTAX_ERROR, SCRIPT_SYNTAX_ERROR,
SCRIPT_KILLED SCRIPT_PANIC,
SCRIPT_KILLED,
}; };
enum ScriptReference { enum ScriptReference {
SCRIPT_MIX_FIRST, SCRIPT_MIX_FIRST,
@ -1498,13 +1499,18 @@ enum AUDIO_SOUNDS {
uint8_t outputsCount; uint8_t outputsCount;
ScriptOutput outputs[MAX_SCRIPT_OUTPUTS]; ScriptOutput outputs[MAX_SCRIPT_OUTPUTS];
}; };
#define LUASTATE_STANDALONE_SCRIPT_RUNNING 1 enum InterpreterState {
#define LUASTATE_RELOAD_MODEL_SCRIPTS 2 INTERPRETER_RUNNING_PERMANENT_SCRIPTS,
INTERPRETER_RUNNING_STANDALONE_SCRIPT,
INTERPRETER_RELOAD_PERMANENT_SCRIPTS,
INTERPRETER_PANIC,
};
extern uint8_t luaState; extern uint8_t luaState;
extern uint8_t luaScriptsCount; extern uint8_t luaScriptsCount;
extern ScriptInternalData standaloneScript; extern ScriptInternalData standaloneScript;
extern ScriptInternalData scriptInternalData[MAX_SCRIPTS]; extern ScriptInternalData scriptInternalData[MAX_SCRIPTS];
extern ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS]; extern ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS];
void luaClose();
void luaInit(); void luaInit();
void luaTask(uint8_t evt); void luaTask(uint8_t evt);
void luaExec(const char *filename); void luaExec(const char *filename);
@ -1513,13 +1519,23 @@ enum AUDIO_SOUNDS {
int luaGetMemUsed(); int luaGetMemUsed();
#define luaGetCpuUsed(idx) scriptInternalData[idx].instructions #define luaGetCpuUsed(idx) scriptInternalData[idx].instructions
bool isTelemetryScriptAvailable(uint8_t index); bool isTelemetryScriptAvailable(uint8_t index);
#define LUA_INIT() #define LUA_LOAD_MODEL_SCRIPTS() luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
#define LUA_RESET() luaInit() #define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
#define LUA_LOAD_MODEL_SCRIPTS() luaState |= LUASTATE_RELOAD_MODEL_SCRIPTS
#define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= LUASTATE_RELOAD_MODEL_SCRIPTS // Lua PROTECT/UNPROTECT
#include <setjmp.h>
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 #else
#define LUA_INIT()
#define LUA_RESET()
#define LUA_LOAD_MODEL_SCRIPTS() #define LUA_LOAD_MODEL_SCRIPTS()
#define LUA_LOAD_MODEL_SCRIPT(idx) #define LUA_LOAD_MODEL_SCRIPT(idx)
#endif #endif

View file

@ -309,8 +309,6 @@ void *main_thread(void *)
if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on
LUA_INIT();
if (main_thread_running == 1) { if (main_thread_running == 1) {
opentxStart(); opentxStart();
} }

View file

@ -99,6 +99,13 @@ uint32_t stack_free(uint32_t tid)
stack = audioStack; stack = audioStack;
size = AUDIO_STACK_SIZE; size = AUDIO_STACK_SIZE;
break; 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: default:
return 0; return 0;
} }
@ -107,7 +114,7 @@ uint32_t stack_free(uint32_t tid)
for (; i<size; i++) for (; i<size; i++)
if (stack[i] != 0x55555555) if (stack[i] != 0x55555555)
break; break;
return i; return i*4;
} }
void mixerTask(void * pdata) void mixerTask(void * pdata)

View file

@ -183,7 +183,6 @@ int main(int argc, char **argv)
StartEepromThread(NULL); StartEepromThread(NULL);
g_menuStackPtr = 0; g_menuStackPtr = 0;
g_menuStack[0] = menuMainView; g_menuStack[0] = menuMainView;
LUA_RESET();
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }

View file

@ -52,6 +52,8 @@ extern const char * zchar2string(const char * zstring, int size);
void luaExecStr(const char * str) void luaExecStr(const char * str)
{ {
extern lua_State * L; extern lua_State * L;
if (!L) luaInit();
if (!L) FAIL() << "No Lua state!";
if (luaL_dostring(L, str)) { if (luaL_dostring(L, str)) {
FAIL() << "lua error: " << lua_tostring(L, -1); FAIL() << "lua error: " << lua_tostring(L, -1);
} }
@ -98,4 +100,51 @@ TEST(Lua, testSetTelemetryChannel)
} }
TEST(Lua, testPanicProtection)
{
bool passed = false;
PROTECT_LUA() {
PROTECT_LUA() {
//simulate panic
longjmp(global_lj->b, 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 #endif