Browse Source

LFS patch updates following review II and testing

TerryE 5 years ago
parent
commit
4f21224d56

+ 5 - 11
app/coap/endpoints.c

@@ -162,7 +162,8 @@ end:
     return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
 }
 
-extern lua_Load gLoad;
+extern int lua_put_line(const char *s, size_t l);
+
 static const coap_endpoint_path_t path_command = {2, {"v1", "c"}};
 static int handle_post_command(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
 {
@@ -170,16 +171,9 @@ static int handle_post_command(const coap_endpoint_t *ep, coap_rw_buffer_t *scra
         return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_TEXT_PLAIN);
     if (inpkt->payload.len > 0)
     {
-        lua_Load *load = &gLoad;
-        if(load->line_position == 0){
-            coap_buffer_to_string(load->line, load->len,&inpkt->payload);
-            load->line_position = c_strlen(load->line)+1;
-            // load->line[load->line_position-1] = '\n';
-            // load->line[load->line_position] = 0;
-            // load->line_position++;
-            load->done = 1;
-            NODE_DBG("Get command:\n");
-            NODE_DBG(load->line); // buggy here
+        char line[LUA_MAXINPUT];
+        if (!coap_buffer_to_string(line, LUA_MAXINPUT, &inpkt->payload) &&
+            lua_put_line(line, c_strlen(line))) {
             NODE_DBG("\nResult(if any):\n");
             system_os_post (LUA_TASK_PRIO, LUA_PROCESS_LINE_SIG, 0);
         }

+ 1 - 1
app/esp-gdbstub/Makefile

@@ -23,7 +23,7 @@ endif
 #   makefile at its root level - these are then overridden
 #   for a subtree within the makefile rooted therein
 #
-#DEFINES += 
+#DEFINES += -DGDBSTUB_REDIRECT_CONSOLE_OUTPUT 
 
 #############################################################
 # Recursion Magic - Don't touch this!!

+ 80 - 61
app/include/user_config.h

@@ -1,46 +1,48 @@
 #ifndef __USER_CONFIG_H__
 #define __USER_CONFIG_H__
 
-// The firmware supports a range of Flash sizes, though 4Mbyte seems to be 
-// currently the most common.  Current builds include a discovery function
+// The firmware supports a range of Flash sizes, though 4 Mbyte seems to be
+// the most common currently.  NodeMCU builds include a discovery function
 // which is enabled by FLASH_AUTOSIZE, but you can override this by commenting
 // this out and enabling the explicitly size, e.g. FLASH_4M.  Valid sizes are
 // FLASH_512K, FLASH_1M, FLASH_2M, FLASH_4M, FLASH_8M, FLASH_16M.
-  
+
 #define FLASH_AUTOSIZE
 //#define FLASH_4M
 
 
-// The firmware now selects a baudrate of 115,200 by default, but the driver also 
-// includes automatic baud rate detection at start-up by default.  If you want to
-// change the default rate then vaild rates are  300, 600, 1200, 2400, 4800, 9600, 
-// 19200, 31250, 38400, 57600, 74880, 115200, 230400, 256000, 460800 [, 921600, 
-// 1843200, 368640].  Note that the last 3 rates are not recommended as these 
-// might be unreliable.
- 
+// The firmware now selects a baudrate of 115,200 by default, but the driver
+// also includes automatic baud rate detection at start-up.  If you want to change
+// the default rate then vaild rates are  300, 600, 1200, 2400, 4800, 9600, 19200,
+// 31250, 38400, 57600, 74880, 115200, 230400, 256000, 460800 [, 921600, 1843200,
+// 368640].  Note that the last 3 rates are not recommended as these might be
+// unreliable, but 460800 seems to work well for most USB-serial devices.
+
 #define BIT_RATE_DEFAULT BIT_RATE_115200
-#define BIT_RATE_AUTOBAUD
+//#define BIT_RATE_AUTOBAUD
 
 
 // Three separate build variants are now supported. The main difference is in the
 // processing of numeric data types.  If LUA_NUMBER_INTEGRAL is defined, then
-// all numeric calculations are done in integer, with divide being an integer 
+// all numeric calculations are done in integer, with divide being an integer
 // operations, and decimal fraction constants are illegal.  Otherwise all
 // numeric operations use floating point, though they are exact for integer
-// expressions < 2^53.  The main advantage of INTEGRAL builds is that the basic
-// internal storage unit, the TValue, is 8 bytes long, rather than the default 
-// on floating point builds of 16 bytes.  We have now also introduced an 
-// experimental option LUA_PACK_TVALUES which reduces the floating point TValues
-// to 12 bytes without any performance impact.
+// expressions < 2^53.
+
+// The main advantage of INTEGRAL builds is that the basic internal storage unit,
+// the TValue, is 8 bytes long.  We have now reduced the size of FP TValues to
+// 12 bytes rather than the previous 16 as this gives a material RAM saving with
+// no performance loss.  However, you can define LUA_DWORD_ALIGNED_TVALUES and
+// this will force 16 byte TValues on FP builds.
 
 //#define LUA_NUMBER_INTEGRAL
-//#define LUA_PACK_TVALUES
+//#define LUA_DWORD_ALIGNED_TVALUES
 
 
 // The Lua Flash Store (LFS) allows you to store Lua code in Flash memory and
-// the Lua VMS will execute this code directly from flash without needing any 
+// the Lua VMS will execute this code directly from flash without needing any
 // RAM overhead.  If you want to enable LFS then set the following define to
-// the size of the store that you need.  This can be any multiple of 4kB up to 
+// the size of the store that you need.  This can be any multiple of 4kB up to
 // a maximum 256Kb.
 
 //#define LUA_FLASH_STORE 0x10000
@@ -48,45 +50,45 @@
 
 // By default Lua executes the file init.lua at start up.  The following
 // define allows you to replace this with an alternative startup.  Warning:
-// you must protect this execution otherwise you will enter a panic loop.
+// you must protect this execution otherwise you will enter a panic loop;
+// the simplest way is to wrap the action in a function invoked by a pcall.
 // The example provided executes the LFS module "_init" at startup or fails
 // through to the interactive prompt.
-// ********* WARNING THIS OPTION ISN'T CURRENTLY WORKING
-//#define LUA_INIT_STRING "local fi=node.flashindex; return pcall(fi and fi'_init')"
-// ********* WARNING THIS OPTION ISN'T CURRENTLY WORKING
+
+//#define LUA_INIT_STRING "pcall(function() node.flashindex'_init'() end)"
 
 
 // NodeMCU supports two file systems: SPIFFS and FATFS, the first is available
 // on all ESP8266 modules.  The latter requires extra H/W so is less common.
-// If you use SPIFFS then there are a number of options which impact the 
-// RAM overhead and performance of the file system.  
-//
+// If you use SPIFFS then there are a number of options which impact the
+// RAM overhead and performance of the file system.
+
 // If you use the spiffsimg tool to create your own FS images on your dev PC
 // then we recommend that you fix the location and size of the FS, allowing
 // some headroom for rebuilding flash images and LFS.  As an alternative to
-// fixing the size of the FS, you can force the SPIFFS file system to end on 
+// fixing the size of the FS, you can force the SPIFFS file system to end on
 // the next 1Mb boundary.  This is useful for certain OTA scenarios.  In
-// general, limiting the size of the FS only to what your application needs 
+// general, limiting the size of the FS only to what your application needs
 // gives the fastest start-up and imaging times.
 
 #define BUILD_SPIFFS
-//#define BUILD_FATFS
-
 //#define SPIFFS_FIXED_LOCATION        0x100000
-//#define SPIFFS_MAX_FILESYSTEM_SIZE    0x10000	
+//#define SPIFFS_MAX_FILESYSTEM_SIZE    0x20000	
 //#define SPIFFS_SIZE_1M_BOUNDARY
-#define SPIFFS_CACHE 1          // Enable if you use you SPIFFS in R/W mode 
+#define SPIFFS_CACHE 1          // Enable if you use you SPIFFS in R/W mode
 #define SPIFFS_MAX_OPEN_FILES 4 // maximum number of open files for SPIFFS
 #define FS_OBJ_NAME_LEN 31      // maximum length of a filename
 
+//#define BUILD_FATFS
+
 
 // The HTTPS stack requires client SSL to be enabled.  The SSL buffer size is
-// used only for espconn-layer secure connections, and is ignored otherwise.  
+// used only for espconn-layer secure connections, and is ignored otherwise.
 // Some HTTPS  applications require a larger buffer size to work.  See
 // https://github.com/nodemcu/nodemcu-firmware/issues/1457 for details.
-// The SHA2 and MD2 libraries are also used by the crypto functions.  The 
-// MD2 function are implemented in the ROM BIOS, and the SHA2 by NodeMCU
-// code, so only enable SHA2 if you need this functionality.
+// The SHA2 and MD2 libraries are also optionally used by the crypto functions.
+// The SHA1 and MD5 function are implemented in the ROM BIOS. The MD2 and SHA2
+// are by firmware code, and can be enabled if you need this functionality.
 
 //#define CLIENT_SSL_ENABLE
 //#define MD2_ENABLE
@@ -97,15 +99,15 @@
 // GPIO_INTERRUPT_ENABLE needs to be defined if your application uses the
 // gpio.trig() or related GPIO interrupt service routine code.  Likewise the
 // GPIO interrupt hook is requited for a few modules such as rotary.  If you
-// don't require this functionality, then we recommend commenting out these 
-// options which removes any associated runtime overhead. 
+// don't require this functionality, then commenting out these options out
+// will remove any associated runtime overhead.
 
 #define GPIO_INTERRUPT_ENABLE
 #define GPIO_INTERRUPT_HOOK_ENABLE
 
 
-// If your application uses the light sleep functions and you wish the 
-// firmware to manage timer rescheduling over sleeps (the CPU clock is 
+// If your application uses the light sleep functions and you wish the
+// firmware to manage timer rescheduling over sleeps (the CPU clock is
 // suspended so timers get out of sync) then enable the following options
 
 //#define ENABLE_TIMER_SUSPEND
@@ -115,24 +117,32 @@
 // The WiFi module optionally offers an enhanced level of WiFi connection
 // management, using internal timer callbacks.  Whilst many Lua developers
 // prefer to implement equivalent features in Lua, others will prefer the
-// Wifi module to do this for them.  Uncomment the following to enable 
-// this functionality. The event sub-options are ignore if the SMART 
-// functionality is not enabled.
+// Wifi module to do this for them.  Uncomment the following to enable
+// this functionality.  See the relevant WiFi module documentation for 
+// further details, as the scope of these changes is not obvious.
 
+//  Enable the wifi.startsmart() and wifi.stopsmart()  
 //#define WIFI_SMART_ENABLE
+
+//  Enable wifi.sta.config() event callbacks
 #define WIFI_SDK_EVENT_MONITOR_ENABLE
+
+//  Enable creation on the wifi.eventmon.reason table
 #define WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
 
+//  Enable use of the WiFi.monitor sub-module
+//#define LUA_USE_MODULES_WIFI_MONITOR
+
 
 // Whilst the DNS client details can be configured through the WiFi API,
 // the defaults can be exposed temporarily during start-up.  The following
 // WIFI_STA options allow you to configure this in the firmware.  If the
-// WIFI_STA_HOSTNAME is not defined then the hostname will default to 
-// to the last 3 octets (6 hexadecimal digits) of MAC address with the 
+// WIFI_STA_HOSTNAME is not defined then the hostname will default to
+// to the last 3 octets (6 hexadecimal digits) of MAC address with the
 // prefix "NODE-".  If it is defined then the hostname must only contain
 // alphanumeric characters. If you are imaging multiple modules with this
-// firmware then you must also define WIFI_STA_HOSTNAME_APPEND_MAC to 
-// append the last 3 octets of the MAC address.  Note that the total 
+// firmware then you must also define WIFI_STA_HOSTNAME_APPEND_MAC to
+// append the last 3 octets of the MAC address.  Note that the total
 // Hostname MUST be 32 chars or less.
 
 //#define WIFI_STA_HOSTNAME "NodeMCU"
@@ -145,7 +155,7 @@
 #define ENDUSER_SETUP_AP_SSID "SetupGadget"
 
 
-// The following sections are only relevent for those developers who are 
+// The following sections are only relevent for those developers who are
 // developing modules or core Lua changes and configure how extra diagnostics
 // are enabled in the firmware. These should only be configured if you are
 // building your own custom firmware and have full access to the firmware
@@ -153,18 +163,18 @@
 
 // Enabling DEVELOPMENT_TOOLS adds the asserts in LUA and also some useful
 // extras to the node module. These are silent in normal operation and so can
-// be enabled without any harm (except for the code size increase and slight 
-// slowdown). If you want to use the remote GDB to handle breaks and failed 
+// be enabled without any harm (except for the code size increase and slight
+// slowdown). If you want to use the remote GDB to handle breaks and failed
 // assertions then enable the DEVELOPMENT_USE GDB option.  A supplimentary
-// define DEVELOPMENT_BREAK_ON_STARTUP_PIN allows you to define a GPIO pin, 
+// define DEVELOPMENT_BREAK_ON_STARTUP_PIN allows you to define a GPIO pin,
 // which if pulled low at start-up will immediately initiate a GDB session.
 
-// The DEVELOP_VERSION option enables lots of debug output, and is normally 
+// The DEVELOP_VERSION option enables lots of debug output, and is normally
 // only used by hardcore developers.
 
-// These options can be enabled globally here or you can alternatively use 
+// These options can be enabled globally here or you can alternatively use
 // the DEFINES variable in the relevant Makefile to set these on a per
-// directory basis. If you do this then you can also set the corresponding 
+// directory basis. If you do this then you can also set the corresponding
 // compile options (-O0 -ggdb) on a per directory as well.
 
 //#define DEVELOPMENT_TOOLS
@@ -196,19 +206,24 @@ extern void luaL_dbgbreak(void);
 #endif
 #endif
 
+#if !defined(LUA_NUMBER_INTEGRAL) && defined (LUA_DWORD_ALIGNED_TVALUES)
+  #define LUA_PACK_TVALUES
+#else
+  #undef LUA_PACK_TVALUES
+#endif
+
 #ifdef DEVELOP_VERSION
 #define NODE_DEBUG
 #define COAP_DEBUG
 #endif /* DEVELOP_VERSION */
 
-#define NODE_ERROR
-
 #ifdef NODE_DEBUG
 #define NODE_DBG dbg_printf
 #else
 #define NODE_DBG
 #endif	/* NODE_DEBUG */
 
+#define NODE_ERROR
 #ifdef NODE_ERROR
 #define NODE_ERR dbg_printf
 #else
@@ -218,9 +233,14 @@ extern void luaL_dbgbreak(void);
 // #define GPIO_SAFE_NO_INTR_ENABLE
 #define ICACHE_STORE_TYPEDEF_ATTR __attribute__((aligned(4),packed))
 #define ICACHE_STORE_ATTR __attribute__((aligned(4)))
-#define ICACHE_RAM_STRING(x) ICACHE_RAM_STRING2(x)
-#define ICACHE_RAM_STRING2(x) #x
-#define ICACHE_RAM_ATTR     __attribute__((section(".iram0.text." __FILE__ "." ICACHE_RAM_STRING(__LINE__))))
+#define ICACHE_STRING(x) ICACHE_STRING2(x)
+#define ICACHE_STRING2(x) #x
+#define ICACHE_RAM_ATTR \
+  __attribute__((section(".iram0.text." __FILE__ "." ICACHE_STRING(__LINE__))))
+#define ICACHE_FLASH_RESERVED_ATTR \
+  __attribute__((section(".irom.reserved." __FILE__ "." ICACHE_STRING(__LINE__)),\
+                 used,unused,aligned(INTERNAL_FLASH_SECTOR_SIZE)))
+
 #ifdef  GPIO_SAFE_NO_INTR_ENABLE
 #define NO_INTR_CODE ICACHE_RAM_ATTR __attribute__ ((noinline))
 #else
@@ -228,4 +248,3 @@ extern void luaL_dbgbreak(void);
 #endif
 
 #endif	/* __USER_CONFIG_H__ */
-

+ 0 - 12
app/libc/c_stdlib.c

@@ -15,18 +15,6 @@
 #include "c_stdlib.h"
 #include "c_types.h"
 #include "c_string.h"
-
-extern const char lua_init_value[];
-
-const char *c_getenv(const char *__string)
-{
-    if (c_strcmp(__string, "LUA_INIT") == 0)
-    {
-        return lua_init_value;
-    }
-    return NULL;
-}
-
 #include <_ansi.h>
 //#include <reent.h>
 //#include "mprec.h"

+ 1 - 2
app/libc/c_stdlib.h

@@ -46,8 +46,7 @@
 
 // void c_exit(int);
 
-// c_getenv() get env "LUA_INIT" string for lua initialization.
-const char *c_getenv(const char *__string);
+//const char *c_getenv(const char *__string);
 
 // void *c_malloc(size_t __size);
 // void *c_zalloc(size_t __size);

+ 2 - 2
app/lua/lauxlib.c

@@ -48,7 +48,7 @@
 //#define DEBUG_ALLOCATOR
 #ifdef DEBUG_ALLOCATOR 
 #ifdef LUA_CROSS_COMPILER
-static void break_hook(void)
+static void break_hook(void) {}
 #define ASSERT(s) if (!(s)) {break_hook();}
 #else
 #define ASSERT(s) if (!(s)) {asm ("break 0,0" ::);}
@@ -186,7 +186,7 @@ void *debug_realloc (void *b, size_t oldsize, size_t size) {
 /* }====================================================================== */
 #else
 #define this_realloc(p,os,s) c_realloc(p,s)
-#endif
+#endif /* DEBUG_ALLOCATOR */
 
 /*
 ** {======================================================

+ 25 - 21
app/lua/lflash.c

@@ -41,7 +41,7 @@ static uint32_t curOffset;
 #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 
+char flash_region_base[FLASH_SIZE] ICACHE_FLASH_RESERVED_ATTR;
 
 #ifdef NODE_DEBUG
 extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
@@ -94,6 +94,7 @@ static char *flashBlock(const void* b, size_t size)  {
   return cur;
 }
 
+
 static void flashErase(uint32_t start, uint32_t end){
   int i;
   if (start == -1) start = FLASH_PAGES - 1;
@@ -104,38 +105,41 @@ static void flashErase(uint32_t start, uint32_t end){
 }
 
 
-/* =====================================================================================
- * Hook in user_main.c to allocate flash memory for the lua flash store
- */
-extern void luaL_dbgbreak(void);   //<<<<<<<<<<<<< Temp
-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); 
-//  luaL_dbgbreak();      //<<<<<<<<<<<<< Temp
-}
-
-
 /*
  * Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed
  */  
 LUAI_FUNC void luaN_init (lua_State *L) {
+//  luaL_dbgbreak();
+  curOffset      = 0;
+  flashAddr     = flash_region_base;
+  flashAddrPhys = platform_flash_mapped2phys((uint32_t)flashAddr);
+  flashSector   = platform_flash_get_sector_of_address(flashAddrPhys);
   FlashHeader *fh = cast(FlashHeader *, flashAddr);
+
   /*
    * For the LFS to be valid, its signature has to be correct for this build variant,
    * thr ROhash and main proto fields must be defined and the main proto address 
    * be within the LFS address bounds. (This last check is primarily to detect the
    * direct imaging of an absolute LFS with the wrong base address. 
    */
-  if ((fh->flash_sig & (~FLASH_SIG_ABSOLUTE)) == FLASH_SIG && 
-      fh->pROhash   != ALL_SET &&
-      ((fh->mainProto - cast(FlashAddr, fh)) < fh->flash_size)) {
-    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);
+
+  if ((fh->flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG ) {
+    NODE_ERR("Flash sig not correct: %p vs %p\n",
+       fh->flash_sig & (~FLASH_SIG_ABSOLUTE), FLASH_SIG); 
+    return;
+  }
+
+  if (fh->pROhash == ALL_SET ||
+      ((fh->mainProto - cast(FlashAddr, fh)) >= fh->flash_size)) {
+    NODE_ERR("Flash size check failed: %p vs 0xFFFFFFFF; %p >= %p\n",
+       fh->mainProto - cast(FlashAddr, fh), fh->flash_size);
+    return;
   }
+ 
+  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))

+ 2 - 3
app/lua/lflash.h

@@ -10,14 +10,14 @@
 #include "lstate.h"
 #include "lzio.h"
 
-#ifdef LUA_NUNBER_INTEGRAL
+#ifdef LUA_NUMBER_INTEGRAL
 # define FLASH_SIG_B1 0x02
 #else
 # define FLASH_SIG_B1 0x00
 #endif
 
 #ifdef LUA_PACK_TVALUES
-#ifdef LUA_NUNBER_INTEGRAL
+#ifdef LUA_NUMBER_INTEGRAL
 #error "LUA_PACK_TVALUES is only valid for Floating point builds" 
 #endif
 # define FLASH_SIG_B2 0x04
@@ -40,7 +40,6 @@ typedef struct {
   lu_int32  fill2;          /* reserved */
 } FlashHeader;
 
-void luaN_user_init(void);
 LUAI_FUNC void luaN_init (lua_State *L);
 LUAI_FUNC int  luaN_flashSetup (lua_State *L);
 LUAI_FUNC int  luaN_reload_reboot (lua_State *L);

+ 2 - 1
app/lua/lgc.c

@@ -65,7 +65,8 @@
 static void removeentry (Node *n) {
   lua_assert(ttisnil(gval(n)));
   if (ttype(gkey(n)) != LUA_TDEADKEY && iscollectable(gkey(n)))
-    lua_assert(!isLFSobject(&((gkey(n))->value.gc->gch)));
+//  The gkey is always in RAM so it can be marked as DEAD even though it
+//  refers to an LFS object.
     setttype(gkey(n), LUA_TDEADKEY);  /* dead key; remove it */
 }
 

+ 1 - 1
app/lua/loadlib.c

@@ -613,7 +613,7 @@ static int ll_seeall (lua_State *L) {
 
 static void setpath (lua_State *L, const char *fieldname, const char *envname,
                                    const char *def) {
-  const char *path = c_getenv(envname);
+  const char *path = NULL;  /* getenv(envname) not used in NodeMCU */;
   if (path == NULL)  /* no environment variable? */
     lua_pushstring(L, def);  /* use default */
   else {

+ 26 - 16
app/lua/lua.c

@@ -29,11 +29,9 @@
 
 lua_State *globalL = NULL;
 
-lua_Load gLoad;
-
+static lua_Load gLoad;
 static const char *progname = LUA_PROGNAME;
 
-
 static void l_message (const char *pname, const char *msg) {
 #if defined(LUA_USE_STDIO)
   if (pname) c_fprintf(c_stderr, "%s: ", pname);
@@ -237,19 +235,16 @@ static int runargs (lua_State *L, char **argv, int n) {
 }
 
 
-#ifdef LUA_INIT_STRING
-const char lua_init_value[] = LUA_INIT_STRING;
-#else
-const char lua_init_value[] = "@init.lua";
+#ifndef LUA_INIT_STRING
+#define LUA_INIT_STRING "@init.lua"
 #endif
 
 static int handle_luainit (lua_State *L) {
-  const char *init = c_getenv(LUA_INIT);
-  if (init == NULL) return 0;  /* status OK */
-  else if (init[0] == '@')
+  const char *init = LUA_INIT_STRING;
+  if (init[0] == '@')
     return dofsfile(L, init+1);
   else
-    return dostring(L, init, "=" LUA_INIT);
+    return dostring(L, init, LUA_INIT);
 }
 
 
@@ -284,7 +279,6 @@ static int pmain (lua_State *L) {
 
 static void dojob(lua_Load *load);
 static bool readline(lua_Load *load);
-char line_buffer[LUA_MAXINPUT];
 
 #ifdef LUA_RPC
 int main (int argc, char **argv) {
@@ -315,24 +309,39 @@ int lua_main (int argc, char **argv) {
   gLoad.L = L;
   gLoad.firstline = 1;
   gLoad.done = 0;
-  gLoad.line = line_buffer;
+  gLoad.line = c_malloc(LUA_MAXINPUT);
   gLoad.len = LUA_MAXINPUT;
   gLoad.line_position = 0;
   gLoad.prmt = get_prompt(L, 1);
 
   dojob(&gLoad);
 
-  NODE_DBG("Heap size::%d.\n",system_get_free_heap_size());
+  NODE_DBG("Heap size:%d.\n",system_get_free_heap_size());
   legc_set_mode( L, EGC_ALWAYS, 4096 );
   // legc_set_mode( L, EGC_ON_MEM_LIMIT, 4096 );
   // lua_close(L);
   return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
+int lua_put_line(const char *s, size_t l) {
+  if (s == NULL || ++l < LUA_MAXINPUT || gLoad.line_position > 0)
+    return 0;
+  c_memcpy(gLoad.line, s, l);
+  gLoad.line[l] = '\0';
+  gLoad.line_position = l;
+  gLoad.done = 1;
+  NODE_DBG("Get command: %s\n", gLoad.line);
+  return 1;
+}
+
 void lua_handle_input (bool force)
 {
-  while (gLoad.L && (force || readline (&gLoad)))
+  while (gLoad.L && (force || readline (&gLoad))) { 
+    NODE_DBG("Handle Input: first=%u, pos=%u, len=%u, actual=%u, line=%s\n", gLoad.firstline,
+              gLoad.line_position, gLoad.len, c_strlen(gLoad.line), gLoad.line);
     dojob (&gLoad);
+    force = false;
+  }
 }
 
 void donejob(lua_Load *load){
@@ -462,11 +471,12 @@ static bool readline(lua_Load *load){
         {
           /* Get a empty line, then go to get a new line */
           c_puts(load->prmt);
+          continue;
         } else {
           load->done = 1;
           need_dojob = true;
+          break;
         }
-        continue;
       }
 
       /* other control character or not an acsii character */

+ 1 - 1
app/lua/luac_cross/lflashimg.c

@@ -155,7 +155,7 @@ static void *fromFashAddr(FlashAddr a) {
  * Add a TS found in the Proto Load to the table at the ToS
  */
 static void addTS(lua_State *L, TString *ts) {
-  lua_assert(ttisstring(&(ts->tsv)));
+  lua_assert(ts->tsv.tt==LUA_TSTRING);
   lua_pushnil(L);
   setsvalue(L, L->top-1, ts);
   lua_pushinteger(L, 1);

+ 6 - 16
app/modules/node.c

@@ -169,26 +169,16 @@ static int node_heap( lua_State* L )
   return 1;
 }
 
-extern lua_Load gLoad;
+extern int  lua_put_line(const char *s, size_t l);
 extern bool user_process_input(bool force);
+
 // Lua: input("string")
-static int node_input( lua_State* L )
-{
+static int node_input( lua_State* L ) {
   size_t l = 0;
   const char *s = luaL_checklstring(L, 1, &l);
-  if (s != NULL && l > 0 && l < LUA_MAXINPUT - 1)
-  {
-    lua_Load *load = &gLoad;
-    if (load->line_position == 0) {
-      c_memcpy(load->line, s, l);
-      load->line[l + 1] = '\0';
-      load->line_position = c_strlen(load->line) + 1;
-      load->done = 1;
-      NODE_DBG("Get command:\n");
-      NODE_DBG(load->line); // buggy here
-      NODE_DBG("\nResult(if any):\n");
-      user_process_input(true);
-    }
+  if (lua_put_line(s, l)) {
+    NODE_DBG("Result (if any):\n");
+    user_process_input(true);
   }
   return 0;
 }

+ 11 - 43
app/platform/common.c

@@ -24,7 +24,7 @@ extern char _flash_used_end[];
 
 // Helper function: find the flash sector in which an address resides
 // Return the sector number, as well as the start and end address of the sector
-static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
+static uint32_t flash_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
 {
 #ifdef INTERNAL_FLASH_SECTOR_SIZE
   // All the sectors in the flash have the same size, so just align the address
@@ -53,7 +53,7 @@ static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t
 
 uint32_t platform_flash_get_sector_of_address( uint32_t addr )
 {
-  return flashh_find_sector( addr, NULL, NULL );
+  return flash_find_sector( addr, NULL, NULL );
 }
 
 uint32_t platform_flash_get_num_sectors(void)
@@ -67,54 +67,22 @@ uint32_t platform_flash_get_num_sectors(void)
 #endif // #ifdef INTERNAL_FLASH_SECTOR_SIZE
 }
 
-static uint32_t allocated = 0;
-static uint32_t phys_flash_used_end = 0;  //Phyiscal address of last byte in last flash used sector 
-
-uint32_t platform_flash_reserve_section( uint32_t regsize, uint32_t *start )
-{
-  // Return Flash sector no (and optional flash mapped address of first allocated byte)
-
-  if(phys_flash_used_end == 0) 
-    flashh_find_sector(platform_flash_mapped2phys( (uint32_t)_flash_used_end - 1), NULL, &phys_flash_used_end );
-
-  /* find sector and last byte address of previous allocation */
-  uint32_t end;
-  uint32_t sect = flashh_find_sector( phys_flash_used_end + allocated, NULL, &end );
-  if(start)
-    *start = end + 1;
-
-  /* allocated regions are always sector aligned */ 
-  flashh_find_sector( phys_flash_used_end + allocated + regsize, NULL, &end );
-  allocated = end - phys_flash_used_end;
-
-  NODE_DBG("Flash base: %08x %08x %08x\n", regsize, allocated, phys_flash_used_end);
-  return sect + 1;
-}
-
 uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
 {
   // Round the total used flash size to the closest flash block address
   uint32_t start, end, sect;
   NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end);
-#if 0
-  if(_flash_used_end>0){ // find the used sector
-    sect = flashh_find_sector( platform_flash_mapped2phys ( (uint32_t)_flash_used_end - 1), NULL, &end );
-    sect++;
-    start = end + 1;
-  }else{
-    sect = flashh_find_sector( 0, &start, NULL ); // find the first free sector
-  }
   if(_flash_used_end>0){ // find the used sector
-    uint32_t sta1, sec1;
-    sec1 = platform_flash_reserve_section( 0, &sta1 ); 
-    NODE_DBG("Flash base: %p %p %p %p\n", sect, start, sec1, sta1);
+    sect = flash_find_sector( platform_flash_mapped2phys ( (uint32_t)_flash_used_end - 1), NULL, &end );
+    if( psect )
+      *psect = sect + 1;
+    return end + 1;
+  } else {
+    sect = flash_find_sector( 0, &start, NULL ); // find the first free sector
+    if( psect )
+      *psect = sect;
+    return start;
   }
-#endif
-  sect = _flash_used_end ? platform_flash_reserve_section( 0, &start ) :
-                           flashh_find_sector( 0, &start, NULL );
-  if( psect )
-    *psect = sect;
-  return start;
 }
 
 uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size )

+ 4 - 2
app/platform/flash_api.c

@@ -116,10 +116,11 @@ bool flash_rom_set_size_type(uint8_t size)
     uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR;
     if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
     {
-        ((SPIFlashInfo *)(&data[0]))->size = size;
+        NODE_DBG("\nflash_rom_set_size_type(%u), was %u\n", size, ((SPIFlashInfo *)data)->size );
+        ((SPIFlashInfo *)data)->size = size;
         if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE))
         {
-            NODE_DBG("\nERASE SUCCESS\n");
+            NODE_DBG("\nSECTOR 0 ERASE SUCCESS\n");
         }
         if (SPI_FLASH_RESULT_OK == spi_flash_write(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
         {
@@ -266,6 +267,7 @@ bool flash_rom_set_speed(uint32_t speed)
     if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
     {
         ((SPIFlashInfo *)(&data[0]))->speed = speed_type;
+        NODE_DBG("\nflash_rom_set_speed(%u), was %u\n", speed_type, ((SPIFlashInfo *)(&data[0]))->speed );
         if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE))
         {
             NODE_DBG("\nERASE SUCCESS\n");

+ 14 - 16
app/platform/platform.c

@@ -879,7 +879,7 @@ uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t siz
   if(SPI_FLASH_RESULT_OK == r)
     return size;
   else{
-    NODE_ERR( "ERROR in flash_write: r=%d at %p\n", ( int )r, ( unsigned )toaddr);
+    NODE_ERR( "ERROR in flash_write: r=%d at %p\n", r, toaddr);
     return 0;
   }
 }
@@ -917,37 +917,35 @@ uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size )
   if(SPI_FLASH_RESULT_OK == r)
     return size;
   else{
-    NODE_ERR( "ERROR in flash_read: r=%d at %p\n", ( int )r, ( unsigned )fromaddr);
+    NODE_ERR( "ERROR in flash_read: r=%d at %p\n", r, fromaddr);
     return 0;
   }
 }
 
 int platform_flash_erase_sector( uint32_t sector_id )
 {
+  NODE_DBG( "flash_erase_sector(%u)\n", sector_id);
   system_soft_wdt_feed ();
   return flash_erase( sector_id ) == SPI_FLASH_RESULT_OK ? PLATFORM_OK : PLATFORM_ERR;
 }
 
-static uint32_t flash_map_meg_offset ()
-{
+static uint32_t flash_map_meg_offset (void) {
   uint32_t cache_ctrl = READ_PERI_REG(CACHE_FLASH_CTRL_REG);
   if (!(cache_ctrl & CACHE_FLASH_ACTIVE))
     return -1;
-  bool b0 = (cache_ctrl & CACHE_FLASH_MAPPED0) ? 1 : 0;
-  bool b1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 1 : 0;
-  return ((b1 << 1) | b0) * 0x100000;
+  uint32_t m0 = (cache_ctrl & CACHE_FLASH_MAPPED0) ? 0x100000 : 0;
+  uint32_t m1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 0x200000 : 0;
+  return m0 + m1;
 }
- 
-uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)
-{
- uint32_t meg = flash_map_meg_offset();
- return (meg&1) ? -1 : mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg ;
+
+uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)  {
+  uint32_t meg = flash_map_meg_offset();
+  return (meg&1) ? -1 : mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg ;
 }
 
-uint32_t platform_flash_phys2mapped (uint32_t phys_addr)
-{
- uint32_t meg = flash_map_meg_offset();
- return (meg&1) ? -1 : phys_addr + INTERNAL_FLASH_MAPPED_ADDRESS - meg;
+uint32_t platform_flash_phys2mapped (uint32_t phys_addr) {
+  uint32_t meg = flash_map_meg_offset();
+  return (meg&1) ? -1 : phys_addr + INTERNAL_FLASH_MAPPED_ADDRESS - meg;
 }
 
 void* platform_print_deprecation_note( const char *msg, const char *time_frame)

+ 2 - 4
app/platform/platform.h

@@ -268,11 +268,8 @@ uint32_t platform_eth_get_elapsed_time(void);
 // *****************************************************************************
 // Internal flash erase/write functions
 
-uint32_t platform_flash_reserve_section( uint32_t regsize, uint32_t *start );
 uint32_t platform_flash_get_first_free_block_address( uint32_t *psect );
 uint32_t platform_flash_get_sector_of_address( uint32_t addr );
-uint32_t platform_flash_mapped2phys (uint32_t mapped_addr);
-uint32_t platform_flash_phys2mapped (uint32_t phys_addr);
 uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size );
 uint32_t platform_flash_read( void *to, uint32_t fromaddr, uint32_t size );
 uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t size );
@@ -282,13 +279,14 @@ int platform_flash_erase_sector( uint32_t sector_id );
 
 /**
  * Translated a mapped address to a physical flash address, based on the
- * current flash cache mapping.
+ * current flash cache mapping, and v.v.
  * @param mapped_addr Address to translate (>= INTERNAL_FLASH_MAPPED_ADDRESS)
  * @return the corresponding physical flash address, or -1 if flash cache is
  *  not currently active.
  * @see Cache_Read_Enable.
  */
 uint32_t platform_flash_mapped2phys (uint32_t mapped_addr);
+uint32_t platform_flash_phys2mapped (uint32_t phys_addr);
 
 // *****************************************************************************
 // Allocator support

+ 7 - 12
app/user/user_main.c

@@ -129,8 +129,7 @@ bool user_process_input(bool force) {
     return task_post_low(input_sig, force);
 }
 
-void nodemcu_init(void)
-{
+void nodemcu_init(void) {
     NODE_ERR("\n");
     // Initialize platform first for lua modules.
     if( platform_init() != PLATFORM_OK )
@@ -139,11 +138,13 @@ void nodemcu_init(void)
         NODE_DBG("Can not init platform for modules.\n");
         return;
     }
-
-    if( flash_detect_size_byte() != flash_rom_get_size_byte() ) {
-        NODE_ERR("Self adjust flash size.\n");
+    uint32_t size_detected = flash_detect_size_byte();
+    uint32_t size_from_rom = flash_rom_get_size_byte();
+    if( size_detected != size_from_rom ) {
+        NODE_ERR("Self adjust flash size. 0x%x (ROM) -> 0x%x (Detected)\n", 
+                 size_from_rom, size_detected);
         // Fit hardware real flash size.
-        flash_rom_set_size_byte(flash_detect_size_byte());
+        flash_rom_set_size_byte(size_detected);
 
         system_restart ();
         // Don't post the start_lua task, we're about to reboot...
@@ -240,7 +241,6 @@ user_rf_cal_sector_set(void)
     return rf_cal_sec;
 }
 
-extern void luaN_user_init(void);
 /******************************************************************************
  * FunctionName : user_init
  * Description  : entry of user application, init user function here
@@ -261,10 +261,5 @@ void user_init(void)
 #ifndef NODE_DEBUG
     system_set_os_print(0);
 #endif
-
-#ifdef LUA_FLASH_STORE
-    luaN_user_init();
-#endif
-
     system_init_done_cb(nodemcu_init);
 }

File diff suppressed because it is too large
+ 8 - 0
docs/en/lcd.md


File diff suppressed because it is too large
+ 10 - 0
docs/en/lfs.md


+ 7 - 3
docs/en/modules/node.md

@@ -150,15 +150,19 @@ flash ID (number)
 Returns the function reference for a function in the LFS (Lua Flash Store).
 
 #### Syntax
-`node.flashindex()`
+`node.flashindex(modulename)`
 
 #### Parameters
 `modulename`  The name of the module to be loaded.  If this is `nil` or invalid then an info list is returned
 
 #### Returns
--  In the case where the LFS in not loaded, `node.flashindex` evaluates to `nil`, followed by the flash and mapped base addresss of the LFS  
+-  In the case where the LFS in not loaded, `node.flashindex` evaluates to `nil`, followed by the flash and mapped base addresss of the LFS
 -  If the LFS is loaded and the function is called with the name of a valid module in the LFS, then the function is returned in the same way the `load()` and the other Lua load functions do.
--  Otherwise an extended info list is returned: the Unix time of the LFS build, the flash and mapped base addresses of the LFS and its current length, and an array of the valid module names in the LFS. 
+-  Otherwise an extended info list is returned: the Unix time of the LFS build, the flash and mapped base addresses of the LFS and its current length, and an array of the valid module names in the LFS.
+
+#### Example
+
+The `node.flashindex()` is a low level API call that is normally wrapped using standard Lua code to present a simpler application API.  See the module `_init.lua` in the `lua_examples/lfs` directory for an example of how to do this.
 
 ## node.flashreload()
 

+ 5 - 2
ld/nodemcu.ld

@@ -241,14 +241,17 @@ SECTIONS
     KEEP(*(.lua_rotable))
     LONG(0) LONG(0) /* Null-terminate the array */
 
-    /* SDK doesn't use libc functions, and are therefore safe to put in flash */
+    /* SDK doesn't use libc functions, and are therefore safe to put in flash */ 
     */libc.a:*.o(.text* .literal*)
     /* end libc functions */
 
+    /* Reserved areas, flash page aligned and last */
+    . = ALIGN(4096);
+    KEEP(*(.irom.reserved .irom.reserved.*))
+
     _irom0_text_end = ABSOLUTE(.);
     _flash_used_end = ABSOLUTE(.);
   } >irom0_0_seg :irom0_0_phdr =0xffffffff
-
 }
 
 /* get ROM code address */

+ 83 - 0
lua_examples/lfs/_init.lua

@@ -0,0 +1,83 @@
+--
+-- File: _init.lua
+--[[
+
+  This is a template for the LFS equivalent of the SPIFFS init.lua.  
+
+  It is a good idea to such an _init.lua module to your LFS and do most of the LFS
+  module related initialisaion in this. This example uses standard Lua features to
+  simplify the LFS API.  
+
+  The first section adds a 'LFS' table to _G and uses the __index metamethod to
+  resolve functions in the LFS, so you can execute the main function of module
+  'fred' by executing LFS.fred(params), etc. It also implements some standard
+  readonly properties:
+
+  LFS._time    The Unix Timestamp when the luac.cross was executed.  This can be
+               used as a version identifier.
+
+  LFS._config  This returns a table of useful configuration parameters, hence
+                 print (("0x%6x"):format(LFS._config.lfs_base))
+               gives you the parameter to use in the luac.cross -a option.
+
+  LFS._list    This returns a table of the LFS modules, hence
+                 print(table.concat(LFS._list),'\n')
+               gives you a single column listing of all modules in the LFS.
+
+---------------------------------------------------------------------------------]]               
+
+local index = node.flashindex
+
+local lfs_t = {
+  __index = function(_, name)
+      local fn_ut, ba, ma, size, modules = index(name)
+      if not ba then 
+        return fn_ut
+      elseif name == '_time' then
+        return fn_ut
+      elseif name == '_config' then
+        local fs_ma, fs_size = file.fscfg()
+        return {lfs_base = ba, lfs_mapped = ma, lfs_size = size, 
+                fs_mapped = fs_ma, fs_size = fs_size}
+      elseif name == '_list' then
+        return modules
+      else
+        return nil
+      end
+    end,
+
+  __newindex = function(_, name, value)
+      error("LFS is readonly. Invalid write to LFS." .. name, 2)
+    end,
+ 
+  }
+
+local G=getfenv()
+G.LFS = setmetatable(lfs_t,lfs_t)
+
+--[[-------------------------------------------------------------------------------
+  The second section adds the LFS to the require searchlist, so that you can
+  require a Lua module 'jean' in the LFS by simply doing require "jean". However
+  note that this is at the search entry following the FS searcher, so if you also
+  have jean.lc or jean.lua in SPIFFS, then this SPIFFS version will get loaded into 
+  RAM instead of using. (Useful, for development).
+
+  Note that if you want LFS to take a higher priority than SPIFFS, the use the [2]
+  slot for loaders.  If you want to reverse these in your init.lua or interactively
+  for debugging, then use
+
+  do local pl = package.loaders; pl[2],pl[4] = pl[4],pl[2]; end
+---------------------------------------------------------------------------------]]
+
+package.loaders[4] = function(module) -- loader_flash
+  local fn, ba = index(module)
+  return ba and "Module not in LFS" or fn 
+end
+
+--[[-------------------------------------------------------------------------------
+  You can add any other initialisation here, for example a couple of the globals
+  are never used, so setting them to nil saves a couple of global entries
+---------------------------------------------------------------------------------]]
+ 
+G.module       = nil    -- disable Lua 5.0 style modules to save RAM
+package.seeall = nil 

+ 37 - 0
lua_examples/lfs/dummy_strings.lua

@@ -0,0 +1,37 @@
+--
+-- File: LFS_dummy_strings.lua
+--[[
+  luac.cross -f generates a ROM string table which is part of the compiled LFS
+  image. This table includes all strings referenced in the loaded modules. 
+
+  If you want to preload other string constants, then one way to achieve this is
+  to include a dummy module in the LFS that references the strings that you want
+  to load. You never need to call this module; it's inclusion in the LFS image is
+  enough to add the strings to the ROM table. Your application can use any strings
+  in the ROM table without incuring any RAM or Lua Garbage Collector (LGC)
+  overhead. 
+
+  The local preload example is a useful starting point. However, if you call the
+  following code in your application during testing, then this will provide a 
+  listing of the current RAM string table.  
+
+do
+  local a=debug.getstrings'RAM'
+  for i =1, #a do a[i] = ('%q'):format(a[i]) end
+  print ('local preload='..table.concat(a,','))
+end
+
+  This will exclude any strings already in the ROM table, so the output is the list
+  of putative strings that you should consider adding to LFS ROM table.
+
+---------------------------------------------------------------------------------]]
+
+local preload = "?.lc;?.lua", "/\n;\n?\n!\n-", "@init.lua", "_G", "_LOADED",
+"_LOADLIB", "__add", "__call", "__concat", "__div", "__eq", "__gc", "__index",
+"__le", "__len", "__lt", "__mod", "__mode", "__mul", "__newindex", "__pow",
+"__sub", "__tostring", "__unm", "collectgarbage", "cpath", "debug", "file",
+"file.obj", "file.vol", "flash", "getstrings", "index", "ipairs", "list", "loaded",
+"loader", "loaders", "loadlib", "module", "net.tcpserver", "net.tcpsocket",
+"net.udpsocket", "newproxy", "package", "pairs", "path", "preload", "reload",
+"require", "seeall", "wdclr", "not enough memory", "sjson.decoder","sjson.encoder", 
+"tmr.timer"

+ 9 - 70
lua_examples/lfs/lfs_fragments.lua

@@ -4,8 +4,12 @@
 -- image for the first time bare, that is without either LFS or SPIFFS preloaded
 -- then enter the following commands interactively through the UART:
 --
-local _,mapa,fa=node.flashindex(); return ('0x%x, 0x%x, 0x%x'):format(
-  mapa,fa,file.fscfg())
+do
+  local _,ma,fa=node.flashindex()
+  for n,v in pairs{LFS_MAPPED=ma, LFS_BASE=fa, SPIFFS_BASE=sa} do
+    print(('export %s=""0x%x"'):format(n, v)
+  end
+end
 --
 -- This will print out 3 hex constants: the absolute address used in the 
 -- 'luac.cross -a' options and the flash adresses of the LFS and SPIFFS.
@@ -33,37 +37,6 @@ $ESPTOOL --port $USB --baud 460800  write_flash -fm dio 0x100000 \
 # and now you are good to go
 ]]
 
------------------------------------------------------------------------------------
---
--- It is a good idea to add an _init.lua module to your LFS and do most of the 
--- LFS module related initialisaion in this.  This example uses standard Lua
--- features to simplify the LFS API.  
---
--- The first adds a 'LFS' table to _G and uses the __index metamethod to resolve
--- functions in the LFS, so you can execute the main function of module 'fred'
--- by doing LFS.fred(params)
---
--- The second adds the LFS to the require searchlist so that you can require a
--- Lua module 'jean' in the LFS by simply doing require "jean".  However not that
--- this is at the search entry following the FS searcher, so if you also have
--- jean.lc or jean.lua in SPIFFS, then this will get preferentially loaded,
--- albeit into RAM.  (Useful, for development).
---
-do
-  local index = node.flashindex 
-  local lfs_t = { __index = function(_, name)
-      local fn, ba = index(name)
-      if not ba then return fn end -- or return nil implied
-    end}
-  getfenv().LFS = setmetatable(lfs_t,lfs_t)
-
-  local function loader_flash(module)
-    local fn, ba = index(module)
-    return ba and "Module not in LFS" or fn 
-  end
-  package.loaders[3] = loader_flash
-
-end
 
 -----------------------------------------------------------------------------------
 --
@@ -73,8 +46,9 @@ end
 -- module in LFS.  Here is an example.  It's a good idea either to use a timer 
 -- delay or a GPIO pin during development, so that you as developer can break into 
 -- the boot sequence if there is a problem with the _init bootstrap that is causing
--- a panic loop.  Here is one example of how you might do this.  You have a second to
--- inject tmr.stop(0) into UART0.  Extend if your reactions can't meet this.
+-- a panic loop.  Here is one example of how you might do this.  You have a second
+-- to inject tmr.stop(0) into UART0.  Extend this dealy if your reactions can't 
+-- meet this.
 --
 -- You also want to do autoload the LFS, for example by adding the following:
 --
@@ -87,38 +61,3 @@ tmr.alarm(0, 1000, tmr.ALARM_SINGLE,
     local fi=node.flashindex; return pcall(fi and fi'_init')
   end)
 
------------------------------------------------------------------------------------
---
--- The debug.getstrings function can be used to get a listing of the RAM (or ROM
--- if LFS is loaded), as per the following example, so you can do this at the 
--- interactive prompt or call it as a debug function during a running application. 
---
-do
-  local a=debug.getstrings'RAM'
-  for i =1, #a do a[i] = ('%q'):format(a[i]) end
-  print ('local preload='..table.concat(a,','))
-end
-
------------------------------------------------------------------------------------
---
--- File: LFS_dummy_strings.lua
---
--- luac.cross -f will generate a ROM string table that includes all strings 
--- referenced in the loaded modules.  If you want to preload other string constants
--- hen the trick is to include a dummy module in the LFS.  You never need to call
--- this.  It's inclusion is enough to add the strings to the ROM table.  Once in
--- the ROM table, then you can use them in your application without incuring any 
--- RAM or Lua Garbage Collector (LGC) overhead.  Here is a useful starting point,
--- but you can add to this for your application.  
---
--- The trick is to build the LFS as normal then run the previous example from your
--- running application and append these lines to this file.
---
-local preload = "?.lc;?.lua", "@init.lua", "_G", "_LOADED", "_LOADLIB", "__add", 
-"__call", "__concat", "__div", "__eq", "__gc", "__index", "__le", "__len", "__lt", 
-"__mod", "__mode", "__mul", "__newindex", "__pow", "__sub", "__tostring", "__unm", 
-"collectgarbage", "cpath", "debug", "file", "file.obj", "file.vol", "flash", 
-"getstrings", "index", "ipairs", "list", "loaded", "loader", "loaders", "loadlib", 
-"module", "net.tcpserver", "net.tcpsocket", "net.udpsocket", "newproxy", "package", 
-"pairs", "path", "preload", "reload", "require", "seeall", "wdclr"
-

+ 5 - 2
mkdocs.yml

@@ -24,13 +24,16 @@ pages:
     - Home: 'en/index.md'
     - Building the firmware: 'en/build.md'
     - Flashing the firmware: 'en/flash.md'
-    - Internal filesystem notes: 'en/spiffs.md'
-    - Filesystem on SD card: 'en/sdcard.md'
     - Uploading code: 'en/upload.md'
     - FAQs:
         - Lua Developer FAQ: 'en/lua-developer-faq.md'
         - Extension Developer FAQ: 'en/extn-developer-faq.md'
         - Hardware FAQ: 'en/hardware-faq.md'
+    - Whitepapers:
+        - Filesystem on SD card: 'en/sdcard.md'
+        - Internal filesystem notes: 'en/spiffs.md'
+        - Lua Compact Debug(LCD): 'en/lfs.md'
+        - Lua Flash Store(LFS): 'en/lcd.md'
     - Support: 'en/support.md'
     - Modules:
         - 'adc': 'en/modules/adc.md'

+ 1 - 1
tools/Makefile

@@ -61,7 +61,7 @@ spiffsimg: spiffsimg/spiffsimg
 	@echo Built spiffsimg in spiffsimg/spiffsimg
 
 spiffsimg/spiffsimg: 
-	@$(MAKE) -C spiffsimg CC=$(HOSTCC)
+	@$(MAKE) -C spiffsimg 
 
 spiffsscript: remove-image LFSimage spiffsimg/spiffsimg
 	rm -f ./spiffsimg/spiffs.lst

Some files were not shown because too many files changed in this diff