Merge pull request #136 from SuperHouse/feature/ota_improvements
OTA improvements, always enable OTA mode
This commit is contained in:
		
						commit
						4b39a0e6ca
					
				
					 27 changed files with 730 additions and 514 deletions
				
			
		
							
								
								
									
										4
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -7,3 +7,7 @@
 | 
			
		|||
[submodule "extras/jsmn/jsmn"]
 | 
			
		||||
	path = extras/jsmn/jsmn
 | 
			
		||||
	url = https://github.com/zserge/jsmn.git
 | 
			
		||||
[submodule "bootloader/rboot"]
 | 
			
		||||
	path = bootloader/rboot
 | 
			
		||||
	url = https://github.com/raburton/rboot.git
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,15 +5,12 @@ env:
 | 
			
		|||
  OPENSDK_COMMIT=a48b12f
 | 
			
		||||
  CROSS_ROOT="${HOME}/toolchain-${OPENSDK_COMMIT}"
 | 
			
		||||
  CROSS_BINDIR="${CROSS_ROOT}/bin"
 | 
			
		||||
  ESPTOOL2_COMMIT=ec0e2c7
 | 
			
		||||
  ESPTOOL2_DIR="${HOME}/esptool2-${ESPTOOL2_COMMIT}"
 | 
			
		||||
  PATH=${PATH}:${CROSS_BINDIR}:${ESPTOOL2_DIR}
 | 
			
		||||
  CROSS="ccache xtensa-lx106-elf-"
 | 
			
		||||
  MAKE_CMD="make WARNINGS_AS_ERRORS=1 -C examples/ build-examples"
 | 
			
		||||
  PATH=${PATH}:${CROSS_BINDIR}
 | 
			
		||||
cache:
 | 
			
		||||
  directories:
 | 
			
		||||
    - ${CROSS_ROOT}
 | 
			
		||||
    - ${ESPTOOL2_DIR}
 | 
			
		||||
addons:
 | 
			
		||||
  apt:
 | 
			
		||||
    packages:
 | 
			
		||||
| 
						 | 
				
			
			@ -35,9 +32,9 @@ addons:
 | 
			
		|||
    - python-serial
 | 
			
		||||
    - sed
 | 
			
		||||
    - git
 | 
			
		||||
    - vim-common
 | 
			
		||||
 | 
			
		||||
before_install:
 | 
			
		||||
  - utils/travis_build/install_esptool2.sh
 | 
			
		||||
  - travis_wait 30 utils/travis_build/install_toolchain.sh
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
| 
						 | 
				
			
			@ -46,3 +43,5 @@ script:
 | 
			
		|||
  - sed -i "s%#error%//#error%" include/ssid_config.h
 | 
			
		||||
  # Don't verbose-build all examples (too much output), only verbose-build errors
 | 
			
		||||
  - ( ${MAKE_CMD} ) || ( ${MAKE_CMD} V=1 )
 | 
			
		||||
  # build bootloader
 | 
			
		||||
  - make -C bootloader/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										59
									
								
								bootloader/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								bootloader/Makefile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
# This is a wrapper around the rboot makefile, which gives us the parameters
 | 
			
		||||
# we need to use rboot with esp-open-rtos.
 | 
			
		||||
#
 | 
			
		||||
# Use 'make bootloader' to build a custom bootloader.
 | 
			
		||||
#
 | 
			
		||||
# 'make flash' for any esp-open-rtos program will use the compiled
 | 
			
		||||
# bootloader if it exists, or a prebuilt bootloader if no custom
 | 
			
		||||
# bootloader was compiled.
 | 
			
		||||
#
 | 
			
		||||
# The wrapper means we don't require esptool2 in the build process, so we can just use
 | 
			
		||||
# esptool.py (still need xxd, grep, sed to generate the header - see below.)
 | 
			
		||||
BOOTLOADER_DIR:=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
 | 
			
		||||
 | 
			
		||||
include ../parameters.mk
 | 
			
		||||
 | 
			
		||||
all: $(FIRMWARE_DIR)/rboot.bin
 | 
			
		||||
 | 
			
		||||
rboot/Makefile:
 | 
			
		||||
	$(error rboot git submodule is not checkedo out. Try running 'git submodule update --init --recursive')
 | 
			
		||||
 | 
			
		||||
$(FIRMWARE_DIR)/rboot.bin: $(BUILD_DIR)/rboot.elf $(FIRMWARE_DIR)
 | 
			
		||||
	@echo "FW rboot.bin"
 | 
			
		||||
	$(Q) $(ESPTOOL) elf2image $(ESPTOOL_ARGS) $< -o $(BUILD_DIR)/
 | 
			
		||||
	$(Q) mv $(BUILD_DIR)/0x00000.bin $@
 | 
			
		||||
 | 
			
		||||
# rboot generates this header using the 'esptool2 -header' option. To try and avoid
 | 
			
		||||
# esptool2 as a dependency, we try it here using grep, sed, xxd (all fairly common Unix tools)
 | 
			
		||||
$(BUILD_DIR)/rboot-hex2a.h: $(BUILD_DIR)/rboot-stage2a.elf $(BUILD_DIR)
 | 
			
		||||
	@echo "Extracting stub image header..."
 | 
			
		||||
	$(Q) xtensa-lx106-elf-objcopy $< --only-section .text -Obinary $(BUILD_DIR)/rboot-hex2a.bin
 | 
			
		||||
	$(Q) xxd -i $(BUILD_DIR)/rboot-hex2a.bin > $@.in
 | 
			
		||||
	$(Q) sed -i "s/unsigned char .\+\[\]/const uint8 _text_data[]/" $@.in
 | 
			
		||||
	$(Q) sed -i "s/unsigned int .\+_len/const uint32 _text_len/" $@.in
 | 
			
		||||
	$(Q) echo "const uint32 entry_addr = $$(xtensa-lx106-elf-objdump -f $< | grep 'start address' | grep -o '0x.\+');" >> $@.in
 | 
			
		||||
	$(Q) echo "const uint32 _text_addr = 0x$$(xtensa-lx106-elf-objdump -h -j .text $< | grep ".text" | grep -o '401.....' | head -n1);" >> $@.in
 | 
			
		||||
	$(Q) mv $@.in $@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RBOOT_BUILD_BASE="$(abspath $(BUILD_DIR))"
 | 
			
		||||
RBOOT_FW_BASE="$(abspath $(FIRMWARE_DIR))"
 | 
			
		||||
MAKE_VARS=RBOOT_EXTRA_INCDIR=$(BOOTLOADER_DIR) RBOOT_BUILD_BASE=$(RBOOT_BUILD_BASE) RBOOT_FW_BASE=$(RBOOT_FW_BASE)
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)/rboot-stage2a.elf: $(BUILD_DIR)
 | 
			
		||||
	$(Q) $(MAKE) -C rboot $(RBOOT_BUILD_BASE)/rboot-stage2a.elf $(MAKE_VARS)
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)/rboot.elf: $(BUILD_DIR)/rboot-hex2a.h
 | 
			
		||||
	$(Q) $(MAKE) -C rboot $(RBOOT_BUILD_BASE)/rboot.elf $(MAKE_VARS)
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR) $(FIRMWARE_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
flash: $(FIRMWARE_DIR)/rboot.bin
 | 
			
		||||
	$(Q) $(ESPTOOL) -p $(ESPPORT) -b $(ESPBAUD) write_flash $(ESPTOOL_ARGS) 0x0 $<
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	$(Q) rm -rf $(BUILD_DIR)
 | 
			
		||||
	$(Q) rm -rf $(FIRMWARE_DIR)
 | 
			
		||||
 | 
			
		||||
.PHONY: all
 | 
			
		||||
							
								
								
									
										12
									
								
								bootloader/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								bootloader/README.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
OTA Bootloader (rboot) source module and support files.
 | 
			
		||||
 | 
			
		||||
rboot is an open source bootloader by Richard Burton:
 | 
			
		||||
https://github.com/raburton/rboot
 | 
			
		||||
 | 
			
		||||
Can be used to build an esp-open-rtos compatible rboot bootloader. Run 'make bootloader' in this directory to compile a new bootloader.
 | 
			
		||||
 | 
			
		||||
Compiling a new bootloader is optional, there's a prebuilt one in the "firmware_prebuilt" directory that will be used if no new bootloader was compiled.
 | 
			
		||||
 | 
			
		||||
It is also possible to use rboot from upstream verbatim, but *ensure that the `RBOOT_BIG_FLASH` option is enabled or images in slots other than 0 won't work correctly.
 | 
			
		||||
 | 
			
		||||
See the contents of the 'rboot' directory for more information on rboot.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								bootloader/firmware_prebuilt/blank_config.bin
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bootloader/firmware_prebuilt/blank_config.bin
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bootloader/firmware_prebuilt/rboot.bin
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bootloader/firmware_prebuilt/rboot.bin
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								bootloader/rboot
									
										
									
									
									
										Submodule
									
								
							
							
						
						
									
										1
									
								
								bootloader/rboot
									
										
									
									
									
										Submodule
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
Subproject commit 30afbaa777e00abf9d7d469fb3345f118c4975c1
 | 
			
		||||
							
								
								
									
										23
									
								
								bootloader/rboot.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								bootloader/rboot.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
/* rboot header overrides
 | 
			
		||||
 | 
			
		||||
   This "wrapper" header contains default values for building rboot
 | 
			
		||||
   on/for esp-open-rtos. It gets included both when building the
 | 
			
		||||
   bootloader and when building extras/rboot-ota support. It includes
 | 
			
		||||
   the default bootloader/rboot/rboot.h header via the gcc
 | 
			
		||||
   include_next mechanism.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef __RBOOT_H__
 | 
			
		||||
 | 
			
		||||
// Big flash support is required for esp-open-rtos (we use 8Mbit
 | 
			
		||||
// "slots" only.)
 | 
			
		||||
#define BOOT_BIG_FLASH
 | 
			
		||||
 | 
			
		||||
// enable 2 way communication between
 | 
			
		||||
// rBoot and the user app via the esp rtc data area
 | 
			
		||||
#define BOOT_RTC_ENABLED
 | 
			
		||||
 | 
			
		||||
// Call 'main' rboot.h to pick up defaults for other parameters
 | 
			
		||||
#include_next "rboot.h"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										187
									
								
								common.mk
									
										
									
									
									
								
							
							
						
						
									
										187
									
								
								common.mk
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -20,156 +20,10 @@
 | 
			
		|||
# assume the 'root' directory (ie top of the tree) is the directory common.mk is in
 | 
			
		||||
ROOT := $(dir $(lastword $(MAKEFILE_LIST)))
 | 
			
		||||
 | 
			
		||||
# include optional local overrides at the root level, then in program directory
 | 
			
		||||
#
 | 
			
		||||
# Create either of these files for local system overrides if possible,
 | 
			
		||||
# instead of editing this makefile directly.
 | 
			
		||||
-include $(ROOT)local.mk
 | 
			
		||||
-include local.mk
 | 
			
		||||
 | 
			
		||||
# Flash size in megabits
 | 
			
		||||
# Valid values are same as for esptool.py - 2,4,8,16,32
 | 
			
		||||
FLASH_SIZE ?= 16
 | 
			
		||||
 | 
			
		||||
# Flash mode, valid values are same as for esptool.py - qio,qout,dio.dout
 | 
			
		||||
FLASH_MODE ?= qio
 | 
			
		||||
 | 
			
		||||
# Flash speed in MHz, valid values are same as for esptool.py - 80, 40, 26, 20
 | 
			
		||||
FLASH_SPEED ?= 40
 | 
			
		||||
 | 
			
		||||
# Output directories to store intermediate compiled files
 | 
			
		||||
# relative to the program directory
 | 
			
		||||
BUILD_DIR ?= $(PROGRAM_DIR)build/
 | 
			
		||||
FIRMWARE_DIR ?= $(PROGRAM_DIR)firmware/
 | 
			
		||||
 | 
			
		||||
# esptool.py from https://github.com/themadinventor/esptool
 | 
			
		||||
ESPTOOL ?= esptool.py
 | 
			
		||||
# serial port settings for esptool.py
 | 
			
		||||
ESPPORT ?= /dev/ttyUSB0
 | 
			
		||||
ESPBAUD ?= 115200
 | 
			
		||||
 | 
			
		||||
# set this to 0 if you don't need floating point support in printf/scanf
 | 
			
		||||
# this will save approx 14.5KB flash space and 448 bytes of statically allocated
 | 
			
		||||
# data RAM
 | 
			
		||||
#
 | 
			
		||||
# NB: Setting the value to 0 requires a recent esptool.py (Feb 2016 / commit ebf02c9)
 | 
			
		||||
PRINTF_SCANF_FLOAT_SUPPORT ?= 1
 | 
			
		||||
 | 
			
		||||
# Set OTA to 1 to build an image that supports rBoot OTA bootloader
 | 
			
		||||
#
 | 
			
		||||
# Currently only works with 16mbit or more flash sizes, with 8mbit
 | 
			
		||||
# images for each "slot"
 | 
			
		||||
OTA ?= 0
 | 
			
		||||
 | 
			
		||||
ifeq ($(OTA),1)
 | 
			
		||||
# for OTA, we build a "SDK v1.2 bootloader" compatible image where everything is in
 | 
			
		||||
# one file (should work with the v1.2 binary bootloader, and the FOSS rBoot bootloader).
 | 
			
		||||
IMGTOOL ?= esptool2
 | 
			
		||||
 | 
			
		||||
# Tell C preprocessor that we're building for OTA
 | 
			
		||||
CPPFLAGS = -DOTA
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
FLAVOR ?= release # or debug
 | 
			
		||||
 | 
			
		||||
# Compiler names, etc. assume gdb
 | 
			
		||||
CROSS ?= xtensa-lx106-elf-
 | 
			
		||||
 | 
			
		||||
# Path to the filteroutput.py tool
 | 
			
		||||
FILTEROUTPUT ?= $(ROOT)/utils/filteroutput.py
 | 
			
		||||
 | 
			
		||||
AR = $(CROSS)ar
 | 
			
		||||
CC = $(CROSS)gcc
 | 
			
		||||
CPP = $(CROSS)cpp
 | 
			
		||||
LD = $(CROSS)gcc
 | 
			
		||||
NM = $(CROSS)nm
 | 
			
		||||
C++ = $(CROSS)g++
 | 
			
		||||
SIZE = $(CROSS)size
 | 
			
		||||
OBJCOPY = $(CROSS)objcopy
 | 
			
		||||
OBJDUMP = $(CROSS)objdump
 | 
			
		||||
 | 
			
		||||
# Source components to compile and link. Each of these are subdirectories
 | 
			
		||||
# of the root, with a 'component.mk' file.
 | 
			
		||||
COMPONENTS     ?= $(EXTRA_COMPONENTS) FreeRTOS lwip core
 | 
			
		||||
 | 
			
		||||
# binary esp-iot-rtos SDK libraries to link. These are pre-processed prior to linking.
 | 
			
		||||
SDK_LIBS		?= main net80211 phy pp wpa
 | 
			
		||||
 | 
			
		||||
# open source libraries linked in
 | 
			
		||||
LIBS ?= hal gcc c
 | 
			
		||||
 | 
			
		||||
# set to 0 if you want to use the toolchain libc instead of esp-open-rtos newlib
 | 
			
		||||
OWN_LIBC ?= 1
 | 
			
		||||
 | 
			
		||||
# Note: you will need a recent esp
 | 
			
		||||
ENTRY_SYMBOL ?= call_user_start
 | 
			
		||||
 | 
			
		||||
# Set this to zero if you don't want individual function & data sections
 | 
			
		||||
# (some code may be slightly slower, linking will be slighty slower,
 | 
			
		||||
# but compiled code size will come down a small amount.)
 | 
			
		||||
SPLIT_SECTIONS ?= 1
 | 
			
		||||
 | 
			
		||||
# Set this to 1 to have all compiler warnings treated as errors (and stop the
 | 
			
		||||
# build).  This is recommended whenever you are working on code which will be
 | 
			
		||||
# submitted back to the main project, as all submitted code will be expected to
 | 
			
		||||
# compile without warnings to be accepted.
 | 
			
		||||
WARNINGS_AS_ERRORS ?= 0
 | 
			
		||||
 | 
			
		||||
# Common flags for both C & C++_
 | 
			
		||||
C_CXX_FLAGS ?= -Wall -Wl,-EL -nostdlib $(EXTRA_C_CXX_FLAGS)
 | 
			
		||||
# Flags for C only
 | 
			
		||||
CFLAGS		?= $(C_CXX_FLAGS) -std=gnu99 $(EXTRA_CFLAGS)
 | 
			
		||||
# Flags for C++ only
 | 
			
		||||
CXXFLAGS	?= $(C_CXX_FLAGS) -fno-exceptions -fno-rtti $(EXTRA_CXXFLAGS)
 | 
			
		||||
 | 
			
		||||
# these aren't technically preprocesor args, but used by all 3 of C, C++, assembler
 | 
			
		||||
CPPFLAGS	+= -mlongcalls -mtext-section-literals
 | 
			
		||||
 | 
			
		||||
LDFLAGS		= -nostdlib -Wl,--no-check-sections -L$(BUILD_DIR)sdklib -L$(ROOT)lib -u $(ENTRY_SYMBOL) -Wl,-static -Wl,-Map=$(BUILD_DIR)$(PROGRAM).map $(EXTRA_LDFLAGS)
 | 
			
		||||
 | 
			
		||||
ifeq ($(WARNINGS_AS_ERRORS),1)
 | 
			
		||||
    C_CXX_FLAGS += -Werror
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(SPLIT_SECTIONS),1)
 | 
			
		||||
  C_CXX_FLAGS += -ffunction-sections -fdata-sections
 | 
			
		||||
  LDFLAGS += -Wl,-gc-sections
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(FLAVOR),debug)
 | 
			
		||||
    C_CXX_FLAGS += -g -O0
 | 
			
		||||
    LDFLAGS += -g -O0
 | 
			
		||||
else ifeq ($(FLAVOR),sdklike)
 | 
			
		||||
    # These are flags intended to produce object code as similar as possible to
 | 
			
		||||
    # the output of the compiler used to build the SDK libs (for comparison of
 | 
			
		||||
    # disassemblies when coding replacement routines).  It is not normally
 | 
			
		||||
    # intended to be used otherwise.
 | 
			
		||||
    CFLAGS += -O2 -Os -fno-inline -fno-ipa-cp -fno-toplevel-reorder
 | 
			
		||||
    LDFLAGS += -O2
 | 
			
		||||
else
 | 
			
		||||
    C_CXX_FLAGS += -g -O2
 | 
			
		||||
    LDFLAGS += -g -O2
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
GITSHORTREV=\"$(shell cd $(ROOT); git rev-parse --short -q HEAD 2> /dev/null)\"
 | 
			
		||||
ifeq ($(GITSHORTREV),\"\")
 | 
			
		||||
  GITSHORTREV="\"(nogit)\"" # (same length as a short git hash)
 | 
			
		||||
endif
 | 
			
		||||
CPPFLAGS += -DGITSHORTREV=$(GITSHORTREV)
 | 
			
		||||
 | 
			
		||||
ifeq ($(OTA),0)
 | 
			
		||||
LINKER_SCRIPTS  = $(ROOT)ld/nonota.ld
 | 
			
		||||
else
 | 
			
		||||
LINKER_SCRIPTS = $(ROOT)ld/ota.ld
 | 
			
		||||
endif
 | 
			
		||||
LINKER_SCRIPTS += $(ROOT)ld/common.ld $(ROOT)ld/rom.ld
 | 
			
		||||
 | 
			
		||||
####
 | 
			
		||||
#### no user configurable options below here
 | 
			
		||||
####
 | 
			
		||||
include $(ROOT)parameters.mk
 | 
			
		||||
 | 
			
		||||
ifndef PROGRAM
 | 
			
		||||
	$(error "Set the PROGRAM environment variable in your Makefile before including common.mk"
 | 
			
		||||
$(error "Set the PROGRAM environment variable in your Makefile before including common.mk")
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# hacky way to get a single space value
 | 
			
		||||
| 
						 | 
				
			
			@ -188,28 +42,7 @@ LIB_ARGS      = $(addprefix -l,$(LIBS))
 | 
			
		|||
PROGRAM_OUT   = $(BUILD_DIR)$(PROGRAM).out
 | 
			
		||||
LDFLAGS      += $(addprefix -T,$(LINKER_SCRIPTS))
 | 
			
		||||
 | 
			
		||||
ifeq ($(OTA),0)
 | 
			
		||||
# for non-OTA, we create two different files for uploading into the flash
 | 
			
		||||
# these are the names and options to generate them
 | 
			
		||||
FW_ADDR_1	= 0x00000
 | 
			
		||||
FW_ADDR_2	= 0x20000
 | 
			
		||||
FW_FILE_1    = $(addprefix $(FIRMWARE_DIR),$(FW_ADDR_1).bin)
 | 
			
		||||
FW_FILE_2    = $(addprefix $(FIRMWARE_DIR),$(FW_ADDR_2).bin)
 | 
			
		||||
else
 | 
			
		||||
# for OTA, it's a single monolithic image
 | 
			
		||||
FW_FILE = $(addprefix $(FIRMWARE_DIR),$(PROGRAM).bin)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# firmware tool arguments
 | 
			
		||||
ESPTOOL_ARGS=-fs $(FLASH_SIZE)m -fm $(FLASH_MODE) -ff $(FLASH_SPEED)m
 | 
			
		||||
 | 
			
		||||
IMGTOOL_FLASH_SIZE_2=256
 | 
			
		||||
IMGTOOL_FLASH_SIZE_4=512
 | 
			
		||||
IMGTOOL_FLASH_SIZE_8=1024
 | 
			
		||||
IMGTOOL_FLASH_SIZE_16=2048
 | 
			
		||||
IMGTOOL_FLASH_SIZE_32=4096
 | 
			
		||||
IMGTOOL_FLASH_SIZE=$(value IMGTOOL_FLASH_SIZE_$(FLASH_SIZE))
 | 
			
		||||
IMGTOOL_ARGS=-$(IMGTOOL_FLASH_SIZE) -$(FLASH_MODE) -$(FLASH_SPEED)
 | 
			
		||||
 | 
			
		||||
# Common include directories, shared across all "components"
 | 
			
		||||
# components will add their include directories to this argument
 | 
			
		||||
| 
						 | 
				
			
			@ -235,7 +68,7 @@ Q := @
 | 
			
		|||
vecho := @echo
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
.PHONY: all clean debug_print
 | 
			
		||||
.PHONY: all clean flash erase_flash
 | 
			
		||||
 | 
			
		||||
all: $(PROGRAM_OUT) $(FW_FILE_1) $(FW_FILE_2) $(FW_FILE)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -373,16 +206,14 @@ $(FW_FILE_1) $(FW_FILE_2): $(PROGRAM_OUT) $(FIRMWARE_DIR)
 | 
			
		|||
	$(Q) $(ESPTOOL) elf2image $(ESPTOOL_ARGS) $< -o $(FIRMWARE_DIR)
 | 
			
		||||
 | 
			
		||||
$(FW_FILE): $(PROGRAM_OUT) $(FIRMWARE_DIR)
 | 
			
		||||
	$(Q) $(IMGTOOL) $(IMGTOOL_ARGS) -bin -boot2 $(PROGRAM_OUT) $(FW_FILE) .text .data .rodata
 | 
			
		||||
	$(vecho) "FW $@"
 | 
			
		||||
	$(Q) $(ESPTOOL) elf2image --version=2 $(ESPTOOL_ARGS) $< -o $(FW_FILE)
 | 
			
		||||
 | 
			
		||||
ifeq ($(OTA),0)
 | 
			
		||||
flash: $(FW_FILE_1) $(FW_FILE_2)
 | 
			
		||||
	$(ESPTOOL) -p $(ESPPORT) --baud $(ESPBAUD) write_flash $(ESPTOOL_ARGS) $(FW_ADDR_2) $(FW_FILE_2) $(FW_ADDR_1) $(FW_FILE_1)
 | 
			
		||||
else
 | 
			
		||||
flash: $(FW_FILE)
 | 
			
		||||
	$(vecho) "Flashing OTA image slot 0 (bootloader not updated)"
 | 
			
		||||
	$(ESPTOOL) -p $(ESPPORT) --baud $(ESPBAUD) write_flash $(ESPTOOL_ARGS) 0x2000 $(FW_FILE)
 | 
			
		||||
endif
 | 
			
		||||
	$(ESPTOOL) -p $(ESPPORT) --baud $(ESPBAUD) write_flash $(ESPTOOL_ARGS) 0x0 $(RBOOT_BIN) 0x1000 $(RBOOT_CONF) 0x2000 $(FW_FILE)
 | 
			
		||||
 | 
			
		||||
erase_flash:
 | 
			
		||||
	$(ESPTOOL) -p $(ESPPORT) --baud $(ESPBAUD) erase_flash
 | 
			
		||||
 | 
			
		||||
size: $(PROGRAM_OUT)
 | 
			
		||||
	$(Q) $(CROSS)size --format=sysv $(PROGRAM_OUT)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,8 +12,6 @@
 | 
			
		|||
 * Copyright (C) 2015 Superhouse Automation Pty Ltd
 | 
			
		||||
 * BSD Licensed as described in the file LICENSE
 | 
			
		||||
*/
 | 
			
		||||
#ifdef OTA
 | 
			
		||||
 | 
			
		||||
#define RBOOT_CONFIG_BASE (0x40200000 + 0x1000)
 | 
			
		||||
#define RBOOT_ROMS_OFFS 0x8 /* offset of rboot_config_t.roms array in config */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -74,5 +72,3 @@ Cache_Read_Enable:
 | 
			
		|||
	movi a0, cache_return_save /* restore a0 return address */
 | 
			
		||||
	l32i a0, a0, 0
 | 
			
		||||
	ret.n
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
PROGRAM=ota_basic
 | 
			
		||||
OTA=1
 | 
			
		||||
EXTRA_COMPONENTS=extras/rboot-ota
 | 
			
		||||
EXTRA_COMPONENTS=extras/rboot-ota extras/mbedtls
 | 
			
		||||
include ../../common.mk
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,23 +1,121 @@
 | 
			
		|||
/* A very simple OTA example
 | 
			
		||||
 *
 | 
			
		||||
 * Binds a TCP socket, reads an image from it over TFTP and then flashes live.
 | 
			
		||||
 * Tries to run both a TFTP client and a TFTP server simultaneously, either will accept a TTP firmware and update it.
 | 
			
		||||
 *
 | 
			
		||||
 * Not a realistic OTA setup, this needs adapting (choose either client or server) before you'd want to use it.
 | 
			
		||||
 *
 | 
			
		||||
 * For more information about esp-open-rtos OTA see https://github.com/SuperHouse/esp-open-rtos/wiki/OTA-Update-Configuration
 | 
			
		||||
 *
 | 
			
		||||
 * NOT SUITABLE TO PUT ON THE INTERNET OR INTO A PRODUCTION ENVIRONMENT!!!!
 | 
			
		||||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "espressif/esp_common.h"
 | 
			
		||||
#include "esp/uart.h"
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
#include "esp8266.h"
 | 
			
		||||
#include "ssid_config.h"
 | 
			
		||||
#include "mbedtls/sha256.h"
 | 
			
		||||
 | 
			
		||||
#include "ota-tftp.h"
 | 
			
		||||
#include "rboot-integration.h"
 | 
			
		||||
#include "rboot.h"
 | 
			
		||||
#include "rboot-api.h"
 | 
			
		||||
 | 
			
		||||
/* TFTP client will request this image filenames from this server */
 | 
			
		||||
#define TFTP_IMAGE_SERVER "192.168.1.23"
 | 
			
		||||
#define TFTP_IMAGE_FILENAME1 "firmware1.bin"
 | 
			
		||||
#define TFTP_IMAGE_FILENAME2 "firmware2.bin"
 | 
			
		||||
 | 
			
		||||
/* Output of the command 'sha256sum firmware1.bin' */
 | 
			
		||||
static const char *FIRMWARE1_SHA256 = "88199daff8b9e76975f685ec7f95bc1df3c61bd942a33a54a40707d2a41e5488";
 | 
			
		||||
 | 
			
		||||
/* Example function to TFTP download a firmware file and verify its SHA256 before
 | 
			
		||||
   booting into it.
 | 
			
		||||
*/
 | 
			
		||||
static void tftpclient_download_and_verify_file1(int slot, rboot_config *conf)
 | 
			
		||||
{
 | 
			
		||||
    printf("Downloading %s to slot %d...\n", TFTP_IMAGE_FILENAME1, slot);
 | 
			
		||||
    int res = ota_tftp_download(TFTP_IMAGE_SERVER, TFTP_PORT+1, TFTP_IMAGE_FILENAME1, 1000, slot, NULL);
 | 
			
		||||
    printf("ota_tftp_download %s result %d\n", TFTP_IMAGE_FILENAME1, res);
 | 
			
		||||
 | 
			
		||||
    if (res != 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("Looks valid, calculating SHA256...\n");
 | 
			
		||||
    uint32_t length;
 | 
			
		||||
    bool valid = rboot_verify_image(conf->roms[slot], &length, NULL);
 | 
			
		||||
    static mbedtls_sha256_context ctx;
 | 
			
		||||
    mbedtls_sha256_init(&ctx);
 | 
			
		||||
    mbedtls_sha256_starts(&ctx, 0);
 | 
			
		||||
    valid = valid && rboot_digest_image(conf->roms[slot], length, (rboot_digest_update_fn)mbedtls_sha256_update, &ctx);
 | 
			
		||||
    static uint8_t hash_result[32];
 | 
			
		||||
    mbedtls_sha256_finish(&ctx, hash_result);
 | 
			
		||||
    mbedtls_sha256_free(&ctx);
 | 
			
		||||
 | 
			
		||||
    if(!valid)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Not valid after all :(\n");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("Image SHA256 = ");
 | 
			
		||||
    valid = true;
 | 
			
		||||
    for(int i = 0; i < sizeof(hash_result); i++) {
 | 
			
		||||
        char hexbuf[3];
 | 
			
		||||
        snprintf(hexbuf, 3, "%02x", hash_result[i]);
 | 
			
		||||
        printf(hexbuf);
 | 
			
		||||
        if(strncmp(hexbuf, FIRMWARE1_SHA256+i*2, 2))
 | 
			
		||||
            valid = false;
 | 
			
		||||
    }
 | 
			
		||||
    printf("\n");
 | 
			
		||||
 | 
			
		||||
    if(!valid) {
 | 
			
		||||
        printf("Downloaded image SHA256 didn't match expected '%s'\n", FIRMWARE1_SHA256);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("SHA256 Matches. Rebooting into slot %d...\n", slot);
 | 
			
		||||
    rboot_set_current_rom(slot);
 | 
			
		||||
    sdk_system_restart();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Much simpler function that just downloads a file via TFTP into an rboot slot.
 | 
			
		||||
 | 
			
		||||
   (
 | 
			
		||||
 */
 | 
			
		||||
static void tftpclient_download_file2(int slot)
 | 
			
		||||
{
 | 
			
		||||
    printf("Downloading %s to slot %d...\n", TFTP_IMAGE_FILENAME2, slot);
 | 
			
		||||
    int res = ota_tftp_download(TFTP_IMAGE_SERVER, TFTP_PORT+1, TFTP_IMAGE_FILENAME2, 1000, slot, NULL);
 | 
			
		||||
    printf("ota_tftp_download %s result %d\n", TFTP_IMAGE_FILENAME2, res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tftp_client_task(void *pvParameters)
 | 
			
		||||
{
 | 
			
		||||
    printf("TFTP client task starting...\n");
 | 
			
		||||
    rboot_config conf;
 | 
			
		||||
    conf = rboot_get_config();
 | 
			
		||||
    int slot = (conf.current_rom + 1) % conf.count;
 | 
			
		||||
    printf("Image will be saved in OTA slot %d.\n", slot);
 | 
			
		||||
    if(slot == conf.current_rom) {
 | 
			
		||||
        printf("FATAL ERROR: Only one OTA slot is configured!\n");
 | 
			
		||||
        while(1) {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Alternate between trying two different filenames. Probalby want to change this if making a practical
 | 
			
		||||
       example!
 | 
			
		||||
 | 
			
		||||
       Note: example will reboot into FILENAME1 if it is successfully downloaded, but FILENAME2 is ignored.
 | 
			
		||||
    */
 | 
			
		||||
    while(1) {
 | 
			
		||||
        tftpclient_download_and_verify_file1(slot, &conf);
 | 
			
		||||
        vTaskDelay(5000 / portTICK_RATE_MS);
 | 
			
		||||
 | 
			
		||||
        tftpclient_download_file2(slot);
 | 
			
		||||
        vTaskDelay(5000 / portTICK_RATE_MS);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void user_init(void)
 | 
			
		||||
{
 | 
			
		||||
    uart_set_baud(0, 115200);
 | 
			
		||||
| 
						 | 
				
			
			@ -38,5 +136,7 @@ void user_init(void)
 | 
			
		|||
    sdk_wifi_set_opmode(STATION_MODE);
 | 
			
		||||
    sdk_wifi_station_set_config(&config);
 | 
			
		||||
 | 
			
		||||
    printf("Starting TFTP server...");
 | 
			
		||||
    ota_tftp_init_server(TFTP_PORT);
 | 
			
		||||
    xTaskCreate(&tftp_client_task, (signed char *)"tftp_client", 2048, NULL, 2, NULL);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,9 @@
 | 
			
		|||
# Component makefile for extras/rboot-ota
 | 
			
		||||
 | 
			
		||||
INC_DIRS += $(rboot-ota_ROOT)
 | 
			
		||||
# global include directories need to find rboot.h for integration, even 
 | 
			
		||||
# when just including rboot-api.h :(
 | 
			
		||||
INC_DIRS += $(rboot-ota_ROOT) $(ROOT)bootloader $(ROOT)bootloader/rboot
 | 
			
		||||
 | 
			
		||||
# args for passing into compile rule generation
 | 
			
		||||
rboot-ota_SRC_DIR =  $(rboot-ota_ROOT)
 | 
			
		||||
 | 
			
		||||
$(eval $(call component_compile_rules,rboot-ota))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,12 +22,12 @@
 | 
			
		|||
#include <espressif/esp_system.h>
 | 
			
		||||
 | 
			
		||||
#include "ota-tftp.h"
 | 
			
		||||
#include "rboot.h"
 | 
			
		||||
#include "rboot-api.h"
 | 
			
		||||
 | 
			
		||||
#define TFTP_FIRMWARE_FILE "firmware.bin"
 | 
			
		||||
#define TFTP_OCTET_MODE "octet" /* non-case-sensitive */
 | 
			
		||||
 | 
			
		||||
#define TFTP_OP_RRQ 1
 | 
			
		||||
#define TFTP_OP_WRQ 2
 | 
			
		||||
#define TFTP_OP_DATA 3
 | 
			
		||||
#define TFTP_OP_ACK 4
 | 
			
		||||
| 
						 | 
				
			
			@ -43,8 +43,9 @@
 | 
			
		|||
 | 
			
		||||
static void tftp_task(void *port_p);
 | 
			
		||||
static char *tftp_get_field(int field, struct netbuf *netbuf);
 | 
			
		||||
static err_t tftp_receive_data(struct netconn *nc, size_t write_offs, size_t limit_offs, size_t *received_len);
 | 
			
		||||
static err_t tftp_receive_data(struct netconn *nc, size_t write_offs, size_t limit_offs, size_t *received_len, ip_addr_t *peer_addr, int peer_port, tftp_receive_cb receive_cb);
 | 
			
		||||
static err_t tftp_send_ack(struct netconn *nc, int block);
 | 
			
		||||
static err_t tftp_send_rrq(struct netconn *nc, const char *filename);
 | 
			
		||||
static void tftp_send_error(struct netconn *nc, int err_code, const char *err_msg);
 | 
			
		||||
 | 
			
		||||
void ota_tftp_init_server(int listen_port)
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +53,62 @@ void ota_tftp_init_server(int listen_port)
 | 
			
		|||
    xTaskCreate(tftp_task, (signed char *)"tftpOTATask", 512, (void *)listen_port, 2, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
err_t ota_tftp_download(const char *server, int port, const char *filename,
 | 
			
		||||
                        int timeout, int ota_slot, tftp_receive_cb receive_cb)
 | 
			
		||||
{
 | 
			
		||||
    rboot_config rboot_config = rboot_get_config();
 | 
			
		||||
    /* Validate the OTA slot parameter */
 | 
			
		||||
    if(rboot_config.current_rom == ota_slot || rboot_config.count <= ota_slot)
 | 
			
		||||
    {
 | 
			
		||||
        return ERR_VAL;
 | 
			
		||||
    }
 | 
			
		||||
    /* This is all we need to know from the rboot config - where we need
 | 
			
		||||
       to write data to.
 | 
			
		||||
    */
 | 
			
		||||
    uint32_t flash_offset = rboot_config.roms[ota_slot];
 | 
			
		||||
 | 
			
		||||
    struct netconn *nc = netconn_new (NETCONN_UDP);
 | 
			
		||||
    err_t err;
 | 
			
		||||
    if(!nc) {
 | 
			
		||||
        return ERR_IF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    netconn_set_recvtimeout(nc, timeout);
 | 
			
		||||
 | 
			
		||||
    /* try to bind our client port as our local port,
 | 
			
		||||
       or keep trying the next 10 ports after it */
 | 
			
		||||
    int local_port = port-1;
 | 
			
		||||
    do {
 | 
			
		||||
        err = netconn_bind(nc, IP_ADDR_ANY, ++local_port);
 | 
			
		||||
    } while(err == ERR_USE && local_port < port + 10);
 | 
			
		||||
    if(err) {
 | 
			
		||||
        netconn_delete(nc);
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ip_addr_t addr;
 | 
			
		||||
    err = netconn_gethostbyname(server, &addr);
 | 
			
		||||
    if(err) {
 | 
			
		||||
        netconn_delete(nc);
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    netconn_connect(nc, &addr, port);
 | 
			
		||||
 | 
			
		||||
    err = tftp_send_rrq(nc, filename);
 | 
			
		||||
    if(err) {
 | 
			
		||||
        netconn_delete(nc);
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t received_len;
 | 
			
		||||
    err = tftp_receive_data(nc, flash_offset, flash_offset+MAX_IMAGE_SIZE,
 | 
			
		||||
                            &received_len, &addr, port, receive_cb);
 | 
			
		||||
    netconn_delete(nc);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void tftp_task(void *listen_port)
 | 
			
		||||
{
 | 
			
		||||
    struct netconn *nc = netconn_new (NETCONN_UDP);
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +157,7 @@ static void tftp_task(void *listen_port)
 | 
			
		|||
 | 
			
		||||
        /* check mode */
 | 
			
		||||
        char *mode = tftp_get_field(1, netbuf);
 | 
			
		||||
        if(!mode || strcmp("octet", mode)) {
 | 
			
		||||
        if(!mode || strcmp(TFTP_OCTET_MODE, mode)) {
 | 
			
		||||
            tftp_send_error(nc, TFTP_ERR_ILLEGAL, "Mode must be octet/binary");
 | 
			
		||||
            free(mode);
 | 
			
		||||
            netbuf_delete(netbuf);
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +190,8 @@ static void tftp_task(void *listen_port)
 | 
			
		|||
 | 
			
		||||
        /* Finished WRQ phase, start TFTP data transfer */
 | 
			
		||||
        size_t received_len;
 | 
			
		||||
        int recv_err = tftp_receive_data(nc, conf.roms[slot], conf.roms[slot]+MAX_IMAGE_SIZE, &received_len);
 | 
			
		||||
        netconn_set_recvtimeout(nc, 10000);
 | 
			
		||||
        int recv_err = tftp_receive_data(nc, conf.roms[slot], conf.roms[slot]+MAX_IMAGE_SIZE, &received_len, NULL, 0, NULL);
 | 
			
		||||
 | 
			
		||||
        netconn_disconnect(nc);
 | 
			
		||||
        printf("OTA TFTP receive data result %d bytes %d\r\n", recv_err, received_len);
 | 
			
		||||
| 
						 | 
				
			
			@ -182,20 +240,48 @@ static char *tftp_get_field(int field, struct netbuf *netbuf)
 | 
			
		|||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static err_t tftp_receive_data(struct netconn *nc, size_t write_offs, size_t limit_offs, size_t *received_len)
 | 
			
		||||
#define TFTP_TIMEOUT_RETRANSMITS 10
 | 
			
		||||
 | 
			
		||||
static err_t tftp_receive_data(struct netconn *nc, size_t write_offs, size_t limit_offs, size_t *received_len, ip_addr_t *peer_addr, int peer_port, tftp_receive_cb receive_cb)
 | 
			
		||||
{
 | 
			
		||||
    *received_len = 0;
 | 
			
		||||
    const int DATA_PACKET_SZ = 512 + 4; /*( packet size plus header */
 | 
			
		||||
    uint32_t start_offs = write_offs;
 | 
			
		||||
    int block = 1;
 | 
			
		||||
 | 
			
		||||
    struct netbuf *netbuf;
 | 
			
		||||
    struct netbuf *netbuf = 0;
 | 
			
		||||
    int retries = TFTP_TIMEOUT_RETRANSMITS;
 | 
			
		||||
 | 
			
		||||
    while(1)
 | 
			
		||||
    {
 | 
			
		||||
        netconn_set_recvtimeout(nc, 10000);
 | 
			
		||||
        if(peer_addr) {
 | 
			
		||||
            netconn_disconnect(nc);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        err_t err = netconn_recv(nc, &netbuf);
 | 
			
		||||
 | 
			
		||||
        if(peer_addr) {
 | 
			
		||||
            if(netbuf) {
 | 
			
		||||
                /* For TFTP server, the UDP connection is already established. But for client,
 | 
			
		||||
                   we don't know what port the server is using until we see the first data
 | 
			
		||||
                   packet - so we connect here.
 | 
			
		||||
                */
 | 
			
		||||
                netconn_connect(nc, netbuf_fromaddr(netbuf), netbuf_fromport(netbuf));
 | 
			
		||||
                peer_addr = 0;
 | 
			
		||||
            } else {
 | 
			
		||||
                /* Otherwise, temporarily re-connect so we can send errors */
 | 
			
		||||
                netconn_connect(nc, peer_addr, peer_port);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(err == ERR_TIMEOUT) {
 | 
			
		||||
            if(retries-- > 0 && block > 1) {
 | 
			
		||||
                /* Retransmit the last ACK, wait for repeat data block.
 | 
			
		||||
 | 
			
		||||
                 This doesn't work for the first block, have to time out and start again. */
 | 
			
		||||
                tftp_send_ack(nc, block-1);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            tftp_send_error(nc, TFTP_ERR_ILLEGAL, "Timeout");
 | 
			
		||||
            return ERR_TIMEOUT;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -225,6 +311,9 @@ static err_t tftp_receive_data(struct netconn *nc, size_t write_offs, size_t lim
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Reset retry count if we got valid data */
 | 
			
		||||
        retries = TFTP_TIMEOUT_RETRANSMITS;
 | 
			
		||||
 | 
			
		||||
        if(write_offs % SECTOR_SIZE == 0) {
 | 
			
		||||
            sdk_spi_flash_erase_sector(write_offs / SECTOR_SIZE);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +370,9 @@ static err_t tftp_receive_data(struct netconn *nc, size_t write_offs, size_t lim
 | 
			
		|||
               it so the client gets an indication if things were successful.
 | 
			
		||||
            */
 | 
			
		||||
            const char *err = "Unknown validation error";
 | 
			
		||||
            if(!rboot_verify_image(start_offs, *received_len, &err)) {
 | 
			
		||||
            uint32_t image_length;
 | 
			
		||||
            if(!rboot_verify_image(start_offs, &image_length, &err)
 | 
			
		||||
               || image_length != *received_len) {
 | 
			
		||||
                tftp_send_error(nc, TFTP_ERR_ILLEGAL, err);
 | 
			
		||||
                return ERR_VAL;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -293,6 +384,11 @@ static err_t tftp_receive_data(struct netconn *nc, size_t write_offs, size_t lim
 | 
			
		|||
            return ack_err;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Make sure ack was successful before calling callback.
 | 
			
		||||
        if(receive_cb) {
 | 
			
		||||
            receive_cb(*received_len);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(len < DATA_PACKET_SZ) {
 | 
			
		||||
            return ERR_OK;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -325,3 +421,17 @@ static void tftp_send_error(struct netconn *nc, int err_code, const char *err_ms
 | 
			
		|||
    netconn_send(nc, err);
 | 
			
		||||
    netbuf_delete(err);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static err_t tftp_send_rrq(struct netconn *nc, const char *filename)
 | 
			
		||||
{
 | 
			
		||||
    struct netbuf *rrqbuf = netbuf_new();
 | 
			
		||||
    uint16_t *rrqdata = (uint16_t *)netbuf_alloc(rrqbuf, 4 + strlen(filename) + strlen(TFTP_OCTET_MODE));
 | 
			
		||||
    rrqdata[0] = htons(TFTP_OP_RRQ);
 | 
			
		||||
    char *rrq_filename = (char *)&rrqdata[1];
 | 
			
		||||
    strcpy(rrq_filename, filename);
 | 
			
		||||
    strcpy(rrq_filename + strlen(filename) + 1, TFTP_OCTET_MODE);
 | 
			
		||||
 | 
			
		||||
    err_t err = netconn_send(nc, rrqbuf);
 | 
			
		||||
    netbuf_delete(rrqbuf);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,10 @@
 | 
			
		|||
#ifndef _OTA_TFTP_H
 | 
			
		||||
#define _OTA_TFTP_H
 | 
			
		||||
 | 
			
		||||
#include "lwip/err.h"
 | 
			
		||||
 | 
			
		||||
typedef void (*tftp_receive_cb)(size_t bytes_received);
 | 
			
		||||
 | 
			
		||||
/* TFTP Server OTA Support
 | 
			
		||||
 *
 | 
			
		||||
 * To use, call ota_tftp_init_server() which will start the TFTP server task
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +35,21 @@
 | 
			
		|||
 */
 | 
			
		||||
void ota_tftp_init_server(int listen_port);
 | 
			
		||||
 | 
			
		||||
/* Attempt to make a TFTP client connection and download the specified filename.
 | 
			
		||||
 | 
			
		||||
   'timeout' is in milliseconds, and is timeout for any UDP exchange
 | 
			
		||||
   _not_ the entire download.
 | 
			
		||||
 | 
			
		||||
   Returns 0 on success, LWIP err.h values for errors.
 | 
			
		||||
 | 
			
		||||
   Does not change the current firmware slot, or reboot.
 | 
			
		||||
 | 
			
		||||
   receive_cb: called repeatedly after each successful packet that
 | 
			
		||||
   has been written to flash and ACKed.  Can pass NULL to omit.
 | 
			
		||||
 */
 | 
			
		||||
err_t ota_tftp_download(const char *server, int port, const char *filename,
 | 
			
		||||
                        int timeout, int ota_slot, tftp_receive_cb receive_cb);
 | 
			
		||||
 | 
			
		||||
#define TFTP_PORT 69
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,9 +4,11 @@
 | 
			
		|||
// richardaburton@gmail.com
 | 
			
		||||
// See license.txt for license terms.
 | 
			
		||||
// OTA code based on SDK sample from Espressif.
 | 
			
		||||
//
 | 
			
		||||
// esp-open-rtos additions Copyright 2016 Angus Gratton
 | 
			
		||||
//////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#include <rboot.h>
 | 
			
		||||
#include <rboot-api.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
//#include <c_types.h>
 | 
			
		||||
//#include <spi_flash.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -209,6 +211,164 @@ bool ICACHE_FLASH_ATTR rboot_get_last_boot_mode(uint8 *mode) {
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* NOTE: Functions below here were added for esp-open-rtos only */
 | 
			
		||||
 | 
			
		||||
uint32_t rboot_get_slot_offset(uint8_t slot) {
 | 
			
		||||
    rboot_config conf;
 | 
			
		||||
    conf = rboot_get_config();
 | 
			
		||||
    if (slot >= conf.count) return (uint32_t)-1;
 | 
			
		||||
    return conf.roms[slot];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Structures for parsing the rboot OTA image format */
 | 
			
		||||
typedef struct __attribute__((packed)) {
 | 
			
		||||
    uint8_t magic;
 | 
			
		||||
    uint8_t section_count;
 | 
			
		||||
    uint8_t val[2]; /* flash size & speed when placed @ offset 0, I thik ignored otherwise */
 | 
			
		||||
    uint32_t entrypoint;
 | 
			
		||||
} image_header_t;
 | 
			
		||||
 | 
			
		||||
typedef struct __attribute__((packed)) {
 | 
			
		||||
    uint32_t load_addr;
 | 
			
		||||
    uint32_t length;
 | 
			
		||||
} section_header_t;
 | 
			
		||||
 | 
			
		||||
#define ROM_MAGIC_OLD 0xe9
 | 
			
		||||
#define ROM_MAGIC_NEW 0xea
 | 
			
		||||
 | 
			
		||||
bool rboot_verify_image(uint32_t initial_offset, uint32_t *image_length, const char **error_message)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t offset = initial_offset;
 | 
			
		||||
    char *error = NULL;
 | 
			
		||||
    RBOOT_DEBUG("rboot_verify_image: verifying image at 0x%08x\n", initial_offset);
 | 
			
		||||
    if(offset % 4) {
 | 
			
		||||
        error = "Unaligned flash offset";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* sanity limit on how far we can read */
 | 
			
		||||
    uint32_t end_limit = offset + 0x100000;
 | 
			
		||||
    image_header_t image_header __attribute__((aligned(4)));
 | 
			
		||||
    if(sdk_spi_flash_read(offset, &image_header, sizeof(image_header_t))) {
 | 
			
		||||
        error = "Flash fail";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    offset += sizeof(image_header_t);
 | 
			
		||||
 | 
			
		||||
    if(image_header.magic != ROM_MAGIC_OLD && image_header.magic != ROM_MAGIC_NEW) {
 | 
			
		||||
        error = "Missing initial magic";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_new_header = (image_header.magic == ROM_MAGIC_NEW); /* a v1.2/rboot header, so expect a v1.1 header after the initial section */
 | 
			
		||||
 | 
			
		||||
    int remaining_sections = image_header.section_count;
 | 
			
		||||
 | 
			
		||||
    uint8_t checksum = CHKSUM_INIT;
 | 
			
		||||
 | 
			
		||||
    while(remaining_sections > 0 && offset < end_limit)
 | 
			
		||||
    {
 | 
			
		||||
        /* read section header */
 | 
			
		||||
        section_header_t header __attribute__((aligned(4)));
 | 
			
		||||
        if(sdk_spi_flash_read(offset, &header, sizeof(section_header_t))) {
 | 
			
		||||
            error = "Flash fail";
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        RBOOT_DEBUG("Found section @ 0x%08x (abs 0x%08x) length %d load 0x%08x\n", offset-initial_offset, offset, header.length, header.load_addr);
 | 
			
		||||
        offset += sizeof(section_header_t);
 | 
			
		||||
 | 
			
		||||
        if(header.length+offset > end_limit) {
 | 
			
		||||
            break; /* sanity check: will reading section take us off end of expected flashregion? */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(header.length % 4) {
 | 
			
		||||
            error = "Header length not modulo 4";
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!is_new_header) {
 | 
			
		||||
            /* Add individual data of the section to the checksum. */
 | 
			
		||||
            char chunk[16] __attribute__((aligned(4)));
 | 
			
		||||
            for(int i = 0; i < header.length; i++) {
 | 
			
		||||
                if(i % sizeof(chunk) == 0)
 | 
			
		||||
                    sdk_spi_flash_read(offset+i, (uint32_t *)chunk, sizeof(chunk));
 | 
			
		||||
                checksum ^= chunk[i % sizeof(chunk)];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        offset += header.length;
 | 
			
		||||
        /* pad section to 4 byte align */
 | 
			
		||||
        offset = (offset+3) & ~3;
 | 
			
		||||
 | 
			
		||||
        remaining_sections--;
 | 
			
		||||
 | 
			
		||||
        if(is_new_header) {
 | 
			
		||||
            /* pad to a 16 byte offset */
 | 
			
		||||
            offset = (offset+15) & ~15;
 | 
			
		||||
 | 
			
		||||
            /* expect a v1.1 header here at start of "real" sections */
 | 
			
		||||
            sdk_spi_flash_read(offset, (uint32_t *)&image_header, sizeof(image_header_t));
 | 
			
		||||
            offset += sizeof(image_header_t);
 | 
			
		||||
            if(image_header.magic != ROM_MAGIC_OLD) {
 | 
			
		||||
                error = "Bad second magic";
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
            remaining_sections = image_header.section_count;
 | 
			
		||||
            is_new_header = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(remaining_sections > 0) {
 | 
			
		||||
        error = "Image truncated";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* add a byte for the image checksum (actually comes after the padding) */
 | 
			
		||||
    offset++;
 | 
			
		||||
    /* pad the image length to a 16 byte boundary */
 | 
			
		||||
    offset = (offset+15) & ~15;
 | 
			
		||||
 | 
			
		||||
    uint32_t read_checksum;
 | 
			
		||||
    sdk_spi_flash_read(offset-1, &read_checksum, 1);
 | 
			
		||||
    if((uint8_t)read_checksum != checksum) {
 | 
			
		||||
        error = "Invalid checksum";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RBOOT_DEBUG("rboot_verify_image: verified expected 0x%08x bytes.\n", offset - initial_offset);
 | 
			
		||||
 | 
			
		||||
    if(image_length)
 | 
			
		||||
        *image_length = offset - initial_offset;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
    if(error_message)
 | 
			
		||||
        *error_message = error;
 | 
			
		||||
    if(error) {
 | 
			
		||||
        printf("%s: %s\n", __func__, error);
 | 
			
		||||
    }
 | 
			
		||||
    if(image_length)
 | 
			
		||||
        *image_length = offset - initial_offset;
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool rboot_digest_image(uint32_t offset, uint32_t image_length, rboot_digest_update_fn update_fn, void *update_ctx)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t buf[32] __attribute__((aligned(4)));
 | 
			
		||||
    for(int i = 0; i < image_length; i += sizeof(buf)) {
 | 
			
		||||
        if(sdk_spi_flash_read(offset+i, buf, sizeof(buf)))
 | 
			
		||||
            return false;
 | 
			
		||||
        uint32_t digest_len = sizeof(buf);
 | 
			
		||||
        if(i + digest_len  > image_length)
 | 
			
		||||
            digest_len = image_length - i;
 | 
			
		||||
        update_fn(update_ctx, buf, digest_len);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
 *  @{
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <rboot-integration.h>
 | 
			
		||||
#include <rboot.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
| 
						 | 
				
			
			@ -128,6 +129,49 @@ bool ICACHE_FLASH_ATTR rboot_get_last_boot_rom(uint8 *rom);
 | 
			
		|||
bool ICACHE_FLASH_ATTR rboot_get_last_boot_mode(uint8 *mode);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* ADDITIONS TO RBOOT-API FOR ESP-OPEN-RTOS FOLLOW */
 | 
			
		||||
 | 
			
		||||
/* Returns offset of given rboot slot, or (uint32_t)-1 if slot is invalid.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t rboot_get_slot_offset(uint8_t slot);
 | 
			
		||||
 | 
			
		||||
/** @description Verify basic image parameters - headers, CRC8 checksum.
 | 
			
		||||
 | 
			
		||||
    @param Offset of image to verify. Can use rboot_get_slot_offset() to find.
 | 
			
		||||
    @param Optional pointer will return the total valid length of the image.
 | 
			
		||||
    @param Optional pointer to a static human-readable error message if fails.
 | 
			
		||||
 | 
			
		||||
    @return True for valid, False for invalid.
 | 
			
		||||
**/
 | 
			
		||||
bool rboot_verify_image(uint32_t offset, uint32_t *image_length, const char **error_message);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* @description Digest callback prototype, designed to be compatible with
 | 
			
		||||
   mbedtls digest functions (SHA, MD5, etc.)
 | 
			
		||||
 | 
			
		||||
   See the ota_basic example to see an example of calculating the
 | 
			
		||||
   SHA256 digest of an OTA image.
 | 
			
		||||
*/
 | 
			
		||||
typedef void (*rboot_digest_update_fn)(void * ctx, void *data, size_t data_len);
 | 
			
		||||
 | 
			
		||||
/** @description Calculate a digest over the image at the offset specified
 | 
			
		||||
 | 
			
		||||
    @note This function is actually a generic function that hashes SPI
 | 
			
		||||
   flash contents, doesn't know anything about rboot image format. Use
 | 
			
		||||
   rboot_verify_image to ensure a well-formed OTA image.
 | 
			
		||||
 | 
			
		||||
   @param offset - Starting offset of image to hash (should be 4 byte aligned.)
 | 
			
		||||
 | 
			
		||||
   @param image_length - Length of image to hash (should be 4 byte aligned.)
 | 
			
		||||
 | 
			
		||||
   @param update_fn - Function to update digest (see rboot_digest_update_fn for details)
 | 
			
		||||
 | 
			
		||||
   @param update_ctx - Context argument for digest update function.
 | 
			
		||||
 | 
			
		||||
   @return True if digest completes successfully, false if digest function failed part way through
 | 
			
		||||
**/
 | 
			
		||||
bool rboot_digest_image(uint32_t offset, uint32_t image_length, rboot_digest_update_fn update_fn, void *update_ctx);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +0,0 @@
 | 
			
		|||
#ifndef _RBOOT_CONFIG_H
 | 
			
		||||
/* rboot configuration parameters.
 | 
			
		||||
 | 
			
		||||
   Must match the config in the compiler bootloader rboot.h. Values below are the rboot.h defaults.
 | 
			
		||||
 | 
			
		||||
   Override rboot parameters by editing this file, or (much better
 | 
			
		||||
   alternative) copy rboot-config.h to your program directory or
 | 
			
		||||
   program/include/ directory, then edit it to override these values.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define RBOOT_MAX_ROMS 4
 | 
			
		||||
//#define RBOOT_CONFIG_CHECKSUM
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,132 +0,0 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <espressif/spi_flash.h>
 | 
			
		||||
#include <espressif/esp_system.h>
 | 
			
		||||
 | 
			
		||||
#include <FreeRTOS.h>
 | 
			
		||||
#include <task.h>
 | 
			
		||||
 | 
			
		||||
#include <rboot.h>
 | 
			
		||||
 | 
			
		||||
#define ROM_MAGIC_OLD 0xe9
 | 
			
		||||
#define ROM_MAGIC_NEW 0xea
 | 
			
		||||
 | 
			
		||||
typedef struct __attribute__((packed)) {
 | 
			
		||||
    uint8_t magic;
 | 
			
		||||
    uint8_t section_count;
 | 
			
		||||
    uint8_t val[2]; /* flash size & speed when placed @ offset 0, I think ignored otherwise */
 | 
			
		||||
    uint32_t entrypoint;
 | 
			
		||||
} image_header_t;
 | 
			
		||||
 | 
			
		||||
typedef struct __attribute__((packed)) {
 | 
			
		||||
    uint32_t load_addr;
 | 
			
		||||
    uint32_t length;
 | 
			
		||||
} section_header_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Check that a valid-looking rboot image is found at this offset on the flash, and
 | 
			
		||||
// takes up 'expected_length' bytes.
 | 
			
		||||
bool rboot_verify_image(uint32_t offset, uint32_t expected_length, const char **error_message)
 | 
			
		||||
{
 | 
			
		||||
    char *error = NULL;
 | 
			
		||||
    if(offset % 4) {
 | 
			
		||||
        error = "Unaligned flash offset";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t end_offset = offset + expected_length;
 | 
			
		||||
    image_header_t image_header;
 | 
			
		||||
    sdk_spi_flash_read(offset, (uint32_t *)&image_header, sizeof(image_header_t));
 | 
			
		||||
    offset += sizeof(image_header_t);
 | 
			
		||||
 | 
			
		||||
    if(image_header.magic != ROM_MAGIC_OLD && image_header.magic != ROM_MAGIC_NEW) {
 | 
			
		||||
        error = "Missing initial magic";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_new_header = (image_header.magic == ROM_MAGIC_NEW); /* a v1.2/rboot header, so expect a v1.1 header after the initial section */
 | 
			
		||||
 | 
			
		||||
    int remaining_sections = image_header.section_count;
 | 
			
		||||
 | 
			
		||||
    uint8_t checksum = CHKSUM_INIT;
 | 
			
		||||
 | 
			
		||||
    while(remaining_sections > 0 && offset < end_offset)
 | 
			
		||||
    {
 | 
			
		||||
        /* read section header */
 | 
			
		||||
        section_header_t header;
 | 
			
		||||
        sdk_spi_flash_read(offset, (uint32_t *)&header, sizeof(section_header_t));
 | 
			
		||||
        RBOOT_DEBUG("Found section @ 0x%08lx length 0x%08lx load 0x%08lx padded 0x%08lx\r\n", offset, header.length, header.load_addr, header.length);
 | 
			
		||||
        offset += sizeof(section_header_t);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if(header.length+offset > end_offset) {
 | 
			
		||||
            break; /* sanity check: will reading section take us off end of expected flashregion? */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!is_new_header) {
 | 
			
		||||
            /* Add individual data of the section to the checksum. */
 | 
			
		||||
            char chunk[16];
 | 
			
		||||
            for(int i = 0; i < header.length; i++) {
 | 
			
		||||
                if(i % sizeof(chunk) == 0)
 | 
			
		||||
                    sdk_spi_flash_read(offset+i, (uint32_t *)chunk, sizeof(chunk));
 | 
			
		||||
                checksum ^= chunk[i % sizeof(chunk)];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        offset += header.length;
 | 
			
		||||
        /* pad section to 4 byte align */
 | 
			
		||||
        offset = (offset+3) & ~3;
 | 
			
		||||
 | 
			
		||||
        remaining_sections--;
 | 
			
		||||
 | 
			
		||||
        if(is_new_header) {
 | 
			
		||||
            /* pad to a 16 byte offset */
 | 
			
		||||
            offset = (offset+15) & ~15;
 | 
			
		||||
 | 
			
		||||
            /* expect a v1.1 header here at start of "real" sections */
 | 
			
		||||
            sdk_spi_flash_read(offset, (uint32_t *)&image_header, sizeof(image_header_t));
 | 
			
		||||
            offset += sizeof(image_header_t);
 | 
			
		||||
            if(image_header.magic != ROM_MAGIC_OLD) {
 | 
			
		||||
                error = "Bad second magic";
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
            remaining_sections = image_header.section_count;
 | 
			
		||||
            is_new_header = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(remaining_sections > 0) {
 | 
			
		||||
        error = "Image truncated";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* add a byte for the image checksum (actually comes after the padding) */
 | 
			
		||||
    offset++;
 | 
			
		||||
    /* pad the image length to a 16 byte boundary */
 | 
			
		||||
    offset = (offset+15) & ~15;
 | 
			
		||||
 | 
			
		||||
    uint8_t read_checksum;
 | 
			
		||||
    sdk_spi_flash_read(offset-1, (uint32_t *)&read_checksum, 1); /* not sure if this will work */
 | 
			
		||||
    if(read_checksum != checksum) {
 | 
			
		||||
        error = "Invalid checksum";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(offset != end_offset) {
 | 
			
		||||
        error = "Wrong length";
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RBOOT_DEBUG("rboot_verify_image: verified expected 0x%08lx bytes.\r\n", expected_length);
 | 
			
		||||
    return true;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
    if(error_message)
 | 
			
		||||
        *error_message = error;
 | 
			
		||||
    printf("%s: %s\r\n", __func__, error);
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +9,10 @@
 | 
			
		|||
#include <FreeRTOS.h>
 | 
			
		||||
#include <task.h>
 | 
			
		||||
 | 
			
		||||
/***************************************************
 | 
			
		||||
 * Platform configuration definitions              *
 | 
			
		||||
 ***************************************************/
 | 
			
		||||
 | 
			
		||||
#define uint8 uint8_t
 | 
			
		||||
#define uint16 uint16_t
 | 
			
		||||
#define uint32 uint32_t
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +32,11 @@
 | 
			
		|||
#define RBOOT_DEBUG(f_, ...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Check that a valid-looking rboot image is found at this offset on the flash, and
 | 
			
		||||
// takes up 'expected_length' bytes.
 | 
			
		||||
bool rboot_verify_image(uint32_t offset, uint32_t expected_length, const char **error_message);
 | 
			
		||||
/* Enable checksumming when writing out the config,
 | 
			
		||||
   so if the bootloader is built with checksumming then
 | 
			
		||||
   it will still work.
 | 
			
		||||
*/
 | 
			
		||||
#define BOOT_CONFIG_CHKSUM
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // __RBOOT_INTEGRATION_H__
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,111 +0,0 @@
 | 
			
		|||
#ifndef __RBOOT_H__
 | 
			
		||||
#define __RBOOT_H__
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////
 | 
			
		||||
// rBoot open source boot loader for ESP8266.
 | 
			
		||||
// Copyright 2015 Richard A Burton
 | 
			
		||||
// richardaburton@gmail.com
 | 
			
		||||
// See license.txt for license terms.
 | 
			
		||||
//////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define RBOOT_INTEGRATION
 | 
			
		||||
 | 
			
		||||
// uncomment to use only c code
 | 
			
		||||
// if you aren't using gcc you may need to do this
 | 
			
		||||
//#define BOOT_NO_ASM
 | 
			
		||||
 | 
			
		||||
// uncomment to have a checksum on the boot config
 | 
			
		||||
//#define BOOT_CONFIG_CHKSUM
 | 
			
		||||
 | 
			
		||||
// uncomment to enable big flash support (>1MB)
 | 
			
		||||
#define BOOT_BIG_FLASH
 | 
			
		||||
 | 
			
		||||
// uncomment to enable 2 way communication between
 | 
			
		||||
// rBoot and the user app via the esp rtc data area
 | 
			
		||||
#define BOOT_RTC_ENABLED
 | 
			
		||||
 | 
			
		||||
// uncomment to enable GPIO booting
 | 
			
		||||
//#define BOOT_GPIO_ENABLED
 | 
			
		||||
 | 
			
		||||
// uncomment to include .irom0.text section in the checksum
 | 
			
		||||
// roms must be built with esptool2 using -iromchksum option
 | 
			
		||||
//#define BOOT_IROM_CHKSUM
 | 
			
		||||
 | 
			
		||||
// uncomment to add a boot delay, allows you time to connect
 | 
			
		||||
// a terminal before rBoot starts to run and output messages
 | 
			
		||||
// value is in microseconds
 | 
			
		||||
//#define BOOT_DELAY_MICROS 2000000
 | 
			
		||||
 | 
			
		||||
// increase if required
 | 
			
		||||
#define MAX_ROMS 4
 | 
			
		||||
 | 
			
		||||
#define CHKSUM_INIT 0xef
 | 
			
		||||
 | 
			
		||||
#define SECTOR_SIZE 0x1000
 | 
			
		||||
#define BOOT_CONFIG_SECTOR 1
 | 
			
		||||
 | 
			
		||||
#define BOOT_CONFIG_MAGIC 0xe1
 | 
			
		||||
#define BOOT_CONFIG_VERSION 0x01
 | 
			
		||||
 | 
			
		||||
#define MODE_STANDARD 0x00
 | 
			
		||||
#define MODE_GPIO_ROM 0x01
 | 
			
		||||
#define MODE_TEMP_ROM 0x02
 | 
			
		||||
 | 
			
		||||
#define RBOOT_RTC_MAGIC 0x2334ae68
 | 
			
		||||
#define RBOOT_RTC_READ 1
 | 
			
		||||
#define RBOOT_RTC_WRITE 0
 | 
			
		||||
#define RBOOT_RTC_ADDR 64
 | 
			
		||||
 | 
			
		||||
#ifdef RBOOT_INTEGRATION
 | 
			
		||||
#include <rboot-integration.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @brief  Structure containing rBoot configuration
 | 
			
		||||
 *  @note   ROM addresses must be multiples of 0x1000 (flash sector aligned).
 | 
			
		||||
 *          Without BOOT_BIG_FLASH only the first 8Mbit (1MB) of the chip will
 | 
			
		||||
 *          be memory mapped so ROM slots containing .irom0.text sections must
 | 
			
		||||
 *          remain below 0x100000. Slots beyond this will only be accessible via
 | 
			
		||||
 *          spi read calls, so use these for stored resources, not code. With
 | 
			
		||||
 *          BOOT_BIG_FLASH the flash will be mapped in chunks of 8MBit (1MB), so
 | 
			
		||||
 *          ROMs can be anywhere, but must not straddle two 8MBit (1MB) blocks.
 | 
			
		||||
 *  @ingroup rboot
 | 
			
		||||
*/
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint8 magic;           ///< Our magic, identifies rBoot configuration - should be BOOT_CONFIG_MAGIC
 | 
			
		||||
	uint8 version;         ///< Version of configuration structure - should be BOOT_CONFIG_VERSION
 | 
			
		||||
	uint8 mode;            ///< Boot loader mode (MODE_STANDARD | MODE_GPIO_ROM)
 | 
			
		||||
	uint8 current_rom;     ///< Currently selected ROM (will be used for next standard boot)
 | 
			
		||||
	uint8 gpio_rom;        ///< ROM to use for GPIO boot (hardware switch) with mode set to MODE_GPIO_ROM
 | 
			
		||||
	uint8 count;           ///< Quantity of ROMs available to boot
 | 
			
		||||
	uint8 unused[2];       ///< Padding (not used)
 | 
			
		||||
	uint32 roms[MAX_ROMS]; ///< Flash addresses of each ROM
 | 
			
		||||
#ifdef BOOT_CONFIG_CHKSUM
 | 
			
		||||
	uint8 chksum;          ///< Checksum of this configuration structure (if BOOT_CONFIG_CHKSUM defined)
 | 
			
		||||
#endif
 | 
			
		||||
} rboot_config;
 | 
			
		||||
 | 
			
		||||
#ifdef BOOT_RTC_ENABLED
 | 
			
		||||
/** @brief  Structure containing rBoot status/control data
 | 
			
		||||
 *  @note   This structure is used to, optionally, communicate between rBoot and
 | 
			
		||||
 *          the user app. It is stored in the ESP RTC data area.
 | 
			
		||||
 *  @ingroup rboot
 | 
			
		||||
*/
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint32 magic;           ///< Magic, identifies rBoot RTC data - should be RBOOT_RTC_MAGIC
 | 
			
		||||
	uint8 next_mode;        ///< The next boot mode, defaults to MODE_STANDARD - can be set to MODE_TEMP_ROM
 | 
			
		||||
	uint8 last_mode;        ///< The last (this) boot mode - can be MODE_STANDARD, MODE_GPIO_ROM or MODE_TEMP_ROM
 | 
			
		||||
	uint8 last_rom;         ///< The last (this) boot rom number
 | 
			
		||||
	uint8 temp_rom;         ///< The next boot rom number when next_mode set to MODE_TEMP_ROM
 | 
			
		||||
	uint8 chksum;           ///< Checksum of this structure this will be updated for you passed to the API
 | 
			
		||||
} rboot_rtc_data;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ sdk_SpiFlashOpResult sdk_spi_flash_erase_sector(uint16_t sec);
 | 
			
		|||
/* Write data to flash.
 | 
			
		||||
 | 
			
		||||
   des_addr is byte offset to write to. Should be 4-byte aligned.
 | 
			
		||||
   src is pointer to a buffer to read bytes from.
 | 
			
		||||
   src is pointer to a buffer to read bytes from. Should be 4-byte aligned.
 | 
			
		||||
   size is length of buffer in bytes. Should be a multiple of 4.
 | 
			
		||||
*/
 | 
			
		||||
sdk_SpiFlashOpResult sdk_spi_flash_write(uint32_t des_addr, const void *src, uint32_t size);
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ sdk_SpiFlashOpResult sdk_spi_flash_write(uint32_t des_addr, const void *src, uin
 | 
			
		|||
/* Read data from flash.
 | 
			
		||||
 | 
			
		||||
   src_addr is byte offset to read from. Should be 4-byte aligned.
 | 
			
		||||
   des is pointer to a buffer to read bytes into.
 | 
			
		||||
   des is pointer to a buffer to read bytes into. Should be 4-byte aligned.
 | 
			
		||||
   size is number of bytes to read. Should be a multiple of 4.
 | 
			
		||||
*/
 | 
			
		||||
sdk_SpiFlashOpResult sdk_spi_flash_read(uint32_t src_addr, void *des, uint32_t size);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								ld/nonota.ld
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								ld/nonota.ld
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
/* Memory layout for esp-open-rtos when not using OTA
 | 
			
		||||
   (ie ROM bootloader only, no second stage rboot)
 | 
			
		||||
 */
 | 
			
		||||
MEMORY
 | 
			
		||||
{
 | 
			
		||||
  dport0_0_seg :                      	org = 0x3FF00000, len = 0x10
 | 
			
		||||
  dram0_0_seg :                       	org = 0x3FFE8000, len = 0x14000
 | 
			
		||||
  iram1_0_seg :                       	org = 0x40100000, len = 0x08000
 | 
			
		||||
/* irom0 section, mapped from SPI flash
 | 
			
		||||
  - Origin is offset by 0x20000 to leave space for bootloader RAM sections.
 | 
			
		||||
 | 
			
		||||
  - Length is max 8Mbit of mappable flash, minus start offset
 | 
			
		||||
*/
 | 
			
		||||
  irom0_0_seg :                       	org = 0x40220000, len = (1M - 0x20000)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								ld/ota.ld
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								ld/ota.ld
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
/* Memory layout for esp-open-rtos when using OTA second stage bootloader */
 | 
			
		||||
 | 
			
		||||
MEMORY
 | 
			
		||||
{
 | 
			
		||||
  dport0_0_seg :                      	org = 0x3FF00000, len = 0x10
 | 
			
		||||
  dram0_0_seg :                       	org = 0x3FFE8000, len = 0x14000
 | 
			
		||||
  iram1_0_seg :                       	org = 0x40100000, len = 0x08000
 | 
			
		||||
/* irom0 section, mapped from SPI flash
 | 
			
		||||
  - Origin is offset by 0x2010 to create spacer for second stage bootloader image,
 | 
			
		||||
    header.
 | 
			
		||||
 | 
			
		||||
  - Length is max 8Mbit of mappable flash, minus start offset
 | 
			
		||||
*/
 | 
			
		||||
  irom0_0_seg :                       	org = 0x40202010, len = (1M - 0x2010)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,17 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Common (OTA and non-OTA) parts for the esp-open-rtos Linker Script
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
/* Memory layout for esp-open-rtos when using OTA second stage bootloader */
 | 
			
		||||
MEMORY
 | 
			
		||||
{
 | 
			
		||||
  dport0_0_seg :                      	org = 0x3FF00000, len = 0x10
 | 
			
		||||
  dram0_0_seg :                       	org = 0x3FFE8000, len = 0x14000
 | 
			
		||||
  iram1_0_seg :                       	org = 0x40100000, len = 0x08000
 | 
			
		||||
/* irom0 section, mapped from SPI flash
 | 
			
		||||
  - Origin is offset by 0x2010 to create spacer for second stage bootloader image,
 | 
			
		||||
    header.
 | 
			
		||||
 | 
			
		||||
  - Length is max 8Mbit of mappable flash, minus start offset
 | 
			
		||||
*/
 | 
			
		||||
  irom0_0_seg :                       	org = 0x40202010, len = (1M - 0x2010)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS memory management functions
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										141
									
								
								parameters.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								parameters.mk
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,141 @@
 | 
			
		|||
# Parameters for the esp-open-rtos make process
 | 
			
		||||
#
 | 
			
		||||
# You can edit this file to change parameters, but a better option is
 | 
			
		||||
# to create a local.mk file and add overrides there. The local.mk file
 | 
			
		||||
# can be in the root directory, or the program directory alongside the
 | 
			
		||||
# Makefile, or both.
 | 
			
		||||
#
 | 
			
		||||
-include $(ROOT)local.mk
 | 
			
		||||
-include local.mk
 | 
			
		||||
 | 
			
		||||
# Flash size in megabits
 | 
			
		||||
# Valid values are same as for esptool.py - 2,4,8,16,32
 | 
			
		||||
FLASH_SIZE ?= 16
 | 
			
		||||
 | 
			
		||||
# Flash mode, valid values are same as for esptool.py - qio,qout,dio.dout
 | 
			
		||||
FLASH_MODE ?= qio
 | 
			
		||||
 | 
			
		||||
# Flash speed in MHz, valid values are same as for esptool.py - 80, 40, 26, 20
 | 
			
		||||
FLASH_SPEED ?= 40
 | 
			
		||||
 | 
			
		||||
# Output directories to store intermediate compiled files
 | 
			
		||||
# relative to the program directory
 | 
			
		||||
BUILD_DIR ?= $(PROGRAM_DIR)build/
 | 
			
		||||
FIRMWARE_DIR ?= $(PROGRAM_DIR)firmware/
 | 
			
		||||
 | 
			
		||||
# esptool.py from https://github.com/themadinventor/esptool
 | 
			
		||||
ESPTOOL ?= esptool.py
 | 
			
		||||
# serial port settings for esptool.py
 | 
			
		||||
ESPPORT ?= /dev/ttyUSB0
 | 
			
		||||
ESPBAUD ?= 115200
 | 
			
		||||
 | 
			
		||||
# firmware tool arguments
 | 
			
		||||
ESPTOOL_ARGS=-fs $(FLASH_SIZE)m -fm $(FLASH_MODE) -ff $(FLASH_SPEED)m
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# set this to 0 if you don't need floating point support in printf/scanf
 | 
			
		||||
# this will save approx 14.5KB flash space and 448 bytes of statically allocated
 | 
			
		||||
# data RAM
 | 
			
		||||
#
 | 
			
		||||
# NB: Setting the value to 0 requires a recent esptool.py (Feb 2016 / commit ebf02c9)
 | 
			
		||||
PRINTF_SCANF_FLOAT_SUPPORT ?= 1
 | 
			
		||||
 | 
			
		||||
FLAVOR ?= release # or debug
 | 
			
		||||
 | 
			
		||||
# Compiler names, etc. assume gdb
 | 
			
		||||
CROSS ?= xtensa-lx106-elf-
 | 
			
		||||
 | 
			
		||||
# Path to the filteroutput.py tool
 | 
			
		||||
FILTEROUTPUT ?= $(ROOT)/utils/filteroutput.py
 | 
			
		||||
 | 
			
		||||
AR = $(CROSS)ar
 | 
			
		||||
CC = $(CROSS)gcc
 | 
			
		||||
CPP = $(CROSS)cpp
 | 
			
		||||
LD = $(CROSS)gcc
 | 
			
		||||
NM = $(CROSS)nm
 | 
			
		||||
C++ = $(CROSS)g++
 | 
			
		||||
SIZE = $(CROSS)size
 | 
			
		||||
OBJCOPY = $(CROSS)objcopy
 | 
			
		||||
OBJDUMP = $(CROSS)objdump
 | 
			
		||||
 | 
			
		||||
# Source components to compile and link. Each of these are subdirectories
 | 
			
		||||
# of the root, with a 'component.mk' file.
 | 
			
		||||
COMPONENTS     ?= $(EXTRA_COMPONENTS) FreeRTOS lwip core
 | 
			
		||||
 | 
			
		||||
# binary esp-iot-rtos SDK libraries to link. These are pre-processed prior to linking.
 | 
			
		||||
SDK_LIBS		?= main net80211 phy pp wpa
 | 
			
		||||
 | 
			
		||||
# open source libraries linked in
 | 
			
		||||
LIBS ?= hal gcc c
 | 
			
		||||
 | 
			
		||||
# set to 0 if you want to use the toolchain libc instead of esp-open-rtos newlib
 | 
			
		||||
OWN_LIBC ?= 1
 | 
			
		||||
 | 
			
		||||
# Note: you will need a recent esp
 | 
			
		||||
ENTRY_SYMBOL ?= call_user_start
 | 
			
		||||
 | 
			
		||||
# Set this to zero if you don't want individual function & data sections
 | 
			
		||||
# (some code may be slightly slower, linking will be slighty slower,
 | 
			
		||||
# but compiled code size will come down a small amount.)
 | 
			
		||||
SPLIT_SECTIONS ?= 1
 | 
			
		||||
 | 
			
		||||
# Set this to 1 to have all compiler warnings treated as errors (and stop the
 | 
			
		||||
# build).  This is recommended whenever you are working on code which will be
 | 
			
		||||
# submitted back to the main project, as all submitted code will be expected to
 | 
			
		||||
# compile without warnings to be accepted.
 | 
			
		||||
WARNINGS_AS_ERRORS ?= 0
 | 
			
		||||
 | 
			
		||||
# Common flags for both C & C++_
 | 
			
		||||
C_CXX_FLAGS ?= -Wall -Wl,-EL -nostdlib $(EXTRA_C_CXX_FLAGS)
 | 
			
		||||
# Flags for C only
 | 
			
		||||
CFLAGS		?= $(C_CXX_FLAGS) -std=gnu99 $(EXTRA_CFLAGS)
 | 
			
		||||
# Flags for C++ only
 | 
			
		||||
CXXFLAGS	?= $(C_CXX_FLAGS) -fno-exceptions -fno-rtti $(EXTRA_CXXFLAGS)
 | 
			
		||||
 | 
			
		||||
# these aren't all technically preprocesor args, but used by all 3 of C, C++, assembler
 | 
			
		||||
CPPFLAGS	+= -mlongcalls -mtext-section-literals
 | 
			
		||||
 | 
			
		||||
LDFLAGS		= -nostdlib -Wl,--no-check-sections -L$(BUILD_DIR)sdklib -L$(ROOT)lib -u $(ENTRY_SYMBOL) -Wl,-static -Wl,-Map=$(BUILD_DIR)$(PROGRAM).map $(EXTRA_LDFLAGS)
 | 
			
		||||
 | 
			
		||||
ifeq ($(WARNINGS_AS_ERRORS),1)
 | 
			
		||||
    C_CXX_FLAGS += -Werror
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(SPLIT_SECTIONS),1)
 | 
			
		||||
  C_CXX_FLAGS += -ffunction-sections -fdata-sections
 | 
			
		||||
  LDFLAGS += -Wl,-gc-sections
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(FLAVOR),debug)
 | 
			
		||||
    C_CXX_FLAGS += -g -O0
 | 
			
		||||
    LDFLAGS += -g -O0
 | 
			
		||||
else ifeq ($(FLAVOR),sdklike)
 | 
			
		||||
    # These are flags intended to produce object code as similar as possible to
 | 
			
		||||
    # the output of the compiler used to build the SDK libs (for comparison of
 | 
			
		||||
    # disassemblies when coding replacement routines).  It is not normally
 | 
			
		||||
    # intended to be used otherwise.
 | 
			
		||||
    CFLAGS += -O2 -Os -fno-inline -fno-ipa-cp -fno-toplevel-reorder
 | 
			
		||||
    LDFLAGS += -O2
 | 
			
		||||
else
 | 
			
		||||
    C_CXX_FLAGS += -g -O2
 | 
			
		||||
    LDFLAGS += -g -O2
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
GITSHORTREV=\"$(shell cd $(ROOT); git rev-parse --short -q HEAD 2> /dev/null)\"
 | 
			
		||||
ifeq ($(GITSHORTREV),\"\")
 | 
			
		||||
  GITSHORTREV="\"(nogit)\"" # (same length as a short git hash)
 | 
			
		||||
endif
 | 
			
		||||
CPPFLAGS += -DGITSHORTREV=$(GITSHORTREV)
 | 
			
		||||
 | 
			
		||||
LINKER_SCRIPTS += $(ROOT)ld/program.ld $(ROOT)ld/rom.ld
 | 
			
		||||
 | 
			
		||||
# rboot firmware binary paths for flashing
 | 
			
		||||
RBOOT_BIN = $(ROOT)bootloader/firmware/rboot.bin
 | 
			
		||||
RBOOT_PREBUILT_BIN = $(ROOT)bootloader/firmware_prebuilt/rboot.bin
 | 
			
		||||
RBOOT_CONF = $(ROOT)bootloader/firmware_prebuilt/blank_config.bin
 | 
			
		||||
 | 
			
		||||
# if a custom bootloader hasn't been compiled, use the
 | 
			
		||||
# prebuilt binary from the source tree
 | 
			
		||||
ifeq (,$(wildcard $(RBOOT_BIN)))
 | 
			
		||||
RBOOT_BIN=$(RBOOT_PREBUILT_BIN)
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
#!/bin/bash
 | 
			
		||||
set -uv
 | 
			
		||||
 | 
			
		||||
# Called by Travis to install esptool2 to generate OTA-compatible build
 | 
			
		||||
# images
 | 
			
		||||
 | 
			
		||||
if test -f ${ESPTOOL2_DIR}/esptool2; then
 | 
			
		||||
	echo "Using cached esptool2"
 | 
			
		||||
	exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
git clone https://github.com/raburton/esptool2 ${ESPTOOL2_DIR}
 | 
			
		||||
cd ${ESPTOOL2_DIR}
 | 
			
		||||
git reset --hard ${ESPTOOL2_COMMIT}
 | 
			
		||||
make
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue