Unverified Commit 11592951 authored by Arnim Läuger's avatar Arnim Läuger Committed by GitHub
Browse files

Merge pull request #2582 from nodemcu/dev

Next master drop
parents 4095c408 61433c44
.gdb_history
sdk/
cache/
.ccache/
local/
luac.cross
user_config.h
server-ca.crt
luac.cross
uz_unzip
uz_zip
tools/toolchains/
#ignore Eclipse project files
.cproject
......
[submodule "app/u8g2lib/u8g2"]
path = app/u8g2lib/u8g2
url = https://github.com/olikraus/U8g2_Arduino.git
[submodule "app/ucglib/ucg"]
path = app/ucglib/ucg
url = https://github.com/olikraus/Ucglib_Arduino.git
sudo: false
language: cpp
addons:
apt:
......@@ -8,9 +7,6 @@ addons:
cache:
- directories:
- cache
install:
- tar -Jxvf tools/esp-open-sdk.tar.xz
- export PATH=$PATH:$PWD/esp-open-sdk/xtensa-lx106-elf/bin
script:
- export BUILD_DATE=$(date +%Y%m%d)
- make EXTRA_CCFLAGS="-DBUILD_DATE='\"'$BUILD_DATE'\"'" all
......
......@@ -2,6 +2,8 @@
#
.NOTPARALLEL:
TOOLCHAIN_VERSION:=20181106.0
# SDK base version, as released by Espressif
SDK_BASE_VER:=2.2.1
......@@ -47,7 +49,7 @@ ifeq ($(OS),Windows_NT)
OBJCOPY = xt-objcopy
#MAKE = xt-make
CCFLAGS += --rename-section .text=.irom0.text --rename-section .literal=.irom0.literal
else
else
# It is gcc, may be cygwin
# Can we use -fdata-sections?
CCFLAGS += -ffunction-sections -fno-jump-tables -fdata-sections
......@@ -73,11 +75,13 @@ ifeq ($(OS),Windows_NT)
else
# We are under other system, may be Linux. Assume using gcc.
# Can we use -fdata-sections?
PLATFORM:=linux-x86_64
ifndef COMPORT
ESPPORT = /dev/ttyUSB0
else
ESPPORT = $(COMPORT)
endif
export PATH := $(PATH):$(TOP_DIR)/tools/toolchains/esp8266-$(PLATFORM)-$(TOOLCHAIN_VERSION)/bin/
CCFLAGS += -ffunction-sections -fno-jump-tables -fdata-sections
AR = xtensa-lx106-elf-ar
CC = $(WRAPCC) xtensa-lx106-elf-gcc
......@@ -145,9 +149,9 @@ endif
endif
#
# Note:
# Note:
# https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
# If you add global optimize options like "-O2" here
# If you add global optimize options like "-O2" here
# they will override "-Os" defined above.
# "-Os" should be used to reduce code size
#
......@@ -161,7 +165,7 @@ CCFLAGS += \
-nostdlib \
-mlongcalls \
-mtext-section-literals
# -Wall
# -Wall
CFLAGS = $(CCFLAGS) $(DEFINES) $(EXTRA_CCFLAGS) $(STD_CFLAGS) $(INCLUDES)
DFLAGS = $(CCFLAGS) $(DDEFINES) $(EXTRA_CCFLAGS) $(STD_CFLAGS) $(INCLUDES)
......@@ -191,7 +195,7 @@ DEP_LIBS_$(1) = $$(foreach lib,$$(filter %.a,$$(COMPONENTS_$(1))),$$(dir $$(lib)
DEP_OBJS_$(1) = $$(foreach obj,$$(filter %.o,$$(COMPONENTS_$(1))),$$(dir $$(obj))$$(OBJODIR)/$$(notdir $$(obj)))
$$(IMAGEODIR)/$(1).out: $$(OBJS) $$(DEP_OBJS_$(1)) $$(DEP_LIBS_$(1)) $$(DEPENDS_$(1))
@mkdir -p $$(IMAGEODIR)
$$(CC) $$(LDFLAGS) $$(if $$(LINKFLAGS_$(1)),$$(LINKFLAGS_$(1)),$$(LINKFLAGS_DEFAULT) $$(OBJS) $$(DEP_OBJS_$(1)) $$(DEP_LIBS_$(1))) -o $$@
$$(CC) $$(LDFLAGS) $$(if $$(LINKFLAGS_$(1)),$$(LINKFLAGS_$(1)),$$(LINKFLAGS_DEFAULT) $$(OBJS) $$(DEP_OBJS_$(1)) $$(DEP_LIBS_$(1))) -o $$@
endef
$(BINODIR)/%.bin: $(IMAGEODIR)/%.out
......@@ -204,16 +208,32 @@ $(BINODIR)/%.bin: $(IMAGEODIR)/%.out
# Should be done in top-level makefile only
#
all: sdk_pruned pre_build .subdirs $(OBJS) $(OLIBS) $(OIMAGES) $(OBINS) $(SPECIAL_MKTARGETS)
all: toolchain sdk_pruned pre_build .subdirs $(OBJS) $(OLIBS) $(OIMAGES) $(OBINS) $(SPECIAL_MKTARGETS)
.PHONY: sdk_extracted
.PHONY: sdk_patched
.PHONY: sdk_pruned
.PHONY: toolchain
sdk_extracted: $(TOP_DIR)/sdk/.extracted-$(SDK_BASE_VER)
sdk_patched: sdk_extracted $(TOP_DIR)/sdk/.patched-$(SDK_VER)
sdk_pruned: $(SDK_DIR_DEPENDS) $(TOP_DIR)/sdk/.pruned-$(SDK_VER)
ifeq ($(OS),Windows_NT)
toolchain:
else
toolchain: $(TOP_DIR)/tools/toolchains/esp8266-$(PLATFORM)-$(TOOLCHAIN_VERSION)/bin/xtensa-lx106-elf-gcc
$(TOP_DIR)/tools/toolchains/esp8266-$(PLATFORM)-$(TOOLCHAIN_VERSION)/bin/xtensa-lx106-elf-gcc: $(TOP_DIR)/cache/toolchain-esp8266-$(PLATFORM)-$(TOOLCHAIN_VERSION).tar.xz
mkdir -p $(TOP_DIR)/tools/toolchains/
tar -xJf $< -C $(TOP_DIR)/tools/toolchains/
touch $@
$(TOP_DIR)/cache/toolchain-esp8266-$(PLATFORM)-$(TOOLCHAIN_VERSION).tar.xz:
mkdir -p $(TOP_DIR)/cache
wget --tries=10 --timeout=15 --waitretry=30 --read-timeout=20 --retry-connrefused https://github.com/jmattsson/esp-toolchains/releases/download/$(PLATFORM)-$(TOOLCHAIN_VERSION)/toolchain-esp8266-$(PLATFORM)-$(TOOLCHAIN_VERSION).tar.xz -O $@ || { rm -f "$@"; exit 1; }
endif
$(TOP_DIR)/sdk/.extracted-$(SDK_BASE_VER): $(TOP_DIR)/cache/v$(SDK_FILE_VER).zip
mkdir -p "$(dir $@)"
(cd "$(dir $@)" && rm -fr esp_iot_sdk_v$(SDK_VER) ESP8266_NONOS_SDK-$(SDK_BASE_VER) && unzip $(TOP_DIR)/cache/v$(SDK_FILE_VER).zip ESP8266_NONOS_SDK-$(SDK_BASE_VER)/lib/* ESP8266_NONOS_SDK-$(SDK_BASE_VER)/ld/eagle.rom.addr.v6.ld ESP8266_NONOS_SDK-$(SDK_BASE_VER)/include/* ESP8266_NONOS_SDK-$(SDK_BASE_VER)/bin/esp_init_data_default_v05.bin)
......
......@@ -20,7 +20,7 @@ FLAVOR = debug
ifndef PDIR # {
GEN_IMAGES= eagle.app.v6.out
GEN_BINS= eagle.app.v6.bin
OPT_MKTARGETS := coap crypto dht http mqtt pcm sjson sqlite3 tsl2561 websocket
OPT_MKTARGETS := coap dht http mqtt pcm sjson sqlite3 tsl2561 websocket
OPT_MKLIBTARGETS := u8g2 ucg
SEL_MKTARGETS := $(shell $(CC) -E -dM include/user_modules.h | sed -n '/^\#define LUA_USE_MODULES_/{s/.\{24\}\(.*\)/\L\1/; p}')
OPT_SEL_MKLIBTARGETS := $(foreach tgt,$(OPT_MKLIBTARGETS),$(findstring $(tgt), $(SEL_MKTARGETS)))
......@@ -31,6 +31,7 @@ SPECIAL_MKTARGETS :=$(APP_MKTARGETS)
SUBDIRS= \
user \
crypto \
driver \
mbedtls \
platform \
......@@ -45,6 +46,7 @@ SUBDIRS= \
fatfs \
esp-gdbstub \
pm \
uzlib \
$(OPT_SEL_MKTARGETS)
endif # } PDIR
......@@ -62,6 +64,7 @@ LD_FILE = $(LDDIR)/nodemcu.ld
COMPONENTS_eagle.app.v6 = \
user/libuser.a \
crypto/libcrypto.a \
driver/libdriver.a \
platform/libplatform.a \
task/libtask.a \
......@@ -76,6 +79,8 @@ COMPONENTS_eagle.app.v6 = \
net/libnodemcu_net.a \
mbedtls/libmbedtls.a \
modules/libmodules.a \
smart/smart.a \
uzlib/libuzlib.a \
$(OPT_SEL_COMPONENTS)
......
......@@ -210,7 +210,7 @@ static void ICACHE_FLASH_ATTR http_connect_callback( void * arg )
char ua_header[32] = "";
int ua_len = 0;
if (os_strstr( req->headers, "User-Agent:" ) == NULL && os_strstr( req->headers, "user-agent:" ) == NULL)
if (strcasestr( req->headers, "User-Agent:" ) == NULL )
{
os_sprintf( ua_header, "User-Agent: %s\r\n", "ESP8266" );
ua_len = strlen(ua_header);
......@@ -218,7 +218,7 @@ static void ICACHE_FLASH_ATTR http_connect_callback( void * arg )
char * host_header = "";
int host_len = 0;
if ( os_strstr( req->headers, "Host:" ) == NULL && os_strstr( req->headers, "host:" ) == NULL)
if ( strcasestr( req->headers, "Host:" ) == NULL )
{
int max_header_len = 9 + strlen(req->hostname); // 9 is fixed size of "Host:[space][cr][lf]\0"
if ((req->port == 80)
......@@ -328,10 +328,7 @@ static void ICACHE_FLASH_ATTR http_disconnect_callback( void * arg )
{
http_status = atoi( req->buffer + strlen( version_1_0 ) );
char *locationOffset = (char *) os_strstr( req->buffer, "Location:" );
if ( locationOffset == NULL ) {
locationOffset = (char *) os_strstr( req->buffer, "location:" );
}
char *locationOffset = (char *) strcasestr( req->buffer, "Location:" );
if ( locationOffset != NULL && http_status >= 300 && http_status <= 308 ) {
if (req->redirect_follow_count < REDIRECTION_FOLLOW_MAX) {
......@@ -414,7 +411,7 @@ static void ICACHE_FLASH_ATTR http_disconnect_callback( void * arg )
body = body + 4;
}
if ( os_strstr( req->buffer, "Transfer-Encoding: chunked" ) || os_strstr( req->buffer, "transfer-encoding: chunked" ) )
if ( strcasestr( req->buffer, "Transfer-Encoding: chunked" ) )
{
int body_size = req->buffer_size - (body - req->buffer);
char chunked_decode_buffer[body_size];
......
......@@ -57,18 +57,8 @@
const LOCK_IN_SECTION(libs) \
luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \
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(libs) \
luaL_Reg MODULE_PASTE_(lua_lib_,name) = { luaname, initfunc }
#define BUILTIN_LIB(name, luaname, map) \
const LOCK_IN_SECTION(rotable) \
luaR_table MODULE_PASTE_(lua_rotable_,name) = { luaname, map }
luaR_entry MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \
= {LSTRKEY(luaname), LROVAL(map)}
#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)
# error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)"
......
......@@ -31,11 +31,26 @@
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_i2c_128x64_vcomh0_f, sh1106_i2c_128x64_vcomh0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_96x16_er_f, ssd1306_i2c_96x16_er) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_i2c_128x64_noname_f, sh1106_i2c_128x64_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_i2c_64x128_f, sh1107_i2c_64x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_i2c_seeed_96x96_f, sh1107_i2c_seeed_96x96) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_i2c_128x128_f, sh1107_i2c_128x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1108_i2c_160x160_f, sh1108_i2c_160x160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1122_i2c_256x64_f, sh1122_i2c_256x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_vcomh0_f, ssd1306_i2c_128x64_vcomh0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1309_i2c_128x64_noname2_f, ssd1309_i2c_128x64_noname2) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_alt0_f, ssd1306_i2c_128x64_alt0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_i2c_ea_dogm240_f, uc1611_i2c_ea_dogm240) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1326_i2c_er_256x32_f, ssd1326_i2c_er_256x32 )\
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_i2c_seeed_96x96_f, ssd1327_i2c_seeed_96x96) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_i2c_ea_w128128_f, ssd1327_i2c_ea_w128128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_i2c_midas_128x128_f, ssd1327_i2c_midas_128x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7567_i2c_64x32_f, st7567_i2c_64x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx256128_f, st75256_i2c_jlx256128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx256160_f, st75256_i2c_jlx256160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx240160_f, st75256_i2c_jlx240160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx25664_f, st75256_i2c_jlx25664) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx172104_f, st75256_i2c_jlx172104) \
#define U8G2_DISPLAY_TABLE_I2C \
U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \
......@@ -72,18 +87,25 @@
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7920_s_192x32_f, st7920_s_192x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1325_nhd_128x64_f, ssd1325_nhd_128x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x64_noname_f, ssd1306_128x64_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x64_alt0_f, ssd1306_128x64_alt0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sed1520_122x32_f, sed1520_122x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_ea_dogm128_f, st7565_ea_dogm128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ld7032_60x32_f, ld7032_60x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1607_200x200_f, ssd1607_200x200) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1309_128x64_noname2_f, ssd1309_128x64_noname2) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_128x64_noname_f, sh1106_128x64_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_64x128_f, sh1107_64x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_seeed_96x96_f, sh1107_seeed_96x96) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_128x128_f, sh1107_128x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1108_160x160_f, sh1108_160x160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1122_256x64_f, sh1122_256x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x32_univision_f, ssd1306_128x32_univision) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7920_s_128x64_f, st7920_s_128x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_64128n_f, st7565_64128n) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1701_ea_dogs102_f, uc1701_ea_dogs102) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_ew50850_f, uc1611_ew50850) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1322_nhd_256x64_f, ssd1322_nhd_256x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1322_nhd_128x64_f, ssd1322_nhd_128x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_ea_dogm132_f, st7565_ea_dogm132) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1329_128x96_noname_f, ssd1329_128x96_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_zolen_128x64_f, st7565_zolen_128x64) \
......@@ -91,17 +113,37 @@
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_96x16_er_f, ssd1306_96x16_er) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ist3020_erc19264_f, ist3020_erc19264) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7588_jlx12864_f, st7588_jlx12864) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1326_er_256x32_f, ssd1326_er_256x32 )\
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_seeed_96x96_f, ssd1327_seeed_96x96) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_ea_w128128_f, ssd1327_ea_w128128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_midas_128x128_f, ssd1327_midas_128x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_jlx172104_f, st75256_jlx172104) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_nhd_c12832_f, st7565_nhd_c12832) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_jlx256160_f, st75256_jlx256160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_jlx240160_f, st75256_jlx240160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_jlx25664_f, st75256_jlx25664) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_64x48_er_f, ssd1306_64x48_er) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_pcf8812_96x65_f, pcf8812_96x65) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7567_pi_132x64_f, st7567_pi_132x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7567_jlx12864_f, st7567_jlx12864) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7567_enh_dg128064i_f, st7567_enh_dg128064i) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7567_64x32_f, st7567_64x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7586s_s028hn118a_f, st7586s_s028hn118a) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7586s_erc240160_f, st7586s_erc240160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_pcd8544_84x48_f, pcd8544_84x48) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_128x64_vcomh0_f, sh1106_128x64_vcomh0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_nt7534_tg12864r_f, nt7534_tg12864r) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1701_mini12864_f, uc1701_mini12864) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_t6963_240x128_f, t6963_240x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_t6963_240x64_f, t6963_240x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_t6963_256x64_f, t6963_256x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_t6963_128x64_f, t6963_128x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_t6963_160x80_f, t6963_160x80) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_lc7981_160x80_f, lc7981_160x80) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_lc7981_160x160_f, lc7981_160x160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_lc7981_240x128_f, lc7981_240x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_lc7981_240x64_f, lc7981_240x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_hx1230_96x68_f, hx1230_96x68) \
#define U8G2_DISPLAY_TABLE_SPI \
U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x64_noname_f, ssd1306_128x64_noname) \
......
......@@ -27,8 +27,10 @@
// Uncomment the UCG_DISPLAY_TABLE_ENTRY for the device(s) you want to
// compile into the firmware.
//
// UCG_DISPLAY_TABLE_ENTRY(hx8352c_18x240x400_hw_spi, ucg_dev_hx8352c_18x240x400, ucg_ext_hx8352c_18) \
// UCG_DISPLAY_TABLE_ENTRY(ili9163_18x128x128_hw_spi, ucg_dev_ili9163_18x128x128, ucg_ext_ili9163_18) \
// UCG_DISPLAY_TABLE_ENTRY(ili9341_18x240x320_hw_spi, ucg_dev_ili9341_18x240x320, ucg_ext_ili9341_18) \
// UCG_DISPLAY_TABLE_ENTRY(ili9486_18x320x480_hw_spi, ucg_dev_ili9486_18x320x480, ucg_ext_ili9486_18) \
// UCG_DISPLAY_TABLE_ENTRY(pcf8833_16x132x132_hw_spi, ucg_dev_pcf8833_16x132x132, ucg_ext_pcf8833_16) \
// UCG_DISPLAY_TABLE_ENTRY(seps225_16x128x128_uvis_hw_spi, ucg_dev_seps225_16x128x128_univision, ucg_ext_seps225_16) \
// UCG_DISPLAY_TABLE_ENTRY(ssd1351_18x128x128_hw_spi, ucg_dev_ssd1351_18x128x128_ilsoft, ucg_ext_ssd1351_18) \
......
......@@ -110,7 +110,7 @@
// 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
//#define TIMER_SUSPEND_ENABLE
//#define PMSLEEP_ENABLE
......
......@@ -46,6 +46,7 @@ INCLUDES += -I ../spiffs
INCLUDES += -I ../libc
INCLUDES += -I ../modules
INCLUDES += -I ../platform
INCLUDES += -I ../uzlib
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
......@@ -25,8 +25,6 @@
#define lauxlib_c
#define LUA_LIB
#include "lrotable.h"
#include "lauxlib.h"
#include "lgc.h"
#include "ldo.h"
......@@ -555,14 +553,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
if (e == NULL) e = fname + c_strlen(fname);
lua_pushlstring(L, fname, e - fname);
lua_rawget(L, -2);
if (lua_isnil(L, -1)) {
/* If looking for a global variable, check the rotables too */
void *ptable = luaR_findglobal(fname, e - fname);
if (ptable) {
lua_pop(L, 1);
lua_pushrotable(L, ptable);
}
}
if (lua_isnil(L, -1)) { /* no such field? */
lua_pop(L, 1); /* remove this nil */
lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
......@@ -967,12 +958,12 @@ LUALIB_API void luaL_assertfail(const char *file, int line, const char *message)
#endif
}
#ifdef DEVELOPMENT_USE_GDB
#if defined(DEVELOPMENT_USE_GDB) && !defined(LUA_CROSS_COMPILER)
/*
* This is a simple stub used by lua_assert() if DEVELOPMENT_USE_GDB is defined.
* Instead of crashing out with an assert error, this hook starts the GDB remote
* stub if not already running and then issues a break. The rationale here is
* that when testing the developer migght be using screen/PuTTY to work ineractively
* that when testing the developer might be using screen/PuTTY to work interactively
* with the Lua Interpreter via UART0. However if an assert triggers, then there
* is the option to exit the interactive session and start the Xtensa remote GDB
* which will then sync up with the remote GDB client to allow forensics of the error.
......
......@@ -16,7 +16,7 @@
#include C_HEADER_STDLIB
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#include "lrodefs.h"
......@@ -462,71 +462,62 @@ static int luaB_newproxy (lua_State *L) {
return 1;
}
#define LUA_BASELIB_FUNCLIST\
{LSTRKEY("assert"), LFUNCVAL(luaB_assert)},\
{LSTRKEY("collectgarbage"), LFUNCVAL(luaB_collectgarbage)},\
{LSTRKEY("dofile"), LFUNCVAL(luaB_dofile)},\
{LSTRKEY("error"), LFUNCVAL(luaB_error)},\
{LSTRKEY("gcinfo"), LFUNCVAL(luaB_gcinfo)},\
{LSTRKEY("getfenv"), LFUNCVAL(luaB_getfenv)},\
{LSTRKEY("getmetatable"), LFUNCVAL(luaB_getmetatable)},\
{LSTRKEY("loadfile"), LFUNCVAL(luaB_loadfile)},\
{LSTRKEY("load"), LFUNCVAL(luaB_load)},\
{LSTRKEY("loadstring"), LFUNCVAL(luaB_loadstring)},\
{LSTRKEY("next"), LFUNCVAL(luaB_next)},\
{LSTRKEY("pcall"), LFUNCVAL(luaB_pcall)},\
{LSTRKEY("print"), LFUNCVAL(luaB_print)},\
{LSTRKEY("rawequal"), LFUNCVAL(luaB_rawequal)},\
{LSTRKEY("rawget"), LFUNCVAL(luaB_rawget)},\
{LSTRKEY("rawset"), LFUNCVAL(luaB_rawset)},\
{LSTRKEY("select"), LFUNCVAL(luaB_select)},\
{LSTRKEY("setfenv"), LFUNCVAL(luaB_setfenv)},\
{LSTRKEY("setmetatable"), LFUNCVAL(luaB_setmetatable)},\
{LSTRKEY("tonumber"), LFUNCVAL(luaB_tonumber)},\
{LSTRKEY("tostring"), LFUNCVAL(luaB_tostring)},\
{LSTRKEY("type"), LFUNCVAL(luaB_type)},\
{LSTRKEY("unpack"), LFUNCVAL(luaB_unpack)},\
{LSTRKEY("xpcall"), LFUNCVAL(luaB_xpcall)}
#if LUA_OPTIMIZE_MEMORY == 2
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE base_funcs_list[] = {
LUA_BASELIB_FUNCLIST,
{LNILKEY, LNILVAL}
};
#endif
extern const luaR_entry lua_rotable_base[];
static int luaB_index(lua_State *L) {
#if LUA_OPTIMIZE_MEMORY == 2
int fres;
if ((fres = luaR_findfunction(L, base_funcs_list)) != 0)
return fres;
#endif
const char *keyname = luaL_checkstring(L, 2);
if (!c_strcmp(keyname, "_VERSION")) {
lua_pushliteral(L, LUA_VERSION);
return 1;
}
void *res = luaR_findglobal(keyname, c_strlen(keyname));
if (!res)
return 0;
else {
lua_pushrotable(L, res);
return 1;
}
}
/*
* ESP builds use specific linker directives to marshal all ROTable declarations
* into a single ROTable in the PSECT ".lua_rotable".
*
* This is not practical on Posix builds using a standard link so for cross
* compiler builds, separate ROTables are used for the base functions and library
* ROTables, with the latter chained from the former using its __index meta-method.
* In this case all library ROTables are defined in linit.c.
*/
#ifdef LUA_CROSS_COMPILER
#define BASE_ROTABLE base_func_map
#define LOCK_IN_ROTABLE
static const LUA_REG_TYPE base_func_meta[] = {
LROT_TABENTRY(__index, lua_rotable_base),
LROT_END};
#else
#define BASE_ROTABLE lua_rotable_base
#define LOCK_IN_ROTABLE __attribute__((used,unused,section(".lua_rotable")))
#endif
static const luaL_Reg base_funcs[] = {
#if LUA_OPTIMIZE_MEMORY != 2
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 0
#include "lrodefs.h"
LUA_BASELIB_FUNCLIST,
static const LUA_REG_TYPE LOCK_IN_ROTABLE base_func_map[] = {
LROT_FUNCENTRY(assert, luaB_assert),
LROT_FUNCENTRY(collectgarbage, luaB_collectgarbage),
LROT_FUNCENTRY(dofile, luaB_dofile),
LROT_FUNCENTRY(error, luaB_error),
LROT_FUNCENTRY(gcinfo, luaB_gcinfo),
LROT_FUNCENTRY(getfenv, luaB_getfenv),
LROT_FUNCENTRY(getmetatable, luaB_getmetatable),
LROT_FUNCENTRY(loadfile, luaB_loadfile),
LROT_FUNCENTRY(load, luaB_load),
LROT_FUNCENTRY(loadstring, luaB_loadstring),
LROT_FUNCENTRY(next, luaB_next),
LROT_FUNCENTRY(pcall, luaB_pcall),
LROT_FUNCENTRY(print, luaB_print),
LROT_FUNCENTRY(rawequal, luaB_rawequal),
LROT_FUNCENTRY(rawget, luaB_rawget),
LROT_FUNCENTRY(rawset, luaB_rawset),
LROT_FUNCENTRY(select, luaB_select),
LROT_FUNCENTRY(setfenv, luaB_setfenv),
LROT_FUNCENTRY(setmetatable, luaB_setmetatable),
LROT_FUNCENTRY(tonumber, luaB_tonumber),
LROT_FUNCENTRY(tostring, luaB_tostring),
LROT_FUNCENTRY(type, luaB_type),
LROT_FUNCENTRY(unpack, luaB_unpack),
LROT_FUNCENTRY(xpcall, luaB_xpcall)
#ifdef LUA_CROSS_COMPILER
,LROT_TABENTRY(__metatable, base_func_meta),
LROT_END
#endif
{"__index", luaB_index},
};
static const luaL_Reg base_funcs[] = {
{NULL, NULL}
};
......@@ -661,7 +652,6 @@ static int luaB_corunning (lua_State *L) {
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1
#include "lrodefs.h"
const LUA_REG_TYPE co_funcs[] = {
{LSTRKEY("create"), LFUNCVAL(luaB_cocreate)},
{LSTRKEY("resume"), LFUNCVAL(luaB_coresume)},
......@@ -682,7 +672,6 @@ static void auxopen (lua_State *L, const char *name,
lua_setfield(L, -2, name);
}
static void base_open (lua_State *L) {
/* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX);
......@@ -691,11 +680,12 @@ static void base_open (lua_State *L) {
luaL_register_light(L, "_G", base_funcs);
#if LUA_OPTIMIZE_MEMORY > 0
lua_pushvalue(L, -1);
lua_setmetatable(L, -2);
#else
lua_setmetatable(L, -2);
lua_pushrotable(L, (void *)BASE_ROTABLE);
lua_setglobal(L, "__index");
#endif
lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */
#endif
/* `ipairs' and `pairs' need auxliliary functions as upvalues */
auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
auxopen(L, "pairs", luaB_pairs, luaB_next);
......
......@@ -16,7 +16,6 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#include "lstring.h"
#include "lflash.h"
#include "user_modules.h"
......
......@@ -47,7 +47,7 @@ static void DumpChar(int y, DumpState* D)
static void Align4(DumpState *D)
{
while(D->wrote&3)
while(D->wrote&3 && D->status==0)
DumpChar(0,D);
}
......
......@@ -16,6 +16,7 @@
#include "lflash.h"
#include "platform.h"
#include "vfs.h"
#include "uzlib.h"
#include "c_fcntl.h"
#include "c_stdio.h"
......@@ -34,15 +35,52 @@ 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(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 ALL_SET (~0)
#define FLASH_SIZE LUA_FLASH_STORE
#define FLASH_PAGE_SIZE INTERNAL_FLASH_SECTOR_SIZE
#define FLASH_PAGES (FLASH_SIZE/FLASH_PAGE_SIZE)
#define FLASH_PAGES (FLASH_SIZE/FLASH_PAGE_SIZE)
#define READ_BLOCKSIZE 1024
#define WRITE_BLOCKSIZE 2048
#define DICTIONARY_WINDOW 16384
#define WORDSIZE (sizeof(int))
#define BITS_PER_WORD 32
#define WRITE_BLOCKS ((DICTIONARY_WINDOW/WRITE_BLOCKSIZE)+1)
#define WRITE_BLOCK_WORDS (WRITE_BLOCKSIZE/WORDSIZE)
char flash_region_base[FLASH_SIZE] ICACHE_FLASH_RESERVED_ATTR;
struct INPUT {
int fd;
int len;
uint8_t block[READ_BLOCKSIZE];
uint8_t *inPtr;
int bytesRead;
int left;
void *inflate_state;
} *in;
typedef struct {
uint8_t byte[WRITE_BLOCKSIZE];
} outBlock;
struct OUTPUT {
lua_State *L;
lu_int32 flash_sig;
int len;
outBlock *block[WRITE_BLOCKS];
outBlock buffer;
int ndx;
uint32_t crc;
int (*fullBlkCB) (void);
int flashLen;
int flagsLen;
int flagsNdx;
uint32_t *flags;
const char *error;
} *out;
#ifdef NODE_DEBUG
extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
void dumpStrt(stringtable *tb, const char *type) {
......@@ -54,11 +92,11 @@ void dumpStrt(stringtable *tb, const char *type) {
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",
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");
......@@ -70,7 +108,7 @@ LUA_API void dumpStrings(lua_State *L) {
/* =====================================================================================
* 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
* 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){
......@@ -104,28 +142,37 @@ static void flashErase(uint32_t start, uint32_t end){
platform_flash_erase_sector( flashSector + i );
}
/* =====================================================================================
* luaN_init(), luaN_reload_reboot() and luaN_index() are exported via lflash.h.
* The first is the startup hook used in lstate.c and the last two are
* implementations of the node.flash API calls.
*/
/*
* 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);
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.
* For the LFS to be valid, its signature has to be correct for this build
* variant, the 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 == 0 || fh->flash_sig == ~0 ) {
NODE_ERR("No LFS image loaded\n");
return;
}
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);
fh->flash_sig & (~FLASH_SIG_ABSOLUTE), FLASH_SIG);
return;
}
......@@ -135,107 +182,89 @@ LUAI_FUNC void luaN_init (lua_State *L) {
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))
/*
* 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 is_absolute) {
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;
if (!is_absolute) {
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;
}
//extern void software_reset(void);
static int loadLFS (lua_State *L);
static int loadLFSgc (lua_State *L);
static int procFirstPass (void);
/*
* Library function called by node.flash.load(filename).
* Library function called by node.flashreload(filename).
*/
LUALIB_API int luaN_reload_reboot (lua_State *L) {
int fd, status, is_absolute;
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_ABSOLUTE)) != 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;
is_absolute = fh.flash_sig & FLASH_SIG_ABSOLUTE;
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, is_absolute) != fh.flash_size)
flashErase(0,-1);
/*
* Issue a break 0,0. This will either enter the debugger or force a restart if
* not installed. Follow this by a H/W timeout is a robust way to insure that
* other interrupts / callbacks don't fire and reference THE old LFS context.
*/
asm("break 0,0" ::);
while (1) {}
// luaL_dbgbreak();
const char *fn = lua_tostring(L, 1), *msg = "";
int status;
/*
* Do a protected call of loadLFS.
*
* - This will normally rewrite the LFS and reboot, with no return.
* - If an error occurs then it is sent to the UART.
* - If this occured in the 1st pass, the previous LFS is unchanged so it is
* safe to return to the calling Lua.
* - If in the 1st pass, then the ESP is rebooted.
*/
status = lua_cpcall(L, &loadLFS, cast(void *,fn));
if (!out || out->fullBlkCB == procFirstPass) {
/*
* Never entered the 2nd pass, so it is safe to return the error. Note
* that I've gone to some trouble to ensure that all dynamically allocated
* working areas have been freed, so that we have no memory leaks.
*/
if (status == LUA_ERRMEM)
msg = "Memory allocation error";
else if (out && out->error)
msg = out->error;
else
msg = "Unknown Error";
/* We can clean up and return error */
lua_cpcall(L, &loadLFSgc, NULL);
lua_settop(L, 0);
lua_pushstring(L, msg);
return 1;
}
if (status == 0) {
/* Successful LFS rewrite */
msg = "LFS region updated. Restarting.";
} else {
/* We have errored during the second pass so clear the LFS and reboot */
if (status == LUA_ERRMEM)
msg = "Memory allocation error";
else if (out->error)
msg = out->error;
else
msg = "Unknown Error";
flashErase(0,-1);
}
NODE_ERR(msg);
while (1) {} // Force WDT as the ROM software_reset() doesn't seem to work
return 0;
}
/*
* In the arg is a valid LFS module name then return the LClosure pointing to it.
* Otherwise return:
* If the arg is a valid LFS module name then return the LClosure
* pointing to it. Otherwise return:
* - The Unix time that the LFS was built
* - The base address and length of the LFS
* - An array of the module names in the the LFS
* - An array of the module names in the LFS
*/
LUAI_FUNC int luaN_index (lua_State *L) {
int i;
int n = lua_gettop(L);
/* Return nil + the LFS base address if the LFS isn't loaded */
/* Return nil + the LFS base address if the LFS isn't loaded */
if(!(G(L)->ROpvmain)) {
lua_settop(L, 0);
lua_pushnil(L);
......@@ -270,5 +299,262 @@ LUAI_FUNC int luaN_index (lua_State *L) {
lua_insert(L, 4);
return 5;
}
/* =====================================================================================
* The following routines use my uzlib which was based on pfalcon's inflate and
* deflate routines. The standard NodeMCU make also makes two host tools uz_zip
* and uz_unzip which also use these and luac.cross uses the deflate. As discussed
* below, The main action routine loadLFS() calls uzlib_inflate() to do the actual
* stream inflation but uses three supplied CBs to abstract input and output
* stream handling.
*
* ESP8266 RAM limitations and heap fragmentation are a key implementation
* constraint and hence these routines use a number of ~2K buffers (11) as
* working storage.
*
* The inflate is done twice, in order to limit storage use and avoid forward /
* backward reference issues. However this has a major advantage that the LFS
* is scanned with the headers, CRC, etc. validated BEFORE the write to flash
* is started, so the only real chance of failure during the second pass
* write is if a power fail occurs during the pass.
*/
static void flash_error(const char *err) {
if (out)
out->error = err;
if (in && in->inflate_state)
uz_free(in->inflate_state);
lua_pushnil(out->L); /* can't use it on a cpcall anyway */
lua_error(out->L);
}
/*
* uzlib_inflate does a stream inflate on an RFC 1951 encoded data stream.
* It uses three application-specific CBs passed in the call to do the work:
*
* - get_byte() CB to return next byte in input stream
* - put_byte() CB to output byte to output buffer
* - recall_byte() CB to output byte to retrieve a historic byte from
* the output buffer.
*
* Note that put_byte() also triggers secondary CBs to do further processing.
*/
static uint8_t get_byte (void) {
if (--in->left < 0) {
/* Read next input block */
int remaining = in->len - in->bytesRead;
int wanted = remaining >= READ_BLOCKSIZE ? READ_BLOCKSIZE : remaining;
if (vfs_read(in->fd, in->block, wanted) != wanted)
flash_error("read error on LFS image file");
system_soft_wdt_feed();
in->bytesRead += wanted;
in->inPtr = in->block;
in->left = wanted-1;
}
return *in->inPtr++;
}
static void put_byte (uint8_t value) {
int offset = out->ndx % WRITE_BLOCKSIZE; /* counts from 0 */
out->block[0]->byte[offset++] = value;
out->ndx++;
if (offset == WRITE_BLOCKSIZE || out->ndx == out->len) {
if (out->fullBlkCB)
out->fullBlkCB();
/* circular shift the block pointers (redundant on last block, but so what) */
outBlock *nextBlock = out->block[WRITE_BLOCKS - 1];
memmove(out->block+1, out->block, (WRITE_BLOCKS-1)*sizeof(void*));
out->block[0] = nextBlock ;
}
}
static uint8_t recall_byte (uint offset) {
if(offset > DICTIONARY_WINDOW || offset >= out->ndx)
flash_error("invalid dictionary offset on inflate");
/* ndx starts at 1. Need relative to 0 */
uint n = out->ndx - offset;
uint pos = n % WRITE_BLOCKSIZE;
uint blockNo = out->ndx / WRITE_BLOCKSIZE - n / WRITE_BLOCKSIZE;
return out->block[blockNo]->byte[pos];
}
/*
* On the first pass the break index is set to call this process at the end
* of each completed output buffer.
* - On the first call, the Flash Header is checked.
* - On each call the CRC is rolled up for that buffer.
* - Once the flags array is in-buffer this is also captured.
* This logic is slightly complicated by the last buffer is typically short.
*/
int procFirstPass (void) {
int len = (out->ndx % WRITE_BLOCKSIZE) ?
out->ndx % WRITE_BLOCKSIZE : WRITE_BLOCKSIZE;
if (out->ndx <= WRITE_BLOCKSIZE) {
uint32_t fl;
/* Process the flash header and cache the FlashHeader fields we need */
FlashHeader *fh = cast(FlashHeader *, out->block[0]);
out->flashLen = fh->flash_size; /* in bytes */
out->flagsLen = (out->len-fh->flash_size)/WORDSIZE; /* in words */
out->flash_sig = fh->flash_sig;
if ((fh->flash_sig & FLASH_FORMAT_MASK) != FLASH_FORMAT_VERSION)
flash_error("Incorrect LFS header version");
if ((fh->flash_sig & FLASH_SIG_B2_MASK) != FLASH_SIG_B2)
flash_error("Incorrect LFS build type");
if ((fh->flash_sig & ~FLASH_SIG_ABSOLUTE) != FLASH_SIG)
flash_error("incorrect LFS header signature");
if (fh->flash_size > FLASH_SIZE)
flash_error("LFS Image too big for configured LFS region");
if ((fh->flash_size & 0x3) ||
fh->flash_size > FLASH_SIZE ||
out->flagsLen != 1 + (out->flashLen/WORDSIZE - 1) / BITS_PER_WORD)
flash_error("LFS length mismatch");
out->flags = luaM_newvector(out->L, out->flagsLen, uint);
}
/* update running CRC */
out->crc = uzlib_crc32(out->block[0], len, out->crc);
/* copy out any flag vector */
if (out->ndx > out->flashLen) {
int start = out->flashLen - (out->ndx - len);
if (start < 0) start = 0;
memcpy(out->flags + out->flagsNdx, out->block[0]->byte + start, len - start);
out->flagsNdx += (len -start) / WORDSIZE; /* flashLen and len are word aligned */
}
return 1;
}
int procSecondPass (void) {
/*
* The length rules are different for the second pass since this only processes
* upto the flashLen and not the full image. This also works in word units.
* (We've already validated these are word multiples.)
*/
int i, len = (out->ndx > out->flashLen) ?
(out->flashLen % WRITE_BLOCKSIZE) / WORDSIZE :
WRITE_BLOCKSIZE / WORDSIZE;
uint32_t *buf = (uint32_t *) out->buffer.byte, flags;
/*
* Relocate all the addresses tagged in out->flags. This can't be done in
* place because the out->blocks are still in use as dictionary content so
* first copy the block to a working buffer and do the relocation in this.
*/
memcpy(out->buffer.byte, out->block[0]->byte, WRITE_BLOCKSIZE);
for (i=0; i<len; i++,flags>>=1 ) {
if ((i&31)==0)
flags = out->flags[out->flagsNdx++];
if (flags&1)
buf[i] = WORDSIZE*buf[i] + cast(uint32_t, flashAddr);
}
/*
* On first block, set the flash_sig has the in progress bit set and this
* is not cleared until end.
*/
if (out->ndx <= WRITE_BLOCKSIZE)
buf[0] = out->flash_sig | FLASH_SIG_IN_PROGRESS;
flashBlock(buf, len*WORDSIZE);
if (out->ndx >= out->flashLen) {
/* we're done so disable CB and rewrite flash sig to complete flash */
flashSetPosition(0);
flashBlock(&out->flash_sig, WORDSIZE);
out->fullBlkCB = NULL;
}
}
/*
* loadLFS)() is protected called from luaN_reload_reboot so that it can recover
* from out of memory and other thrown errors. loadLFSgc() GCs any resources.
*/
static int loadLFS (lua_State *L) {
const char *fn = cast(const char *, lua_touserdata(L, 1));
int i, n, res;
uint32_t crc;
/* Allocate and zero in and out structures */
in = NULL; out = NULL;
in = luaM_new(L, struct INPUT);
memset(in, 0, sizeof(*in));
out = luaM_new(L, struct OUTPUT);
memset(out, 0, sizeof(*out));
out->L = L;
out->fullBlkCB = procFirstPass;
out->crc = ~0;
/* Open LFS image/ file, read unpacked length from last 4 byte and rewind */
if (!(in->fd = vfs_open(fn, "r")))
flash_error("LFS image file not found");
in->len = vfs_size(in->fd);
if (in->len <= 200 || /* size of an empty luac output */
vfs_lseek(in->fd, in->len-4, VFS_SEEK_SET) != in->len-4 ||
vfs_read(in->fd, &out->len, sizeof(uint)) != sizeof(uint))
flash_error("read error on LFS image file");
vfs_lseek(in->fd, 0, VFS_SEEK_SET);
/* Allocate the out buffers */
for(i = 0; i <= WRITE_BLOCKS; i++)
out->block[i] = luaM_new(L, outBlock);
/* first inflate pass */
if (uzlib_inflate (get_byte, put_byte, recall_byte,
in->len, &crc, &in->inflate_state) < 0)
flash_error("read error on LFS image file");
if (crc != ~out->crc)
flash_error("checksum error on LFS image file");
out->fullBlkCB = procSecondPass;
out->flagsNdx = 0;
out->ndx = 0;
in->bytesRead = in->left = 0;
/*
* Once we have completed the 1st pass then the LFS image has passed the
* basic signature, crc and length checks, so now we can reset the counts
* to do the actual write to flash on the second pass.
*/
vfs_lseek(in->fd, 0, VFS_SEEK_SET);
flashErase(0,(out->flashLen - 1)/FLASH_PAGE_SIZE);
flashSetPosition(0);
if (uzlib_inflate(get_byte, put_byte, recall_byte,
in->len, &crc, &in->inflate_state) != UZLIB_OK)
if (res < 0) {
const char *err[] = {"Data_error during decompression",
"Chksum_error during decompression",
"Dictionary error during decompression"
"Memory_error during decompression"};
flash_error(err[UZLIB_DATA_ERROR - res]);
}
return 0;
}
static int loadLFSgc (lua_State *L) {
int i;
if (out) {
for (i = 0; i < WRITE_BLOCKS; i++)
if (out->block[i])
luaM_free(L, out->block[i]);
if (out->flags)
luaM_freearray(L, out->flags, out->flagsLen, uint32_t);
luaM_free(L, out);
}
if (in) {
if (in->fd)
vfs_close(in->fd);
luaM_free(L, in);
}
return 0;
}
#endif
......@@ -15,7 +15,8 @@
#else
# define FLASH_SIG_B1 0x00
#endif
#define FLASH_FORMAT_VERSION (1 << 8)
#define FLASH_FORMAT_MASK 0xF00
#ifdef LUA_PACK_TVALUES
#ifdef LUA_NUMBER_INTEGRAL
#error "LUA_PACK_TVALUES is only valid for Floating point builds"
......@@ -24,9 +25,10 @@
#else
# define FLASH_SIG_B2 0x00
#endif
# define FLASH_SIG_B2_MASK 0x04
#define FLASH_SIG_ABSOLUTE 0x01
#define FLASH_SIG_IN_PROGRESS 0x08
#define FLASH_SIG (0xfafaaf50 | FLASH_SIG_B2 | FLASH_SIG_B1)
#define FLASH_SIG (0xfafaa050 | FLASH_FORMAT_VERSION |FLASH_SIG_B2 | FLASH_SIG_B1)
typedef lu_int32 FlashAddr;
typedef struct {
......
......@@ -43,7 +43,7 @@
#define stringmark(s) if (!isLFSobject(&(s)->tsv)) {reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT);}
#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
#define isfinalized(u) testbit(getmarked(u), FINALIZEDBIT)
#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
......@@ -73,12 +73,12 @@ static void removeentry (Node *n) {
static void reallymarkobject (global_State *g, GCObject *o) {
/* don't mark LFS Protos (or strings) */
if (o->gch.tt == LUA_TPROTO && isLFSobject(&(o->gch)))
if (gettt(&o->gch) == LUA_TPROTO && isLFSobject(&(o->gch)))
return;
lua_assert(iswhite(o) && !isdead(g, o));
white2gray(o);
switch (o->gch.tt) {
switch (gettt(&o->gch)) {
case LUA_TSTRING: {
return;
}
......@@ -168,10 +168,14 @@ static int traversetable (global_State *g, Table *h) {
int i;
int weakkey = 0;
int weakvalue = 0;
const TValue *mode;
if (h->metatable && !luaR_isrotable(h->metatable))
markobject(g, h->metatable);
mode = gfasttm(g, h->metatable, TM_MODE);
const TValue *mode = luaO_nilobject;
if (h->metatable) {
if (!luaR_isrotable(h->metatable))
markobject(g, h->metatable);
mode = gfasttm(g, h->metatable, TM_MODE);
}
if (mode && ttisstring(mode)) { /* is there a weak mode? */
weakkey = (c_strchr(svalue(mode), 'k') != NULL);
weakvalue = (c_strchr(svalue(mode), 'v') != NULL);
......@@ -295,7 +299,7 @@ static l_mem propagatemark (global_State *g) {
GCObject *o = g->gray;
lua_assert(isgray(o));
gray2black(o);
switch (o->gch.tt) {
switch (gettt(&o->gch)) {
case LUA_TTABLE: {
Table *h = gco2h(o);
g->gray = h->gclist;
......@@ -400,7 +404,7 @@ static void cleartable (GCObject *l) {
static void freeobj (lua_State *L, GCObject *o) {
switch (o->gch.tt) {
switch (gettt(&o->gch)) {
case LUA_TPROTO:
lua_assert(!isLFSobject(&(o->gch)));
luaF_freeproto(L, gco2p(o));
......
......@@ -102,8 +102,8 @@
#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);}
#define isLFSobject(x) testbit(getmarked(x), LFSBIT)
#define stringfix(s) if (!test2bits(getmarked(&(s)->tsv), FIXEDBIT, LFSBIT)) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#else
#define isLFSobject(x) (0)
#define stringfix(s) {l_setbit((s)->tsv.marked, FIXEDBIT);}
......
......@@ -15,60 +15,71 @@
#include "lauxlib.h"
#include "luaconf.h"
#include "module.h"
#if defined(LUA_CROSS_COMPILER)
BUILTIN_LIB( start_list, NULL, NULL);
BUILTIN_LIB_INIT( start_list, NULL, NULL);
#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)
# error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)"
#endif
extern const luaR_entry strlib[], tab_funcs[], dblib[],
co_funcs[], math_map[], syslib[];
extern const luaR_entry syslib[], io_funcs[]; // Only used on cross-compile builds
BUILTIN_LIB_INIT( BASE, "", luaopen_base);
BUILTIN_LIB_INIT( LOADLIB, LUA_LOADLIBNAME, luaopen_package);
BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib);
BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string);
BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs);
BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table);
BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib);
BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug);
BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs);
BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map);
#if defined(LUA_CROSS_COMPILER)
extern const luaR_entry syslib[], iolib[];
BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib);
BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io);
BUILTIN_LIB( end_list, NULL, NULL);
BUILTIN_LIB_INIT( end_list, NULL, NULL);
/*
* These base addresses are internal to this module for cross compile builds
* This also exploits feature of the GCC code generator that the variables are
* emitted in either normal OR reverse order within PSECT.
* The NodeMCU Lua initalisation has been adapted to use linker-based module
* registration. This uses a PSECT naming convention to allow the lib and rotab
* entries to be collected by the linker into consoliated tables. The linker
* defines lua_libs_base and lua_rotable_base.
*
* This is not practical on Posix builds which use a standard loader declaration
* so for cross compiler builds, separate ROTables are used for the base functions
* and library ROTables, with the latter chained from the former using its __index
* meta-method. In this case all library ROTables are defined here, avoiding the
* need for linker magic is avoided on host builds.
*/
#define isascending(n) ((&(n ## _end_list)-&(n ## _start_list))>0)
static const luaL_Reg *lua_libs;
const luaR_table *lua_rotable;
#else
/* These base addresses are Xtensa toolchain linker constants for Firmware builds */
#if defined(LUA_CROSS_COMPILER)
#define LUA_ROTABLES lua_rotable_base
#define LUA_LIBS lua_libs_base
#else /* declare Xtensa toolchain linker defined constants */
extern const luaL_Reg lua_libs_base[];
extern const luaR_table lua_rotable_base[];
static const luaL_Reg *lua_libs = lua_libs_base;
const luaR_table *lua_rotable = lua_rotable_base;
extern const luaR_entry lua_rotable_base[];
#define LUA_ROTABLES lua_rotable_core
#define LUA_LIBS lua_libs_core
#endif
static const LOCK_IN_SECTION(libs) luaL_reg LUA_LIBS[] = {
{"", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_STRLIBNAME, luaopen_string},
{LUA_TABLIBNAME, luaopen_table},
{LUA_DBLIBNAME, luaopen_debug}
#if defined(LUA_CROSS_COMPILER)
,{LUA_IOLIBNAME, luaopen_io},
{NULL, NULL}
#endif
};
void luaL_openlibs (lua_State *L) {
#define ENTRY(n,t) {LSTRKEY(n), LRO_ROVAL(t)}
const LOCK_IN_SECTION(rotable) ROTable LUA_ROTABLES[] = {
ENTRY("ROM", LUA_ROTABLES),
ENTRY(LUA_STRLIBNAME, strlib),
ENTRY(LUA_TABLIBNAME, tab_funcs),
ENTRY(LUA_DBLIBNAME, dblib),
ENTRY(LUA_COLIBNAME, co_funcs),
ENTRY(LUA_MATHLIBNAME, math_map)
#if defined(LUA_CROSS_COMPILER)
lua_libs = (isascending(lua_lib) ? &lua_lib_start_list : &lua_lib_end_list) + 1;
lua_rotable = (isascending(lua_rotable) ? &lua_rotable_start_list : &lua_rotable_end_list) + 1;
,ENTRY(LUA_OSLIBNAME, syslib),
LROT_END
#endif
const luaL_Reg *lib = lua_libs;
};
void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib = lua_libs_base;
/* loop round and open libraries */
for (; lib->name; lib++) {
if (lib->func)
{
if (lib->func) {
lua_pushcfunction(L, lib->func);
lua_pushstring(L, lib->name);
lua_call(L, 1, 0);
......
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