# --------------- esphttpd config options ---------------
# If GZIP_COMPRESSION is set to "yes" then the static css, js, and html files will be compressed with gzip before added to the espfs image
# and will be served with gzip Content-Encoding header.
# This could speed up the downloading of these files, but might break compatibility with older web browsers not supporting gzip encoding
# because Accept-Encoding is simply ignored. Enable this option if you have large static files to serve (for e.g. JQuery, Twitter bootstrap)
# By default only js, css and html files are compressed.
# If you have text based static files with different extensions what you want to serve compressed then you will need to add the extension to the following places:
# - Add the extension to this Makefile at the webpages.espfs target to the find command
# - Add the extension to the gzippedFileTypes array in the user/httpd.c file
#
# Adding JPG or PNG files (and any other compressed formats) is not recommended, because GZIP compression does not works effectively on compressed files.
#Static gzipping is disabled by default.
GZIP_COMPRESSION ?= no
# If COMPRESS_W_YUI is set to "yes" then the static css and js files will be compressed with yui-compressor
# This option works only when GZIP_COMPRESSION is set to "yes"
# http://yui.github.io/yuicompressor/
#Disabled by default.
COMPRESS_W_YUI ?= no
YUI-COMPRESSOR ?= /usr/bin/yui-compressor
#If USE_HEATSHRINK is set to "yes" then the espfs files will be compressed with Heatshrink and decompressed
#on the fly while reading the file. Because the decompression is done in the esp8266, it does not require
#any support in the browser.
USE_HEATSHRINK ?= yes
# -------------- End of esphttpd config options -------------
# Output directors to store intermediate compiled files
# relative to the project directory
BUILD_BASE = build
FW_BASE = firmware
# Base directory for the compiler. Needs a / at the end;
XTENSA_TOOLS_ROOT ?= $( abspath ../esp-open-sdk/xtensa-lx106-elf/bin) /
# Base directory of the ESP8266 SDK package, absolute
SDK_BASE ?= $( abspath ../esp_iot_sdk_v1.0.1)
#Esptool.py path and port
ESPTOOL ?= esptool.py
ESPPORT ?= /dev/ttyUSB0
#ESPDELAY indicates seconds to wait between flashing the two binary images
ESPDELAY ?= 3
ESPBAUD ?= 460800
# name for the target project
TARGET = httpd
# espressif tool to concatenate sections for OTA upload using bootloader v1.2+
APPGEN_TOOL ?= gen_appbin.py
ESP_SPI_SIZE ?= 0 # 0->512KB
ESP_FLASH_MODE ?= 0 # 0->QIO
ESP_FLASH_FREQ_DIV ?= 0 # 0->40Mhz
ESP_FLASH_MAX ?= 241664 # max bin file for 512KB flash: 236KB
ESP_HOSTNAME ?= esp8266
# which modules (subdirectories) of the project to include in compiling
#MODULES = driver user lwip/api lwip/app lwip/core lwip/core/ipv4 lwip/netif
MODULES = espfs httpd user
EXTRA_INCDIR = include \
. \
lib/heatshrink/
# libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal phy pp net80211 wpa main lwip
# compiler flags using during compilation of source files
CFLAGS = -Os -ggdb -std= c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -D_STDINT_H \
-Wno-address -DFIRMWARE_SIZE= $( ESP_FLASH_MAX)
# linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static
# linker script used for the above linker step
LD_SCRIPT := build/eagle.esphttpd.v6.ld
LD_SCRIPT1 := build/eagle.esphttpd1.v6.ld
LD_SCRIPT2 := build/eagle.esphttpd2.v6.ld
# various paths from the SDK used in this project
SDK_LIBDIR = lib
SDK_LDDIR = ld
SDK_INCDIR = include include/json
SDK_TOOLSDIR = tools
# select which tools to use as compiler, librarian and linker
CC := $( XTENSA_TOOLS_ROOT) xtensa-lx106-elf-gcc
AR := $( XTENSA_TOOLS_ROOT) xtensa-lx106-elf-ar
LD := $( XTENSA_TOOLS_ROOT) xtensa-lx106-elf-gcc
OBJCP := $( XTENSA_TOOLS_ROOT) xtensa-lx106-elf-objcopy
OBJDP := $( XTENSA_TOOLS_ROOT) xtensa-lx106-elf-objdump
####
#### no user configurable options below here
####
SRC_DIR := $( MODULES)
BUILD_DIR := $( addprefix $( BUILD_BASE) /,$( MODULES) )
SDK_LIBDIR := $( addprefix $( SDK_BASE) /,$( SDK_LIBDIR) )
SDK_LDDIR := $( addprefix $( SDK_BASE) /,$( SDK_LDDIR) )
SDK_INCDIR := $( addprefix -I$( SDK_BASE) /,$( SDK_INCDIR) )
SDK_TOOLS := $( addprefix $( SDK_BASE) /,$( SDK_TOOLSDIR) )
APPGEN_TOOL := $( addprefix $( SDK_TOOLS) /,$( APPGEN_TOOL) )
SRC := $( foreach sdir,$( SRC_DIR) ,$( wildcard $( sdir) /*.c) )
OBJ := $( patsubst %.c,$( BUILD_BASE) /%.o,$( SRC) ) $( BUILD_BASE) /espfs_img.o
LIBS := $( addprefix -l,$( LIBS) )
APP_AR := $( addprefix $( BUILD_BASE) /,$( TARGET) _app.a)
TARGET_OUT := $( addprefix $( BUILD_BASE) /,$( TARGET) .out)
USER1_OUT := $( addprefix $( BUILD_BASE) /,$( TARGET) .user1.out)
USER2_OUT := $( addprefix $( BUILD_BASE) /,$( TARGET) .user2.out)
INCDIR := $( addprefix -I,$( SRC_DIR) )
EXTRA_INCDIR := $( addprefix -I,$( EXTRA_INCDIR) )
MODULE_INCDIR := $( addsuffix /include,$( INCDIR) )
V ?= $( VERBOSE)
i f e q ( "$(V)" , "1" )
Q :=
vecho := @true
e l s e
Q := @
vecho := @echo
e n d i f
i f e q ( "$(GZIP_COMPRESSION)" , "yes" )
CFLAGS += -DGZIP_COMPRESSION
e n d i f
i f e q ( "$(USE_HEATSHRINK)" , "yes" )
CFLAGS += -DESPFS_HEATSHRINK
e n d i f
v p a t h % . c $( SRC_DIR )
d e f i n e c o m p i l e - o b j e c t s
$1/%.o : %.c
$( vecho) " CC $$ < "
$( Q) $( CC) $( INCDIR) $( MODULE_INCDIR) $( EXTRA_INCDIR) $( SDK_INCDIR) $( CFLAGS) -c $$ < -o $$ @
e n d e f
.PHONY : all checkdirs clean webpages .espfs
all : checkdirs $( FW_BASE ) firmware /user 1.bin firmware /user 2.bin
$(TARGET_OUT) : $( APP_AR ) $( LD_SCRIPT )
$( vecho) " LD $@ "
$( Q) $( LD) -L$( SDK_LIBDIR) -T$( LD_SCRIPT) $( LDFLAGS) -Wl,--start-group $( LIBS) $( APP_AR) -Wl,--end-group -o $@
$( OBJDP) -x $( TARGET_OUT) | egrep '(espfs_img)'
$(USER1_OUT) : $( APP_AR ) $( LD_SCRIPT 1)
$( vecho) " LD $@ "
$( Q) $( LD) -L$( SDK_LIBDIR) -T$( LD_SCRIPT1) $( LDFLAGS) -Wl,--start-group $( LIBS) $( APP_AR) -Wl,--end-group -o $@
# $(Q) $(OBJDP) -x $(TARGET_OUT) | egrep espfs_img
$(USER2_OUT) : $( APP_AR ) $( LD_SCRIPT 2)
$( vecho) " LD $@ "
$( Q) $( LD) -L$( SDK_LIBDIR) -T$( LD_SCRIPT2) $( LDFLAGS) -Wl,--start-group $( LIBS) $( APP_AR) -Wl,--end-group -o $@
# $(Q) $(OBJDP) -x $(TARGET_OUT) | egrep espfs_img
$(FW_BASE) : $( TARGET_OUT )
$( vecho) " FW $@ "
$( Q) mkdir -p $@
$( Q) $( ESPTOOL) elf2image $( TARGET_OUT) --output $@ /
firmware/user1.bin : $( USER 1_OUT )
$( Q) $( OBJCP) --only-section .text -O binary $( USER1_OUT) eagle.app.v6.text.bin
$( Q) $( OBJCP) --only-section .data -O binary $( USER1_OUT) eagle.app.v6.data.bin
$( Q) $( OBJCP) --only-section .rodata -O binary $( USER1_OUT) eagle.app.v6.rodata.bin
$( Q) $( OBJCP) --only-section .irom0.text -O binary $( USER1_OUT) eagle.app.v6.irom0text.bin
ls -ls eagle*bin
$( Q) COMPILE = gcc PATH = $( XTENSA_TOOLS_ROOT) :$( PATH) python $( APPGEN_TOOL) $( USER1_OUT) 2 $( ESP_FLASH_MODE) $( ESP_FLASH_FREQ_DIV) $( ESP_SPI_SIZE)
$( Q) rm -f eagle.app.v6.*.bin
$( Q) mv eagle.app.flash.bin $@
@echo " ** user1.bin uses $$ (stat -c '%s' $@ ) bytes of " $( ESP_FLASH_MAX) "available"
$( Q) if [ $$ ( stat -c '%s' $@ ) -gt $$ ( ( $( ESP_FLASH_MAX) ) ) ] ; then echo " $@ too big! " ; false; fi
firmware/user2.bin : $( USER 2_OUT )
$( Q) $( OBJCP) --only-section .text -O binary $( USER2_OUT) eagle.app.v6.text.bin
$( Q) $( OBJCP) --only-section .data -O binary $( USER2_OUT) eagle.app.v6.data.bin
$( Q) $( OBJCP) --only-section .rodata -O binary $( USER2_OUT) eagle.app.v6.rodata.bin
$( Q) $( OBJCP) --only-section .irom0.text -O binary $( USER2_OUT) eagle.app.v6.irom0text.bin
$( Q) COMPILE = gcc PATH = $( XTENSA_TOOLS_ROOT) :$( PATH) python $( APPGEN_TOOL) $( USER2_OUT) 2 $( ESP_FLASH_MODE) $( ESP_FLASH_FREQ_DIV) $( ESP_SPI_SIZE)
$( Q) rm -f eagle.app.v6.*.bin
$( Q) mv eagle.app.flash.bin $@
$( Q) if [ $$ ( stat -c '%s' $@ ) -gt $$ ( ( $( ESP_FLASH_MAX) ) ) ] ; then echo " $@ too big! " ; false; fi
$(APP_AR) : $( OBJ )
$( vecho) " AR $@ "
$( Q) $( AR) cru $@ $^
checkdirs : $( BUILD_DIR )
$(BUILD_DIR) :
$( Q) mkdir -p $@
wiflash : all
./wiflash $( ESP_HOSTNAME) firmware/user1.bin firmware/user2.bin
flash : $( TARGET_OUT ) $( FW_BASE )
$( Q) $( ESPTOOL) --port $( ESPPORT) --baud $( ESPBAUD) write_flash 0x00000 $( FW_BASE) /0x00000.bin 0x40000 $( FW_BASE) /0x40000.bin
$(BUILD_BASE)/espfs_img.o : html / html /wifi / espfs /mkespfsimage /mkespfsimage
i f e q ( "$(COMPRESS_W_YUI)" , "yes" )
$( Q) rm -rf html_compressed;
$( Q) cp -r html html_compressed;
$( Q) echo "Compression assets with yui-compressor. This may take a while..."
$( Q) for file in ` find html_compressed -type f -name "*.js" ` ; do $( YUI-COMPRESSOR) --type js $$ file -o $$ file; done
$( Q) for file in ` find html_compressed -type f -name "*.css" ` ; do $( YUI-COMPRESSOR) --type css $$ file -o $$ file; done
$( Q) awk "BEGIN {printf \"YUI compression ratio was: %.2f%%\\n\", (`du -b -s html_compressed/ | sed 's/\([0-9]*\).*/\1/'`/`du -b -s html/ | sed 's/\([0-9]*\).*/\1/'`)*100}"
# mkespfsimage will compress html, css and js files with gzip by default if enabled
# override with -g cmdline parameter
$( Q) cd html_compressed; find | ../espfs/mkespfsimage/mkespfsimage > ../build/espfs.img; cd ..;
e l s e
$( Q) cd html; find . \! -name \* - | ../espfs/mkespfsimage/mkespfsimage > ../build/espfs.img; cd ..
e n d i f
$( Q) cd build; $( OBJCP) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data= .espfs \
espfs.img espfs_img.o; cd ..
# edit the loader script to add the espfs section to the end of irom with a 4 byte alignment.
# we also adjust the sizes of the segments 'cause we need more irom0
# in the end the only thing that matters wrt size is that the whole shebang fits into the
# 236KB available (in a 512KB flash)
build/eagle.esphttpd.v6.ld : $( SDK_LDDIR ) /eagle .app .v 6.ld
$( Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \
$( SDK_LDDIR) /eagle.app.v6.ld >$@
build/eagle.esphttpd1.v6.ld : $( SDK_LDDIR ) /eagle .app .v 6.new .512.app 1.ld
$( Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \
-e '/^ irom0_0_seg/ s/2B000/38000/' \
$( SDK_LDDIR) /eagle.app.v6.new.512.app1.ld >$@
build/eagle.esphttpd2.v6.ld : $( SDK_LDDIR ) /eagle .app .v 6.new .512.app 2.ld
$( Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \
-e '/^ irom0_0_seg/ s/2B000/38000/' \
$( SDK_LDDIR) /eagle.app.v6.new.512.app2.ld >$@
blankflash :
$( Q) $( ESPTOOL) --port $( ESPPORT) --baud $( ESPBAUD) write_flash 0x7E000 $( SDK_BASE) /bin/blank.bin
espfs/mkespfsimage/mkespfsimage : espfs /mkespfsimage /
$( Q) $( MAKE) -C espfs/mkespfsimage USE_HEATSHRINK = " $( USE_HEATSHRINK) " GZIP_COMPRESSION = " $( GZIP_COMPRESSION) "
clean :
$( Q) rm -f $( APP_AR)
$( Q) rm -f $( TARGET_OUT)
$( Q) find $( BUILD_BASE) -type f | xargs rm -f
$( Q) make -C espfs/mkespfsimage/ clean
$( Q) rm -rf $( FW_BASE)
$( Q) rm -f webpages.espfs
i f e q ( "$(COMPRESS_W_YUI)" , "yes" )
$( Q) rm -rf html_compressed
e n d i f
$( foreach bdir ,$ ( BUILD_DIR ) ,$ ( eval $ ( call compile -objects ,$ ( bdir ) ) ) )