diff --git a/components/app_update/Makefile.projbuild b/components/app_update/Makefile.projbuild new file mode 100644 index 0000000000..29d223dc5e --- /dev/null +++ b/components/app_update/Makefile.projbuild @@ -0,0 +1,27 @@ +# +# Generate partition binary +# +.PHONY: erase_ota blank_ota_data + +GEN_EMPTY_PART := $(PYTHON) $(COMPONENT_PATH)/gen_empty_partition.py +BLANK_OTA_DATA_FILE = $(BUILD_DIR_BASE)/ota_data_initial.bin + +# If there is no otadata partition, both OTA_DATA_OFFSET and BLANK_OTA_DATA_FILE +# expand to empty values. +ESPTOOL_ALL_FLASH_ARGS += $(OTA_DATA_OFFSET) $(BLANK_OTA_DATA_FILE) + +$(BLANK_OTA_DATA_FILE): partition_table_get_info + $(GEN_EMPTY_PART) --size $(OTA_DATA_SIZE) $(BLANK_OTA_DATA_FILE) + $(eval BLANK_OTA_DATA_FILE = $(shell if [ $(OTA_DATA_SIZE) != 0 ]; then echo $(BLANK_OTA_DATA_FILE); else echo " "; fi) ) + +blank_ota_data: $(BLANK_OTA_DATA_FILE) + +erase_ota: partition_table_get_info + @echo $(if $(OTA_DATA_OFFSET), "Erase ota_data [addr=$(OTA_DATA_OFFSET) size=$(OTA_DATA_SIZE)] ...", $(error "ERROR: Partition table does not have ota_data partition.")) + $(ESPTOOLPY_SERIAL) erase_region $(OTA_DATA_OFFSET) $(OTA_DATA_SIZE) + +all: blank_ota_data +flash: blank_ota_data + +clean: + rm -f $(BLANK_OTA_DATA_FILE) diff --git a/components/app_update/gen_empty_partition.py b/components/app_update/gen_empty_partition.py new file mode 100755 index 0000000000..f51df22403 --- /dev/null +++ b/components/app_update/gen_empty_partition.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# generates an empty binary file +# +# This tool generates an empty binary file of the required size. +# +# Copyright 2018 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import print_function, division +import argparse +import os +import re +import struct +import sys +import hashlib +import binascii + +__version__ = '1.0' + +quiet = False + +def status(msg): + """ Print status message to stderr """ + if not quiet: + critical(msg) + +def critical(msg): + """ Print critical message to stderr """ + if not quiet: + sys.stderr.write(msg) + sys.stderr.write('\n') + +def generate_blanked_file(size, output_path): + output = "" + for i in range(size): + output += b"\xFF" + try: + stdout_binary = sys.stdout.buffer # Python 3 + except AttributeError: + stdout_binary = sys.stdout + with stdout_binary if output_path == '-' else open(output_path, 'wb') as f: + f.write(output) + +def main(): + global quiet + parser = argparse.ArgumentParser(description='Generates an empty binary file of the required size.') + + parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') + + parser.add_argument('--size', help='Size of generated the file', type=str, required=True) + + parser.add_argument('output', help='Path for binary file.', nargs='?', default='-') + args = parser.parse_args() + + quiet = args.quiet + + size = int(args.size, 0) + if size > 0 : + generate_blanked_file(size, args.output) + return 0 + +class InputError(RuntimeError): + def __init__(self, e): + super(InputError, self).__init__(e) + +if __name__ == '__main__': + try: + r = main() + sys.exit(r) + except InputError as e: + print(e, file=sys.stderr) + sys.exit(2) diff --git a/components/partition_table/Makefile.projbuild b/components/partition_table/Makefile.projbuild index 4973201f38..b534196206 100644 --- a/components/partition_table/Makefile.projbuild +++ b/components/partition_table/Makefile.projbuild @@ -65,9 +65,13 @@ all_binaries: $(PARTITION_TABLE_BIN) partition_table_get_info partition_table_get_info: $(PARTITION_TABLE_BIN) $(eval PHY_DATA_OFFSET:=$(shell $(GET_PART_INFO) --type data --subtype phy --offset $(PARTITION_TABLE_BIN))) $(eval APP_OFFSET:=$(shell $(GET_PART_INFO) --default-boot-partition --offset $(PARTITION_TABLE_BIN))) + $(eval OTA_DATA_SIZE := $(shell $(GET_PART_INFO) --type data --subtype ota --size $(PARTITION_TABLE_BIN) || echo 0) ) + $(eval OTA_DATA_OFFSET := $(shell $(GET_PART_INFO) --type data --subtype ota --offset $(PARTITION_TABLE_BIN)) ) export APP_OFFSET export PHY_DATA_OFFSET +export OTA_DATA_OFFSET +export OTA_DATA_SIZE PARTITION_TABLE_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_BIN) ESPTOOL_ALL_FLASH_ARGS += $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_BIN) diff --git a/docs/en/get-started/make-project.rst b/docs/en/get-started/make-project.rst index 956b097d04..8f27c89272 100644 --- a/docs/en/get-started/make-project.rst +++ b/docs/en/get-started/make-project.rst @@ -36,7 +36,9 @@ When ``make all`` finishes, it will print a command line to use esptool.py to fl make flash -This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `make menuconfig`. +This will flash the entire project (app, bootloader and partition table) to a new chip. Also if partition table has ota_data then this command will flash a initial ota_data. +It allows to run the newly loaded app from a factory partition (or the first OTA partition, if factory partition is not present). +The settings for serial port flashing can be configured with `make menuconfig`. You don't need to run ``make all`` before running ``make flash``, ``make flash`` will automatically rebuild anything which needs it. diff --git a/examples/system/ota/README.md b/examples/system/ota/README.md index 2b0e0202b0..316789dbcc 100644 --- a/examples/system/ota/README.md +++ b/examples/system/ota/README.md @@ -63,13 +63,15 @@ Save your changes, and type `make` to build the example. ## Step 4: Flash OTA Example -When flashing, use the `erase_flash` target first to erase the entire flash (this deletes any leftover data in the ota_data partition). Then flash the factory image over serial: +When flashing, use the `make flash` to flash the factory image. This command will find if partition table has ota_data partition (as in our case) then ota_data will erase to initial. +It allows to run the newly loaded app from a factory partition. ``` -make erase_flash flash +make flash ``` -(The `make erase_flash flash` means "erase everything, then flash". `make flash` only erases the parts of flash which are being rewritten.) +After first update, if you want to return back to factory app (or the first OTA partition, if factory partition is not present) then use the command `make erase_ota`. +It erases ota_data partition to initial. ## Step 5: Run the OTA Example diff --git a/make/project.mk b/make/project.mk index 5a27cb776f..a5fea2f52c 100644 --- a/make/project.mk +++ b/make/project.mk @@ -34,6 +34,7 @@ help: @echo "make size-components, size-files - Finer-grained memory footprints" @echo "make size-symbols - Per symbol memory footprint. Requires COMPONENT=" @echo "make erase_flash - Erase entire flash contents" + @echo "make erase_ota - Erase ota_data partition. After that will boot first bootable partition (factory or OTAx)." @echo "make monitor - Run idf_monitor tool to monitor serial output from app" @echo "make simple_monitor - Monitor serial output on terminal console" @echo "make list-components - List all components in the project" @@ -547,7 +548,7 @@ list-components: $(foreach cp,$(COMPONENT_PATHS),$(info $(cp))) # print flash command, so users can dump this to config files and download somewhere without idf -print_flash_cmd: partition_table_get_info +print_flash_cmd: partition_table_get_info blank_ota_data echo $(ESPTOOL_WRITE_FLASH_OPTIONS) $(ESPTOOL_ALL_FLASH_ARGS) | sed -e 's:'$(PWD)/build/'::g' # Check toolchain version using the output of xtensa-esp32-elf-gcc --version command. diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index f576153b1f..2626fc0741 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -5,6 +5,7 @@ components/heap/test_multi_heap_host/test_all_configs.sh components/idf_test/unit_test/TestCaseScript/IDFUnitTest/__init__.py components/partition_table/gen_esp32part.py components/partition_table/parttool.py +components/app_update/gen_empty_partition.py components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py components/ulp/esp32ulp_mapgen.py components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py diff --git a/tools/unit-test-app/Makefile b/tools/unit-test-app/Makefile index 272fbe8265..006bf9753e 100644 --- a/tools/unit-test-app/Makefile +++ b/tools/unit-test-app/Makefile @@ -92,7 +92,7 @@ $(BINARIES_DIR)/%/$(PROJECT_NAME).bin: configs/% cp $(BUILDS_DIR)/$*/$(PROJECT_NAME).elf $(BINARIES_DIR)/$*/ cp $(BUILDS_DIR)/$*/$(PROJECT_NAME).bin $(BINARIES_DIR)/$*/ cp $(BUILDS_DIR)/$*/$(PROJECT_NAME).map $(BINARIES_DIR)/$*/ - cp $(BUILDS_DIR)/$*/partition_table*.bin $(BINARIES_DIR)/$*/ + cp $(BUILDS_DIR)/$*/*.bin $(BINARIES_DIR)/$*/ cp $(BUILDS_DIR)/$*/sdkconfig $(BINARIES_DIR)/$*/