Commit 4ae52c23 authored by TerryE's avatar TerryE
Browse files

Alpha working wersion for third party evaluation

parent e00d927a
......@@ -5,6 +5,15 @@
# single hardware breakpoint which can be used as an hb or a wa. You have to
# remember to delete the previous one, so the br macro does this for you.
#
file app/.output/eagle/debug/image/eagle.app.v6.out
#set remotedebug 1
set remotelogfile gdb_rsp_logfile.txt
set serial baud 115200
set remote hardware-breakpoint-limit 1
set remote hardware-watchpoint-limit 1
#set debug xtensa 4
target remote /dev/ttyUSB0
set confirm off
set print null-stop
define br
......@@ -13,10 +22,30 @@ define br
end
set pagination off
define prTS
set $o = &(((TString *)($arg0))->tsv)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked
printf "String: hash = 0x%08x, len = %u : %s\n", $o->hash, $o->len, (char *)(&$o[1])
end
define prTnodes
set $o = (Table *)($arg0)
set $n = 1<<($o->lsizenode)
set $i = 0
while $i < $n
set $nd = ($o->node) + $i
if $nd->i_key.nk.tt && $nd->i_val.tt
if $nd->i_key.nk.tt == 6
printf "%4u: %s %2i\n", $i, $nd->i_key.nk.tt , $nd->i_val.tt else
printf "%4u: %2i %2i\n", $i, $nd->i_key.nk.tt , $nd->i_val.tt
end
end
set $i = $i +1
end
end
define prTV
if $arg0
set $type = $arg0.tt
set $val = $arg0.value
set $type = ($arg0).tt
set $val = ($arg0).value
if $type == 0
# NIL
......@@ -24,34 +53,33 @@ define prTV
end
if $type == 1
# Boolean
printf "Boolean: %u\n", $val->n
printf "Boolean: %u\n", $val.n
end
if $type == 2
# ROTable
printf "ROTable: %p\n", $val->p
printf "ROTable: %p\n", $val.p
end
if $type == 3
# Light Function
printf "Light Func: %p\n",p $arg $val->p
printf "Light Func: %p\n", $val.p
end
if $type == 4
# Light User Data
printf "Light Udata: %p\n", $val->pend
printf "Light Udata: %p\n", $val.p
end
if $type == 5
# Number
printf "Boolean: %u\n", $val->n
printf "Number: %u\n", $val.n
end
if $type == 6
# TString
set $o = &($val.gc->ts.tsv)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked
printf "String: hash = 0x%08x, len = %u : %s\n", $o->hash, $o->len, (char *)($ts+1)
prTS $arg0
end
if $type == 7
# Table
__printComHdr $arg0
set $ts = (TString *)$val->p
set $o = &($val->gc.h)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked
printf "Nodes: %4i %p\n", 2<<($o->lsizenode), $o->nodes
printf "Arry: %4i %p\n", $o->sizearray, $o->array
end
if $type == 8
# Function
......@@ -106,6 +134,25 @@ define dumpRAMstrt
dumpstrt &(L->l_G->strt)
end
define dumpROstrt
dumpstrt &(L->l_G->ROstrt)
end
define graylist
set $n = $arg0
while $n
printf "%p %2u %02X\n",$n, $n->gch.tt, $n->gch.marked
set $n=$n->gch.next
end
end
define prPC
printf "Excuting instruction %i: %08x\n", (pc - cl->p->code)+1-1, i
end
define prT
print *(Table*)($arg0)
end
set history save on
set history size 1000
......@@ -26,7 +26,7 @@ ifdef DEBUG
CCFLAGS += -ggdb -O0
LDFLAGS += -ggdb
else
CCFLAGS += -Os
CCFLAGS += -O2
endif
#############################################################
......
......@@ -20,93 +20,64 @@ FLAVOR = debug
ifndef PDIR # {
GEN_IMAGES= eagle.app.v6.out
GEN_BINS= eagle.app.v6.bin
SPECIAL_MKTARGETS=$(APP_MKTARGETS)
OPT_MKTARGETS := coap crypto dht http mqtt pcm sjson sqlite3 tsl2561 u8glib ucglib websocket
SEL_MKTARGETS := $(shell $(CC) -E -dM include/user_modules.h | sed -n '/^\#define LUA_USE_MODULES_/{s/.\{24\}\(.*\)/\L\1/; p}')
OPT_SEL_MKTARGETS := $(foreach tgt,$(OPT_MKTARGETS),$(findstring $(tgt), $(SEL_MKTARGETS)))
OPT_SEL_COMPONENTS := $(foreach tgt,$(OPT_SEL_MKTARGETS),$(tgt)/lib$(tgt).a)
SPECIAL_MKTARGETS :=$(APP_MKTARGETS)
SUBDIRS= \
user \
driver \
pcm \
mbedtls \
platform \
libc \
lua \
lwip \
coap \
mqtt \
task \
u8glib \
ucglib \
smart \
modules \
spiffs \
crypto \
dhtlib \
tsl2561 \
net \
http \
fatfs \
esp-gdbstub \
websocket \
swTimer \
misc \
pm \
sjson \
sqlite3 \
$(OPT_SEL_MKTARGETS)
endif # } PDIR
APPDIR = .
LDDIR = ../ld
CCFLAGS += -Os
TARGET_LDFLAGS = \
-nostdlib \
-Wl,-EL \
--longcalls \
--text-section-literals
ifeq ($(FLAVOR),debug)
TARGET_LDFLAGS += -g -Os
endif
ifeq ($(FLAVOR),release)
TARGET_LDFLAGS += -Os
endif
LD_FILE = $(LDDIR)/nodemcu.ld
COMPONENTS_eagle.app.v6 = \
user/libuser.a \
driver/libdriver.a \
pcm/pcm.a \
platform/libplatform.a \
task/libtask.a \
libc/liblibc.a \
lua/liblua.a \
lwip/liblwip.a \
coap/coap.a \
mqtt/mqtt.a \
u8glib/u8glib.a \
ucglib/ucglib.a \
smart/smart.a \
spiffs/spiffs.a \
fatfs/libfatfs.a \
crypto/libcrypto.a \
dhtlib/libdhtlib.a \
tsl2561/tsl2561lib.a \
http/libhttp.a \
pm/libpm.a \
websocket/libwebsocket.a \
esp-gdbstub/libgdbstub.a \
net/libnodemcu_net.a \
mbedtls/libmbedtls.a \
modules/libmodules.a \
swTimer/libswtimer.a \
misc/libmisc.a \
sjson/libsjson.a \
sqlite3/libsqlite3.a \
$(OPT_SEL_COMPONENTS)
# Inspect the modules library and work out which modules need to be linked.
# For each enabled module, a symbol name of the form XYZ_module_selected is
......@@ -194,6 +165,5 @@ INCLUDES += -I ./
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
.PHONY: FORCE
FORCE:
......@@ -12,7 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = coap.a
GEN_LIBS = libcoap.a
endif
#############################################################
......
......@@ -12,7 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libdhtlib.a
GEN_LIBS = libdht.a
endif
......
#if !defined(__MODULE_H_) && !defined(LUA_CROSS_COMPILER)
#ifndef __MODULE_H__
#define __MODULE_H__
#include "user_modules.h"
......@@ -38,8 +38,11 @@
#define MODULE_PASTE_(x,y) x##y
#define MODULE_EXPAND_PASTE_(x,y) MODULE_PASTE_(x,y)
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(s)))
#ifdef LUA_CROSS_COMPILER
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".rodata1." #s)))
#else
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s)))
#endif
/* For the ROM table, we name the variable according to ( | denotes concat):
* cfgname | _module_selected | LUA_USE_MODULES_##cfgname
* where the LUA_USE_MODULES_XYZ macro is first expanded to yield either
......@@ -51,20 +54,20 @@
* to be linked in.
*/
#define NODEMCU_MODULE(cfgname, luaname, map, initfunc) \
const LOCK_IN_SECTION(".lua_libs") \
const LOCK_IN_SECTION(libs) \
luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \
const LOCK_IN_SECTION(".lua_rotable") \
const LOCK_IN_SECTION(rotable) \
luaR_table MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \
= { luaname, map }
/* System module registration support, not using LUA_USE_MODULES_XYZ. */
#define BUILTIN_LIB_INIT(name, luaname, initfunc) \
const LOCK_IN_SECTION(".lua_libs") \
const LOCK_IN_SECTION(libs) \
luaL_Reg MODULE_PASTE_(lua_lib_,name) = { luaname, initfunc }
#define BUILTIN_LIB(name, luaname, map) \
const LOCK_IN_SECTION(".lua_rotable") \
const LOCK_IN_SECTION(rotable) \
luaR_table MODULE_PASTE_(lua_rotable_,name) = { luaname, map }
#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)
......
......@@ -12,8 +12,9 @@
// This adds the asserts in LUA. It also adds some useful extras to the
// node module. This is all silent in normal operation and so can be enabled
// without any harm (except for the code size increase and slight slowdown)
// Either here for a global change or in the DEFINES variable in the relevant
// Makefile for ony one subdirectory. If you want to use the remote GDB to
// You can either set these defines here to operate globally or you edit the
// relevant Makefile setting them in the DEFINES variable is you only want to
// enable extra debug for specific subdirs. If you want to use the remote GDB to
// handle breaks and failed assetions then enable DEVELOPMENT_USE GDB
//#define DEVELOPMENT_TOOLS
//#define DEVELOPMENT_USE_GDB
......@@ -54,6 +55,8 @@ extern void luaL_dbgbreak(void);
#define NODE_ERR
#endif /* NODE_ERROR */
#define LUA_USE_BUILTIN_DEBUG_MINIMAL // for debug.getregistry() and debug.traceback()
#define GPIO_INTERRUPT_ENABLE
#define GPIO_INTERRUPT_HOOK_ENABLE
// #define GPIO_SAFE_NO_INTR_ENABLE
......@@ -86,18 +89,22 @@ extern void luaL_dbgbreak(void);
// maximum number of open files for SPIFFS
#define SPIFFS_MAX_OPEN_FILES 4
// Uncomment this next line for fastest startup
// It reduces the format time dramatically
// #define SPIFFS_MAX_FILESYSTEM_SIZE 32768
// Uncomment this next line for fastest startup and set the FS only to what
// your application needs. This reduces the format time dramatically
//#define SPIFFS_MAX_FILESYSTEM_SIZE 0x10000
//
// You can force the spiffs file system to be at a fixed location
// #define SPIFFS_FIXED_LOCATION 0x100000
//#define SPIFFS_FIXED_LOCATION 0x100000
//
// You can force the SPIFFS file system to end on the next !M boundary
// (minus the 16k parameter space). THis is useful for certain OTA scenarios
// #define SPIFFS_SIZE_1M_BOUNDARY
// #define LUA_NUMBER_INTEGRAL
//#define LUA_NUMBER_INTEGRAL
// If you want to enable Lua Flash Store (LFS) then set the following define to
// the size of the store. This can be any multiple of 4kB up to a maximum 256Kb.
//#define LUA_FLASH_STORE 0x10000
#define READLINE_INTERVAL 80
#define LUA_TASK_PRIO USER_TASK_PRIO_0
......
#ifndef __USER_MODULES_H__
#define __USER_MODULES_H__
#define LUA_USE_BUILTIN_STRING // for string.xxx()
#define LUA_USE_BUILTIN_TABLE // for table.xxx()
#define LUA_USE_BUILTIN_COROUTINE // for coroutine.xxx()
#define LUA_USE_BUILTIN_MATH // for math.xxx(), partially work
// #define LUA_USE_BUILTIN_IO // for io.xxx(), partially work
// #define LUA_USE_BUILTIN_OS // for os.xxx(), not work
// #define LUA_USE_BUILTIN_DEBUG
#define LUA_USE_BUILTIN_DEBUG_MINIMAL // for debug.getregistry() and debug.traceback()
#ifndef LUA_CROSS_COMPILER
......@@ -65,13 +57,13 @@
//#define LUA_USE_MODULES_SJSON
//#define LUA_USE_MODULES_SNTP
//#define LUA_USE_MODULES_SOMFY
#define LUA_USE_MODULES_SPI
//#define LUA_USE_MODULES_SPI
//#define LUA_USE_MODULES_SQLITE3
//#define LUA_USE_MODULES_STRUCT
//#define LUA_USE_MODULES_SWITEC
// #define LUA_USE_MODULES_TCS34725
//#define LUA_USE_MODULES_TCS34725
//#define LUA_USE_MODULES_TM1829
#define LUA_USE_MODULES_TLS
//#define LUA_USE_MODULES_TLS
#define LUA_USE_MODULES_TMR
//#define LUA_USE_MODULES_TSL2561
//#define LUA_USE_MODULES_U8G
......
......@@ -25,7 +25,8 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#DEFINES += -DDEVELOPMENT_TOOLS -DDEVELOPMENT_USE_GDB -DNODE_DEBUG -DBREAK_ON_STARTUP_PIN=1
#EXTRA_CCFLAGS += -ggdb -O0
#############################################################
# Recursion Magic - Don't touch this!!
......
......@@ -414,7 +414,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
case LUA_TROTABLE:
return rvalue(o);
case LUA_TLIGHTFUNCTION:
return pvalue(o);
return fvalue(o);
default: return NULL;
}
}
......@@ -459,15 +459,6 @@ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
}
LUA_API void lua_pushrolstring (lua_State *L, const char *s, size_t len) {
lua_lock(L);
luaC_checkGC(L);
setsvalue2s(L, L->top, luaS_newrolstr(L, s, len));
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushstring (lua_State *L, const char *s) {
if (s == NULL)
lua_pushnil(L);
......
......@@ -46,6 +46,13 @@
//#define DEBUG_ALLOCATOR
#ifdef DEBUG_ALLOCATOR
#ifdef LUA_CROSS_COMPILER
static void break_hook(void)
#define ASSERT(s) if (!(s)) {break_hook();}
#else
#define ASSERT(s) if (!(s)) {asm ("break 0,0" ::);}
#endif
/*
** {======================================================================
** Diagnosticd version for realloc. This is enabled only if the
......@@ -56,31 +63,72 @@
** =======================================================================
*/
#define this_realloc debug_realloc
#define ASSERT(s) if (!(s)) {asm ("break 0,0" ::);}
#define MARK 0x55 /* 01010101 (a nice pattern) */
#define MARK4 0x55555555
#define MARKSIZE 4 /* size of marks after each block */
#define fillmem(mem,size) memset(mem, -MARK, size)
#define MARKSIZE 2*sizeof(size_t) /* size of marks after each block */
#define fillmem(mem,size) memset(mem, ~MARK, size)
typedef struct Memcontrol { /* memory-allocator control variables */
uint32_t numblocks;
uint32_t total;
uint32_t maxmem;
uint32_t memlimit;
} Memcontrol;
static Memcontrol mc = {0,0,0,32768};
typedef union MemHeader {
typedef union MemHeader MemHeader;
union MemHeader {
L_Umaxalign a; /* ensures maximum alignment for Header */
struct {
size_t size;
int mark;
} d;
} MemHeader;
MemHeader *next;
size_t mark[2];
};
};
typedef struct Memcontrol { /* memory-allocator control variables */
MemHeader *start;
lu_int32 numblocks;
lu_int32 total;
lu_int32 maxmem;
lu_int32 memlimit;
} Memcontrol;
static Memcontrol mc = {NULL,0,0,0,32768*64};
static size_t marker[2] = {0,0};
static void scanBlocks (void) {
MemHeader *p = mc.start;
int i;
char s,e;
for (i=0; p ;i++) {
s = memcmp(p->mark, marker, MARKSIZE) ? '<' : ' ';
e = memcmp(cast(char *, p+1) + p->size, marker, MARKSIZE) ? '>' : ' ';
c_printf("%4u %p %8lu %c %c\n", i, p, p->size, s, e);
ASSERT(p->next);
p = p->next;
}
}
static int checkBlocks (void) {
MemHeader *p = mc.start;
while(p) {
if (memcmp(p->mark, marker, MARKSIZE) ||
memcmp(cast(char *, p+1) + p->size, marker, MARKSIZE)) {
scanBlocks();
return 0;
}
p = p->next;
}
return 1;
}
static void freeblock (MemHeader *block) {
if (block) {
size_t size = block->d.size;
MemHeader *p = mc.start;
MemHeader *next = block->next;
size_t size = block->size;
ASSERT(checkBlocks());
if (p == block) {
mc.start = next;
} else {
while (p->next != block) {
ASSERT(p);
p = p->next;
}
p->next = next;
}
fillmem(block, sizeof(MemHeader) + size + MARKSIZE); /* erase block */
c_free(block); /* actually free block */
mc.numblocks--; /* update counts */
......@@ -88,18 +136,17 @@ static void freeblock (MemHeader *block) {
}
}
void *debug_realloc (void *b, size_t oldsize, size_t size) {
MemHeader *block = cast(MemHeader *, b);
int i;
ASSERT(checkBlocks());
if (!marker[0]) memset(marker, MARK, MARKSIZE);
if (block == NULL) {
oldsize = 0;
} else {
block--; /* go to real header */
ASSERT(block->d.mark == MARK4);
ASSERT(oldsize == block->d.size);
for (i = 0; i < MARKSIZE; i++) /* check marks after block */
ASSERT (cast(char *, b)[oldsize + i] == MARK);
ASSERT(!memcmp(block->mark, marker, MARKSIZE))
ASSERT(oldsize == block->size);
ASSERT(!memcmp(cast(char *, b)+oldsize, marker, MARKSIZE));
}
if (size == 0) {
freeblock(block);
......@@ -108,7 +155,6 @@ void *debug_realloc (void *b, size_t oldsize, size_t size) {
return NULL; /* fake a memory allocation error */
else {
MemHeader *newblock;
int i;
size_t commonsize = (oldsize < size) ? oldsize : size;
size_t realsize = sizeof(MemHeader) + size + MARKSIZE;
newblock = cast(MemHeader *, c_malloc(realsize)); /* alloc a new block */
......@@ -119,12 +165,14 @@ void *debug_realloc (void *b, size_t oldsize, size_t size) {
freeblock(block); /* erase (and check) old copy */
}
/* initialize new part of the block with something weird */
if (size > commonsize)
fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize);
/* initialize marks after block */
newblock->d.mark = MARK4;
newblock->d.size = size;
for (i = 0; i < MARKSIZE; i++)
cast(char *, newblock + 1)[size + i] = MARK;
memset(newblock->mark, MARK, MARKSIZE);
newblock->size = size;
newblock->next = mc.start;
mc.start = newblock;
memset(cast(char *, newblock + 1)+ size, MARK, MARKSIZE);
mc.total += size;
if (mc.total > mc.maxmem)
mc.maxmem = mc.total;
......
......@@ -712,10 +712,5 @@ static void base_open (lua_State *L) {
LUALIB_API int luaopen_base (lua_State *L) {
base_open(L);
#if LUA_OPTIMIZE_MEMORY == 0
luaL_register(L, LUA_COLIBNAME, co_funcs);
return 2;
#else
return 1;
#endif
}
......@@ -17,6 +17,8 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#include "lstring.h"
#include "lflash.h"
#include "user_modules.h"
......@@ -26,6 +28,39 @@ static int db_getregistry (lua_State *L) {
return 1;
}
static int db_getstrings (lua_State *L) {
size_t i,n;
stringtable *tb;
GCObject *o;
#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER)
const char *opt = lua_tolstring (L, 1, &n);
if (n==3 && memcmp(opt, "ROM", 4) == 0) {
if (G(L)->ROstrt.hash == NULL)
return 0;
tb = &G(L)->ROstrt;
}
else
#endif
tb = &G(L)->strt;
lua_settop(L, 0);
lua_createtable(L, tb->nuse, 0); /* create table the same size as the strt */
for (i=0, n=1; i<tb->size; i++) {
for(o = tb->hash[i]; o; o=o->gch.next) {
TString *ts =cast(TString *, o);
lua_pushnil(L);
setsvalue2s(L, L->top-1, ts);
lua_rawseti(L, -2, n++); /* enumerate the strt, adding elements */
}
}
lua_getfield(L, LUA_GLOBALSINDEX, "table");
lua_getfield(L, -1, "sort"); /* look up table.sort function */
lua_replace(L, -2); /* dump the table table */
lua_pushvalue(L, -2); /* duplicate the strt_copy ref */
lua_call(L, 1, 0); /* table.sort(strt_copy) */
return 1;
}
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
static int db_getmetatable (lua_State *L) {
......@@ -395,6 +430,7 @@ const LUA_REG_TYPE dblib[] = {
{LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)},
#endif
{LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)},
{LSTRKEY("getstrings"), LFUNCVAL(db_getstrings)},
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
{LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)},
{LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)},
......
/*
** $Id: lflash.c
** See Copyright Notice in lua.h
*/
#define lflash_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#ifdef LUA_FLASH_STORE
#include "lobject.h"
#include "lauxlib.h"
#include "lstate.h"
#include "lfunc.h"
#include "lflash.h"
#include "platform.h"
#include "vfs.h"
#include "c_fcntl.h"
#include "c_stdio.h"
#include "c_stdlib.h"
#include "c_string.h"
/*
* Flash memory is a fixed memory addressable block that is serially allocated by the
* luac build process and the out image can be downloaded into SPIFSS and loaded into
* flash with a node.flash.load() command. See luac_cross/lflashimg.c for the build
* process.
*/
static char *flashAddr;
static uint32_t flashAddrPhys;
static uint32_t flashSector;
static uint32_t curOffset;
#define ALIGN(s) (((s)+sizeof(size_t)-1) & ((size_t) (- (signed) sizeof(size_t))))
#define ALIGN_BITS(s) (((uint32_t)s) & (sizeof(size_t)-1))
#define ALL_SET cast(uint32_t, -1)
#define FLASH_SIZE LUA_FLASH_STORE
#define FLASH_PAGE_SIZE INTERNAL_FLASH_SECTOR_SIZE
#define FLASH_PAGES (FLASH_SIZE/FLASH_PAGE_SIZE)
#define BREAK_ON_STARTUP_PIN 1 // GPIO 5 or setting to 0 will disable pin startup
#ifdef NODE_DEBUG
extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
void dumpStrt(stringtable *tb, const char *type) {
int i,j;
GCObject *o;
NODE_DBG("\nDumping %s String table\n\n========================\n", type);
NODE_DBG("No of elements: %d\nSize of table: %d\n", tb->nuse, tb->size);
for (i=0; i<tb->size; i++)
for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) {
TString *ts =cast(TString *, o);
NODE_DBG("%5d %5d %08x %08x %5d %1s %s\n",
i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len,
ts_isreadonly(ts) ? "R" : " ", getstr(ts));
}
}
LUA_API void dumpStrings(lua_State *L) {
dumpStrt(&G(L)->strt, "RAM");
if (G(L)->ROstrt.hash)
dumpStrt(&G(L)->ROstrt, "ROM");
}
#endif
/* =====================================================================================
* The next 4 functions: flashPosition, flashSetPosition, flashBlock and flashErase
* wrap writing to flash. The last two are platform dependent. Also note that any
* writes are suppressed if the global writeToFlash is false. This is used in
* phase I where the pass is used to size the structures in flash.
*/
static char *flashPosition(void){
return flashAddr + curOffset;
}
static char *flashSetPosition(uint32_t offset){
NODE_DBG("flashSetPosition(%04x)\n", offset);
curOffset = offset;
return flashPosition();
}
static char *flashBlock(const void* b, size_t size) {
void *cur = flashPosition();
NODE_DBG("flashBlock((%04x),%08x,%04x)\n", curOffset,b,size);
lua_assert(ALIGN_BITS(b) == 0 && ALIGN_BITS(size) == 0);
platform_flash_write(b, flashAddrPhys+curOffset, size);
curOffset += size;
return cur;
}
static void flashErase(uint32_t start, uint32_t end){
int i;
if (start == -1) start = FLASH_PAGES - 1;
if (end == -1) end = FLASH_PAGES - 1;
NODE_DBG("flashErase(%04x,%04x)\n", flashSector+start, flashSector+end);
for (i = start; i<=end; i++)
platform_flash_erase_sector( flashSector + i );
}
/* =====================================================================================
* Hook in user_main.c to allocate flash memory for the lua flash store
*/
void luaN_user_init(void) {
curOffset = 0;
flashSector = platform_flash_reserve_section( FLASH_SIZE, &flashAddrPhys );
flashAddr = cast(char *,platform_flash_phys2mapped(flashAddrPhys));
NODE_DBG("Flash initialised: %x %08x\n", flashSector, flashAddr);
}
/*
* Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed
*/
LUAI_FUNC void luaN_init (lua_State *L) {
FlashHeader *fh = cast(FlashHeader *, flashAddr);
if (fh->flash_sig == FLASH_SIG &&
fh->pROhash != ALL_SET &&
fh->mainProto != ALL_SET) {
G(L)->ROstrt.hash = cast(GCObject **, fh->pROhash);
G(L)->ROstrt.nuse = fh->nROuse ;
G(L)->ROstrt.size = fh->nROsize;
G(L)->ROpvmain = cast(Proto *,fh->mainProto);
}
}
#define BYTE_OFFSET(t,f) cast(size_t, &(cast(t *, NULL)->f))
/*
* Rehook address chain to correct Flash byte addressed within the mapped adress space
* Note that on input each 32-bit address field is split into 2×16-bit subfields
* - the lu_int16 offset of the target address being referenced
* - the lu_int16 offset of the next address pointer.
*/
static int rebuild_core (int fd, uint32_t size, lu_int32 *buf) {
int bi; /* byte offset into memory mapped LFS of current buffer */
int wNextOffset = BYTE_OFFSET(FlashHeader,mainProto)/sizeof(lu_int32);
int wj; /* word offset into current input buffer */
for (bi = 0; bi < size; bi += FLASH_PAGE_SIZE) {
int wi = bi / sizeof(lu_int32);
int blen = ((bi + FLASH_PAGE_SIZE) < size) ? FLASH_PAGE_SIZE : size - bi;
int wlen = blen / sizeof(lu_int32);
if (vfs_read(fd, buf , blen) != blen)
return 0;
for (wj = 0; wj < wlen; wj++) {
if ((wi + wj) == wNextOffset) { /* this word is the next linked address */
int wTargetOffset = buf[wj]&0xFFFF;
wNextOffset = buf[wj]>>16;
lua_assert(!wNextOffset || (wNextOffset>(wi+wj) && wNextOffset<size/sizeof(lu_int32)));
buf[wj] = cast(lu_int32, flashAddr + wTargetOffset*sizeof(lu_int32));
}
}
flashBlock(buf, blen);
}
return size;
}
/*
* Library function called by node.flash.load(filename).
*/
LUALIB_API int luaN_reload_reboot (lua_State *L) {
int fd, status;
FlashHeader fh;
const char *fn = lua_tostring(L, 1);
if (!fn || !(fd = vfs_open(fn, "r")))
return 0;
if (vfs_read(fd, &fh, sizeof(fh)) != sizeof(fh) ||
fh.flash_sig != FLASH_SIG)
return 0;
if (vfs_lseek(fd, -1, VFS_SEEK_END) != fh.flash_size-1 ||
vfs_lseek(fd, 0, VFS_SEEK_SET) != 0)
return 0;
lu_int32 *buffer = luaM_newvector(L, FLASH_PAGE_SIZE / sizeof(lu_int32), lu_int32);
/*
* This is the point of no return. We attempt to rebuild the flash. If there
* are any problems them the Flash is going to be corrupt, so the only fallback
* is to erase it and reboot with a clean but blank flash. Otherwise the reboot
* will load the new LFS.
*
* Note that the Lua state is not passed into the lua core because from this
* point on, we make no calls on the Lua RTS.
*/
flashErase(0,-1);
if (rebuild_core(fd, fh.flash_size, buffer) != fh.flash_size)
flashErase(0,-1);
/*
* Forcing a H/W timeout is the only robust way to insure that other interrupts
* and callbacks don't fire and attempt to reference to old LFS context.
*/
while (1) {}
return 0;
}
/*
* Return a C closure pointing to the Flash Index function
*/
LUAI_FUNC int luaN_index (lua_State *L) {
int i;
if(G(L)->ROpvmain) {
Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L)));
cl->l.p = G(L)->ROpvmain;
lua_settop(L, 1);
setclvalue(L, L->top-1, cl);
return 1;
}
return 0;
}
#endif
......@@ -146,7 +146,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->k, f->sizek, TValue);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
if (!proto_is_readonly(f)) {
if (!proto_isreadonly(f)) {
luaM_freearray(L, f->code, f->sizecode, Instruction);
#ifdef LUA_OPTIMIZE_DEBUG
if (f->packedlineinfo) {
......
......@@ -18,9 +18,6 @@
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
cast(int, sizeof(TValue *)*((n)-1)))
#define proto_readonly(p) l_setbit((p)->marked, READONLYBIT)
#define proto_is_readonly(p) testbit((p)->marked, READONLYBIT)
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
......
......@@ -28,6 +28,9 @@
#define GCSWEEPCOST 10
#define GCFINALIZECOST 100
#if READONLYMASK != (1<<READONLYBIT) || (defined(LUA_FLASH_STORE) && LFSMASK != (1<<LFSBIT))
#error "lgc.h and object.h out of sync on READONLYMASK / LFSMASK"
#endif
#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
......@@ -37,7 +40,7 @@
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
#define stringmark(s) if (!isLFSobject(&(s)->tsv)) {reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT);}
#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
......@@ -61,12 +64,17 @@
static void removeentry (Node *n) {
lua_assert(ttisnil(gval(n)));
if (iscollectable(gkey(n)))
if (ttype(gkey(n)) != LUA_TDEADKEY && iscollectable(gkey(n)))
lua_assert(!isLFSobject(&((gkey(n))->value.gc->gch)));
setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
}
static void reallymarkobject (global_State *g, GCObject *o) {
/* don't mark LFS Protos (or strings) */
if (o->gch.tt == LUA_TPROTO && isLFSobject(&(o->gch)))
return;
lua_assert(iswhite(o) && !isdead(g, o));
white2gray(o);
switch (o->gch.tt) {
......@@ -180,6 +188,8 @@ static int traversetable (global_State *g, Table *h) {
while (i--)
markvalue(g, &h->array[i]);
}
if (luaH_isdummy (h->node))
return weakkey || weakvalue;
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
......@@ -202,6 +212,8 @@ static int traversetable (global_State *g, Table *h) {
*/
static void traverseproto (global_State *g, Proto *f) {
int i;
if (isLFSobject(f))
return; /* don't traverse Protos in LFS */
if (f->source) stringmark(f->source);
for (i=0; i<f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
......@@ -317,7 +329,7 @@ static l_mem propagatemark (global_State *g) {
sizeof(TValue) * p->sizek +
sizeof(LocVar) * p->sizelocvars +
sizeof(TString *) * p->sizeupvalues +
(proto_is_readonly(p) ? 0 : sizeof(Instruction) * p->sizecode +
(proto_isreadonly(p) ? 0 : sizeof(Instruction) * p->sizecode +
#ifdef LUA_OPTIMIZE_DEBUG
(p->packedlineinfo ?
c_strlen(cast(char *, p->packedlineinfo))+1 :
......@@ -388,7 +400,10 @@ static void cleartable (GCObject *l) {
static void freeobj (lua_State *L, GCObject *o) {
switch (o->gch.tt) {
case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
case LUA_TPROTO:
lua_assert(!isLFSobject(&(o->gch)));
luaF_freeproto(L, gco2p(o));
break;
case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
......@@ -398,6 +413,7 @@ static void freeobj (lua_State *L, GCObject *o) {
break;
}
case LUA_TSTRING: {
lua_assert(!isLFSobject(&(o->gch)));
G(L)->strt.nuse--;
luaM_freemem(L, o, sizestring(gco2ts(o)));
break;
......@@ -420,6 +436,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
global_State *g = G(L);
int deadmask = otherwhite(g);
while ((curr = *p) != NULL && count-- > 0) {
lua_assert(!isLFSobject(&(curr->gch)) || curr->gch.tt == LUA_TTHREAD);
if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
sweepwholelist(L, &gco2th(curr)->openupval);
if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
......@@ -538,7 +555,7 @@ static void atomic (lua_State *L) {
size_t udsize; /* total size of userdata to be finalized */
/* remark occasional upvalues of (maybe) dead threads */
remarkupvals(g);
/* traverse objects cautch by write barrier and by 'remarkupvals' */
/* traverse objects caucht by write barrier and by 'remarkupvals' */
propagateall(g);
/* remark weak tables */
g->gray = g->weak;
......@@ -694,10 +711,10 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
lua_assert(ttype(&o->gch) != LUA_TTABLE);
lua_assert(o->gch.tt != LUA_TTABLE);
/* must keep invariant? */
if (g->gcstate == GCSpropagate)
reallymarkobject(g, v); /* restore invariant */
reallymarkobject(g, v); /* Restore invariant */
else /* don't mind */
makewhite(g, o); /* mark as white just to avoid other barriers */
}
......
......@@ -79,6 +79,7 @@
#define VALUEWEAKBIT 4
#define FIXEDBIT 5
#define SFIXEDBIT 6
#define LFSBIT 6
#define READONLYBIT 7
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
......@@ -100,6 +101,13 @@
#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT)
#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT)
#define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT)
#ifdef LUA_FLASH_STORE
#define isLFSobject(x) testbit((x)->marked, LFSBIT)
#define stringfix(s) if (!test2bits((s)->tsv.marked, FIXEDBIT, LFSBIT)) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#else
#define isLFSobject(x) (0)
#define stringfix(s) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#endif
#define luaC_checkGC(L) { \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment