diff --git a/radio/src/FatFs/ff.c b/radio/src/FatFs/ff.c index aa640f89f..3c87bc3b1 100644 --- a/radio/src/FatFs/ff.c +++ b/radio/src/FatFs/ff.c @@ -3073,6 +3073,11 @@ FRESULT f_opendir ( } +FRESULT f_closedir (DIR * rep) +{ + //apparently nothing to do in FatFS + return FR_OK; +} /*-----------------------------------------------------------------------*/ diff --git a/radio/src/FatFs/ff.h b/radio/src/FatFs/ff.h index b4115f610..9d4b865f8 100644 --- a/radio/src/FatFs/ff.h +++ b/radio/src/FatFs/ff.h @@ -209,6 +209,7 @@ FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ FRESULT f_close (FIL* fp); /* Close an open file object */ FRESULT f_opendir (DIR* dj, const TCHAR* path); /* Open an existing directory */ +FRESULT f_closedir (DIR * rep); FRESULT f_readdir (DIR* dj, FILINFO* fno); /* Read a directory item */ FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ diff --git a/radio/src/Makefile b/radio/src/Makefile index c53697ccf..281c1851b 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -297,6 +297,13 @@ CHANNELS_MONITOR_INV_HIDE = NO # Values = NO, YES NANO = NO +# Use custom bin based allocator for Lua +# Values = NO, YES +# YES - use our bin based allocator +# NO - use default Lua allocator +USE_BIN_ALLOCATOR = NO + + # Enable trace of events into Trace Buffer for debugging purposes # Activating any of these options also activates DEBUG and DEBUG_TRACE_BUFFER # Values = NO, YES @@ -776,6 +783,10 @@ ifeq ($(PCB), TARANIS) lua/src/lbaselib.c lua/src/linit.c lua/src/lmathlib.c lua/src/lbitlib.c lua/src/loadlib.c lua/src/lauxlib.c lua/src/ltablib.c lua/src/lcorolib.c SRC += $(LUASRC) LUADEP = lua_exports.cpp + ifeq ($(USE_BIN_ALLOCATOR), YES) + CPPDEFS += -DUSE_BIN_ALLOCATOR + CPPSRC += bin_allocator.cpp + endif endif ifeq ($(SDCARD), YES) EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/taranis/diskio.cpp diff --git a/radio/src/audio_arm.cpp b/radio/src/audio_arm.cpp index 1d096e558..306f11da8 100644 --- a/radio/src/audio_arm.cpp +++ b/radio/src/audio_arm.cpp @@ -274,6 +274,7 @@ void referenceSystemAudioFiles() } } } + f_closedir(&dir); } sdAvailableSystemAudioFiles = availableAudioFiles; @@ -395,6 +396,7 @@ void referenceModelAudioFiles() } } } + f_closedir(&dir); } } diff --git a/radio/src/bin_allocator.cpp b/radio/src/bin_allocator.cpp new file mode 100644 index 000000000..f74e351f2 --- /dev/null +++ b/radio/src/bin_allocator.cpp @@ -0,0 +1,111 @@ +#include +#include +#include "opentx.h" +#include "bin_allocator.h" + + +BinAllocator_slots1 slots1; +BinAllocator_slots2 slots2; + +#if defined(DEBUG) +int SimulateMallocFailure = 0; //set this to simulate allocation failure +#endif + +bool bin_free(void * ptr) +{ + //return TRUE if ours + return slots1.free(ptr) || slots2.free(ptr); +} + +void * bin_malloc(size_t size) { + //try to allocate from our space + void * res = slots1.malloc(size); + return res ? res : slots2.malloc(size); +} + +void * bin_realloc(void * ptr, size_t size) +{ + if (ptr == 0) { + //no previous data, try our malloc + return bin_malloc(size); + } + else { + if (! (slots1.is_member(ptr) || slots2.is_member(ptr)) ) { + // not our data, leave it to libc realloc + return 0; + } + + //we have existing data + // if it fits in current slot, return it + // TODO if new size is smaller, try to relocate in smaller slot + if ( slots1.can_fit(ptr, size) ) { + // TRACE("OUR realloc %p[%lu] fits in slot1", ptr, size); FLUSH(); + return ptr; + } + if ( slots2.can_fit(ptr, size) ) { + // TRACE("OUR realloc %p[%lu] fits in slot2", ptr, size); FLUSH(); + return ptr; + } + + //we need a bigger slot + void * res = bin_malloc(size); + if (res == 0) { + // we don't have the space, use libc malloc + // TRACE("bin_malloc [%lu] FAILURE", size); FLUSH(); + res = malloc(size); + if (res == 0) { + TRACE("libc malloc [%lu] FAILURE", size); FLUSH(); + return 0; + } + } + //copy data + memcpy(res, ptr, slots1.size(ptr) + slots2.size(ptr)); + bin_free(ptr); + return res; + } +} + + +void *bin_l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) +{ + (void)ud; (void)osize; /* not used */ + if (nsize == 0) { + if (ptr) { // avoid a bunch of NULL pointer free calls + if (!bin_free(ptr)) { + // not our range, use libc allocator + // TRACE("libc free %p", ptr); FLUSH(); + free(ptr); + } + } + return NULL; + } + else { +#if defined(DEBUG) + if (SimulateMallocFailure < 0 ) { + //delayed failure + if (++SimulateMallocFailure == 0) { + SimulateMallocFailure = 1; + } + } + if ( SimulateMallocFailure > 0) { + // simulate one malloc failure + TRACE("bin_l_alloc(): simulating malloc failure at %p[%lu]", ptr, nsize); FLUSH(); + return 0; + } +#endif // #if defined(DEBUG) + // try our allocator, if it fails use libc allocator + void * res = bin_realloc(ptr, nsize); + if (res && ptr) { + // TRACE("OUR realloc %p[%lu] -> %p[%lu]", ptr, osize, res, nsize); FLUSH(); + } + if (res == 0) { + res = realloc(ptr, nsize); + // TRACE("libc realloc %p[%lu] -> %p[%lu]", ptr, osize, res, nsize); FLUSH(); + // if (res == 0 ){ + // TRACE("realloc FAILURE %lu", nsize); + // dumpFreeMemory(); + // } + } + return res; + } +} diff --git a/radio/src/bin_allocator.h b/radio/src/bin_allocator.h new file mode 100644 index 000000000..1c50fb75b --- /dev/null +++ b/radio/src/bin_allocator.h @@ -0,0 +1,78 @@ +#ifndef binallocator_h +#define binallocator_h + +#include "debug.h" + +template class BinAllocator { +private: + PACK(struct Bin { + char data[SIZE_SLOT]; + bool Used; + }); + struct Bin Bins[NUM_BINS]; + int NoUsedBins; +public: + BinAllocator() : NoUsedBins(0) { + memclear(Bins, sizeof(Bins)); + } + bool free(void * ptr) { + for (size_t n = 0; n < NUM_BINS; ++n) { + if (ptr == Bins[n].data) { + Bins[n].Used = false; + --NoUsedBins; + // TRACE("\tBinAllocator<%d> free %lu ------", SIZE_SLOT, n); FLUSH(); + return true; + } + } + return false; + } + bool is_member(void * ptr) { + return (ptr >= Bins[0].data && ptr <= Bins[NUM_BINS-1].data); + } + void * malloc(size_t size) { + if (size > SIZE_SLOT) { + // TRACE("BinAllocator<%d> malloc [%lu] size > SIZE_SLOT", SIZE_SLOT, size); FLUSH(); + return 0; + } + if (NoUsedBins >= NUM_BINS) { + // TRACE("BinAllocator<%d> malloc [%lu] no free slots", SIZE_SLOT, size); FLUSH(); + return 0; + } + for (size_t n = 0; n < NUM_BINS; ++n) { + if (!Bins[n].Used) { + Bins[n].Used = true; + ++NoUsedBins; + // TRACE("\tBinAllocator<%d> malloc %lu[%lu]", SIZE_SLOT, n, size); FLUSH(); + return Bins[n].data; + } + } + // TRACE("BinAllocator<%d> malloc [%lu] no free slots", SIZE_SLOT , size); FLUSH(); + return 0; + } + size_t size(void * ptr) { + return is_member(ptr) ? SIZE_SLOT : 0; + } + bool can_fit(void * ptr, size_t size) { + return is_member(ptr) && size <= SIZE_SLOT; //todo is_member check is redundant + } + unsigned int capacity() { return NUM_BINS; } + unsigned int size() { return NoUsedBins; } +}; + +#if defined(SIMU) +typedef BinAllocator<39,300> BinAllocator_slots1; +typedef BinAllocator<79,100> BinAllocator_slots2; +#else +typedef BinAllocator<29,200> BinAllocator_slots1; +typedef BinAllocator<91,50> BinAllocator_slots2; +#endif + +#if defined(USE_BIN_ALLOCATOR) +extern BinAllocator_slots1 slots1; +extern BinAllocator_slots2 slots2; + +// wrapper for our BinAllocator for Lua +void *bin_l_alloc (void *ud, void *ptr, size_t osize, size_t nsize); +#endif //#if defined(USE_BIN_ALLOCATOR) + +#endif //binallocator_h diff --git a/radio/src/debug.cpp b/radio/src/debug.cpp index a50338443..4ed6d4c3d 100644 --- a/radio/src/debug.cpp +++ b/radio/src/debug.cpp @@ -137,6 +137,13 @@ static void dispw_256( register uint32_t address, register uint32_t lines ) } } +extern Fifo<512> uart3TxFifo; + +void debugFlush() +{ + uart3TxFifo.flush(); +} + void debugTask(void* pdata) { uint8_t rxchar ; diff --git a/radio/src/debug.h b/radio/src/debug.h index 4fe093f62..dc5880eec 100644 --- a/radio/src/debug.h +++ b/radio/src/debug.h @@ -52,6 +52,8 @@ #define TRACE_WARNING(...) do { printf("-W- " __VA_ARGS__); fflush(stdout); } while(0) #define TRACE_WARNING_WP(...) do { printf(__VA_ARGS__); fflush(stdout); } while(0) #define TRACE_ERROR(...) do { printf("-E- " __VA_ARGS__); fflush(stdout); } while(0) +#define FLUSH() + inline void dump(void * data, unsigned int size) { unsigned char *uchar_data = (unsigned char *)data; @@ -78,6 +80,7 @@ extern "C" { void debugPuts(const char *string, ...); void dump(unsigned char *data, unsigned int size); +void debugFlush(); #ifdef __cplusplus } @@ -92,7 +95,7 @@ void dump(unsigned char *data, unsigned int size); #define TRACE_WARNING(...) debugPuts("-W- " __VA_ARGS__) #define TRACE_WARNING_WP(...) debugPuts(__VA_ARGS__) #define TRACE_ERROR(...) debugPuts("-E- " __VA_ARGS__) - +#define FLUSH() debugFlush(); void debugTask(void* pdata); #else @@ -106,6 +109,7 @@ void debugTask(void* pdata); #define TRACE_WARNING(...) { } #define TRACE_WARNING_WP(...) { } #define TRACE_ERROR(...) { } +#define FLUSH() #endif diff --git a/radio/src/eeprom_raw.cpp b/radio/src/eeprom_raw.cpp index b3d2704e3..dafde85ef 100644 --- a/radio/src/eeprom_raw.cpp +++ b/radio/src/eeprom_raw.cpp @@ -682,6 +682,9 @@ const pm_char * eeBackupModel(uint8_t i_fileSrc) if (result != FR_OK) return SDCARD_ERROR(result); } + else { + f_closedir(&archiveFolder); + } buf[sizeof(MODELS_PATH)-1] = '/'; strcpy(strcat_modelname(&buf[sizeof(MODELS_PATH)], i_fileSrc), STR_MODELS_EXT); diff --git a/radio/src/fifo.h b/radio/src/fifo.h index b5d41338f..bb18dab09 100644 --- a/radio/src/fifo.h +++ b/radio/src/fifo.h @@ -47,10 +47,6 @@ class Fifo { } - bool empty() { - return (ridx == widx); - } - void push(uint8_t byte) { uint32_t next = (widx+1) & (N-1); if (next != ridx) { @@ -69,6 +65,12 @@ class Fifo return true; } } + bool empty() { + return (ridx == widx); + } + void flush() { + while (!empty()) {}; + } protected: uint8_t fifo[N]; diff --git a/radio/src/lua.cpp b/radio/src/lua.cpp index dece1af6d..c7fa4a516 100644 --- a/radio/src/lua.cpp +++ b/radio/src/lua.cpp @@ -38,6 +38,7 @@ #include #include "opentx.h" #include "stamp-opentx.h" +#include "bin_allocator.h" #if !defined(SIMU) extern "C" { @@ -1566,7 +1567,11 @@ void luaInit() { luaClose(); if (luaState != INTERPRETER_PANIC) { - L = luaL_newstate(); +#if defined(USE_BIN_ALLOCATOR) + L = lua_newstate(bin_l_alloc, NULL); //we use our own allocator! +#else + L = lua_newstate(l_alloc, NULL); //we use Lua default allocator +#endif if (L) { // install our panic handler lua_atpanic(L, &custom_lua_atpanic); diff --git a/radio/src/lua/src/lauxlib.c b/radio/src/lua/src/lauxlib.c index 1c52b82a6..b548fe297 100644 --- a/radio/src/lua/src/lauxlib.c +++ b/radio/src/lua/src/lauxlib.c @@ -954,10 +954,13 @@ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, } -static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { +void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { (void)ud; (void)osize; /* not used */ if (nsize == 0) { - free(ptr); + if (ptr) { // avoid a bunch of NULL pointer free calls + // TRACE("free %p", ptr); FLUSH(); + free(ptr); + } return NULL; } else diff --git a/radio/src/lua/src/lauxlib.h b/radio/src/lua/src/lauxlib.h index bb2ba5e97..6cc922e12 100644 --- a/radio/src/lua/src/lauxlib.h +++ b/radio/src/lua/src/lauxlib.h @@ -93,6 +93,8 @@ LUALIB_API int (luaL_len) (lua_State *L, int idx); LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, const char *r); +LUALIB_API void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize); + LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); diff --git a/radio/src/lua/src/ldo.c b/radio/src/lua/src/ldo.c index 32d6e5ed4..c301030d6 100644 --- a/radio/src/lua/src/ldo.c +++ b/radio/src/lua/src/ldo.c @@ -205,6 +205,12 @@ static int stackinuse (lua_State *L) { void luaD_shrinkstack (lua_State *L) { int inuse = stackinuse(L); int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; + if ((L->stacksize - goodsize) < 40) { + //skip shrink + // TRACE("luaD_shrinkstack(skip): L->stacksize: %d, goodsize: %d", L->stacksize, goodsize); + return; + } + // TRACE("luaD_shrinkstack(): L->stacksize: %d, goodsize: %d", L->stacksize, goodsize); if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ goodsize >= L->stacksize) /* would grow instead of shrink? */ diff --git a/radio/src/lua/src/lua.h b/radio/src/lua/src/lua.h index 5dc0db202..cf4af4634 100644 --- a/radio/src/lua/src/lua.h +++ b/radio/src/lua/src/lua.h @@ -11,10 +11,10 @@ #include #include - +#include #include "luaconf.h" - +#include "debug.h" #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "2" diff --git a/radio/src/lua/src/luaconf.h b/radio/src/lua/src/luaconf.h index 4d96f2c77..b55800073 100644 --- a/radio/src/lua/src/luaconf.h +++ b/radio/src/lua/src/luaconf.h @@ -11,9 +11,9 @@ #include #include -#include "debug.h" - +#if defined(SDCARD) #define USE_FATFS +#endif /* ** ================================================================== diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 61b0f011a..02dc22eec 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -55,6 +55,7 @@ class Open9xSim: public FXMainWindow public: Open9xSim(){}; Open9xSim(FXApp* a); + ~Open9xSim(); long onKeypress(FXObject*,FXSelector,void*); long onTimeout(FXObject*,FXSelector,void*); void makeSnapshot(const FXDrawable* drawable); @@ -67,7 +68,7 @@ class Open9xSim: public FXMainWindow bool firstTime; public: - FXSlider *sliders[8]; + FXSlider *sliders[NUM_STICKS]; FXKnob *knobs[NUM_POTS]; }; @@ -127,6 +128,24 @@ Open9xSim::Open9xSim(FXApp* a): getApp()->addTimeout(this,2,100); } +Open9xSim::~Open9xSim() +{ + StopMainThread(); + StopEepromThread(); + + delete bmp; + delete sliders[0]; + delete sliders[1]; + delete sliders[2]; + delete sliders[3]; + + for(int i=0; ifs); + return FR_OK; +} + FRESULT f_readdir (DIR * rep, FILINFO * fil) { if (!rep->fs) return FR_NO_FILE; diff --git a/radio/src/targets/simu/simpgmspace.h b/radio/src/targets/simu/simpgmspace.h index 212983271..4325e92fd 100644 --- a/radio/src/targets/simu/simpgmspace.h +++ b/radio/src/targets/simu/simpgmspace.h @@ -356,7 +356,9 @@ void simuSetTrim(uint8_t trim, bool state); void simuSetSwitch(uint8_t swtch, int8_t state); void StartMainThread(bool tests=true); +void StopMainThread(); void StartEepromThread(const char *filename="eeprom.bin"); +void StopEepromThread(); extern const char *eepromFile; #if defined(PCBTARANIS) || defined(PCBACT)