Merge branch 'master' into feature/esp32s2beta_update

This commit is contained in:
Angus Gratton
2019-08-08 13:44:24 +10:00
committed by Angus Gratton
2414 changed files with 160787 additions and 45783 deletions

View File

@@ -1,15 +1,11 @@
set(COMPONENT_SRCS "esp_ota_ops.c"
"esp_app_desc.c")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_REQUIRES spi_flash partition_table bootloader_support)
set(COMPONENT_PRIV_REQUIRES)
register_component()
idf_component_register(SRCS "esp_ota_ops.c"
"esp_app_desc.c"
INCLUDE_DIRS "include"
REQUIRES spi_flash partition_table bootloader_support)
# esp_app_desc structure is added as an undefined symbol because otherwise the
# linker will ignore this structure as it has no other files depending on it.
target_link_libraries(${COMPONENT_LIB} "-u esp_app_desc")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_app_desc")
# cut PROJECT_VER and PROJECT_NAME to required 32 characters.
idf_build_get_property(project_ver PROJECT_VER)
@@ -34,21 +30,27 @@ if(NOT BOOTLOADER_BUILD)
idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(python PYTHON)
add_custom_command(OUTPUT ${blank_otadata_file}
COMMAND ${python} ${idf_path}/components/partition_table/parttool.py
--partition-type data --partition-subtype ota -q
--partition-table-file ${PARTITION_CSV_PATH} generate_blank_partition_file
--output ${blank_otadata_file})
COMMAND ${python} ${idf_path}/components/partition_table/gen_empty_partition.py
${otadata_size} ${blank_otadata_file})
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
add_dependencies(app blank_ota_data)
add_dependencies(flash blank_ota_data)
set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py)
set(esptool_args --esptool-args before=${CONFIG_ESPTOOLPY_BEFORE} after=${CONFIG_ESPTOOLPY_AFTER})
add_custom_target(read_otadata DEPENDS "${PARTITION_CSV_PATH}"
COMMAND ${otatool_py} --partition-table-file ${PARTITION_CSV_PATH} read_otadata)
COMMAND ${otatool_py} ${esptool_args}
--partition-table-file ${PARTITION_CSV_PATH}
--partition-table-offset ${PARTITION_TABLE_OFFSET}
read_otadata)
add_custom_target(erase_otadata DEPENDS "${PARTITION_CSV_PATH}"
COMMAND ${otatool_py} --partition-table-file ${PARTITION_CSV_PATH} erase_otadata)
COMMAND ${otatool_py} ${esptool_args}
--partition-table-file ${PARTITION_CSV_PATH}
--partition-table-offset ${PARTITION_TABLE_OFFSET}
erase_otadata)
esptool_py_flash_project_args(otadata ${otadata_offset} "${blank_otadata_file}" FLASH_IN_PROJECT)
endif()

View File

@@ -17,8 +17,7 @@ endif
$(BLANK_OTA_DATA_FILE): partition_table_get_info $(PARTITION_TABLE_CSV_PATH) | check_python_dependencies
$(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
$(PARTTOOL_PY) --partition-type data --partition-subtype ota --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
-q generate_blank_partition_file --output $(BLANK_OTA_DATA_FILE); \
$(PYTHON) $(IDF_PATH)/components/partition_table/gen_empty_partition.py $(OTA_DATA_SIZE) $(BLANK_OTA_DATA_FILE); \
fi; )
$(eval BLANK_OTA_DATA_FILE = $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
echo $(BLANK_OTA_DATA_FILE); else echo " "; fi) )
@@ -29,17 +28,26 @@ blank_ota_data: $(BLANK_OTA_DATA_FILE)
# expand to empty values.
ESPTOOL_ALL_FLASH_ARGS += $(OTA_DATA_OFFSET) $(BLANK_OTA_DATA_FILE)
ESPTOOL_ARGS := --esptool-args port=$(CONFIG_ESPTOOLPY_PORT) baud=$(CONFIG_ESPTOOLPY_BAUD) before=$(CONFIG_ESPTOOLPY_BEFORE) after=$(CONFIG_ESPTOOLPY_AFTER)
erase_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
$(OTATOOL_PY) --partition-table-file $(PARTITION_TABLE_CSV_PATH) erase_otadata
$(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
--partition-table-offset $(PARTITION_TABLE_OFFSET) \
erase_otadata
read_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
$(OTATOOL_PY) --partition-table-file $(PARTITION_TABLE_CSV_PATH) read_otadata
$(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
--partition-table-offset $(partition_table_offset) \
read_otadata
erase_ota: erase_otadata
@echo "WARNING: erase_ota is deprecated. Use erase_otadata instead."
all: blank_ota_data
flash: blank_ota_data
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
encrypted-flash: blank_ota_data
endif
TMP_DEFINES := $(BUILD_DIR_BASE)/app_update/tmp_cppflags.txt
export TMP_DEFINES

View File

@@ -21,16 +21,20 @@ import argparse
import os
import sys
import binascii
import subprocess
import tempfile
import collections
import struct
__version__ = '1.0'
try:
from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET
except ImportError:
COMPONENTS_PATH = os.path.expandvars(os.path.join("$IDF_PATH", "components"))
PARTTOOL_DIR = os.path.join(COMPONENTS_PATH, "partition_table")
IDF_COMPONENTS_PATH = os.path.expandvars(os.path.join("$IDF_PATH", "components"))
sys.path.append(PARTTOOL_DIR)
from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET
PARTTOOL_PY = os.path.join(IDF_COMPONENTS_PATH, "partition_table", "parttool.py")
__version__ = '2.0'
SPI_FLASH_SEC_SIZE = 0x2000
@@ -42,121 +46,72 @@ def status(msg):
print(msg)
def _invoke_parttool(parttool_args, args, output=False, partition=None):
invoke_args = []
class OtatoolTarget():
if partition:
invoke_args += [sys.executable, PARTTOOL_PY] + partition
else:
invoke_args += [sys.executable, PARTTOOL_PY, "--partition-type", "data", "--partition-subtype", "ota"]
OTADATA_PARTITION = PartitionType("data", "ota")
if quiet:
invoke_args += ["-q"]
def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, partition_table_file=None,
spi_flash_sec_size=SPI_FLASH_SEC_SIZE, esptool_args=[], esptool_write_args=[],
esptool_read_args=[], esptool_erase_args=[]):
self.target = ParttoolTarget(port, baud, partition_table_offset, partition_table_file, esptool_args,
esptool_write_args, esptool_read_args, esptool_erase_args)
self.spi_flash_sec_size = spi_flash_sec_size
if args.port != "":
invoke_args += ["--port", args.port]
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.close()
try:
self.target.read_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name)
with open(temp_file.name, "rb") as f:
self.otadata = f.read()
except Exception:
self.otadata = None
finally:
os.unlink(temp_file.name)
if args.partition_table_file:
invoke_args += ["--partition-table-file", args.partition_table_file]
def _check_otadata_partition(self):
if not self.otadata:
raise Exception("No otadata partition found")
if args.partition_table_offset:
invoke_args += ["--partition-table-offset", args.partition_table_offset]
def erase_otadata(self):
self._check_otadata_partition()
self.target.erase_partition(OtatoolTarget.OTADATA_PARTITION)
invoke_args += parttool_args
def _get_otadata_info(self):
info = []
if output:
return subprocess.check_output(invoke_args)
else:
return subprocess.check_call(invoke_args)
otadata_info = collections.namedtuple("otadata_info", "seq crc")
for i in range(2):
start = i * (self.spi_flash_sec_size >> 1)
def _get_otadata_contents(args, check=True):
global quiet
seq = bytearray(self.otadata[start:start + 4])
crc = bytearray(self.otadata[start + 28:start + 32])
if check:
check_args = ["get_partition_info", "--info", "offset", "size"]
seq = struct.unpack('>I', seq)
crc = struct.unpack('>I', crc)
quiet = True
output = _invoke_parttool(check_args, args, True).split(b" ")
quiet = args.quiet
info.append(otadata_info(seq[0], crc[0]))
if not output:
raise RuntimeError("No ota_data partition found")
return info
with tempfile.NamedTemporaryFile(delete=False) as f:
f_name = f.name
def _get_partition_id_from_ota_id(self, ota_id):
if isinstance(ota_id, int):
return PartitionType("app", "ota_" + str(ota_id))
else:
return PartitionName(ota_id)
try:
invoke_args = ["read_partition", "--output", f_name]
_invoke_parttool(invoke_args, args)
with open(f_name, "rb") as f:
contents = f.read()
finally:
os.unlink(f_name)
def switch_ota_partition(self, ota_id):
self._check_otadata_partition()
return contents
sys.path.append(PARTTOOL_DIR)
import gen_esp32part as gen
def _get_otadata_status(otadata_contents):
status = []
otadata_status = collections.namedtuple("otadata_status", "seq crc")
for i in range(2):
start = i * (SPI_FLASH_SEC_SIZE >> 1)
seq = bytearray(otadata_contents[start:start + 4])
crc = bytearray(otadata_contents[start + 28:start + 32])
seq = struct.unpack('>I', seq)
crc = struct.unpack('>I', crc)
status.append(otadata_status(seq[0], crc[0]))
return status
def read_otadata(args):
status("Reading ota_data partition contents...")
otadata_info = _get_otadata_contents(args)
otadata_info = _get_otadata_status(otadata_info)
print(otadata_info)
print("\t\t{:11}\t{:8s}|\t{:8s}\t{:8s}".format("OTA_SEQ", "CRC", "OTA_SEQ", "CRC"))
print("Firmware: 0x{:8x} \t 0x{:8x} |\t0x{:8x} \t 0x{:8x}".format(otadata_info[0].seq, otadata_info[0].crc,
otadata_info[1].seq, otadata_info[1].crc))
def erase_otadata(args):
status("Erasing ota_data partition contents...")
_invoke_parttool(["erase_partition"], args)
status("Erased ota_data partition contents")
def switch_otadata(args):
sys.path.append(os.path.join(IDF_COMPONENTS_PATH, "partition_table"))
import gen_esp32part as gen
with tempfile.NamedTemporaryFile(delete=False) as f:
f_name = f.name
try:
def is_otadata_status_valid(status):
def is_otadata_info_valid(status):
seq = status.seq % (1 << 32)
crc = hex(binascii.crc32(struct.pack("I", seq), 0xFFFFFFFF) % (1 << 32))
return seq < (int('0xFFFFFFFF', 16) % (1 << 32)) and status.crc == crc
status("Looking for ota app partitions...")
# In order to get the number of ota app partitions, we need the partition table
partition_table = None
invoke_args = ["get_partition_info", "--table", f_name]
_invoke_parttool(invoke_args, args)
partition_table = open(f_name, "rb").read()
partition_table = gen.PartitionTable.from_binary(partition_table)
partition_table = self.target.partition_table
ota_partitions = list()
@@ -171,39 +126,36 @@ def switch_otadata(args):
ota_partitions = sorted(ota_partitions, key=lambda p: p.subtype)
if not ota_partitions:
raise RuntimeError("No ota app partitions found")
status("Verifying partition to switch to exists...")
raise Exception("No ota app partitions found")
# Look for the app partition to switch to
ota_partition_next = None
try:
if args.name:
ota_partition_next = filter(lambda p: p.name == args.name, ota_partitions)
if isinstance(ota_id, int):
ota_partition_next = filter(lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == ota_id, ota_partitions)
else:
ota_partition_next = filter(lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == args.slot, ota_partitions)
ota_partition_next = filter(lambda p: p.name == ota_id, ota_partitions)
ota_partition_next = list(ota_partition_next)[0]
except IndexError:
raise RuntimeError("Partition to switch to not found")
raise Exception("Partition to switch to not found")
otadata_contents = _get_otadata_contents(args)
otadata_status = _get_otadata_status(otadata_contents)
otadata_info = self._get_otadata_info()
# Find the copy to base the computation for ota sequence number on
otadata_compute_base = -1
# Both are valid, take the max as computation base
if is_otadata_status_valid(otadata_status[0]) and is_otadata_status_valid(otadata_status[1]):
if otadata_status[0].seq >= otadata_status[1].seq:
if is_otadata_info_valid(otadata_info[0]) and is_otadata_info_valid(otadata_info[1]):
if otadata_info[0].seq >= otadata_info[1].seq:
otadata_compute_base = 0
else:
otadata_compute_base = 1
# Only one copy is valid, use that
elif is_otadata_status_valid(otadata_status[0]):
elif is_otadata_info_valid(otadata_info[0]):
otadata_compute_base = 0
elif is_otadata_status_valid(otadata_status[1]):
elif is_otadata_info_valid(otadata_info[1]):
otadata_compute_base = 1
# Both are invalid (could be initial state - all 0xFF's)
else:
@@ -216,7 +168,7 @@ def switch_otadata(args):
# Find the next ota sequence number
if otadata_compute_base == 0 or otadata_compute_base == 1:
base_seq = otadata_status[otadata_compute_base].seq % (1 << 32)
base_seq = otadata_info[otadata_compute_base].seq % (1 << 32)
i = 0
while base_seq > target_seq % ota_partitions_num + i * ota_partitions_num:
@@ -231,47 +183,68 @@ def switch_otadata(args):
ota_seq_crc_next = binascii.crc32(ota_seq_next, 0xFFFFFFFF) % (1 << 32)
ota_seq_crc_next = struct.pack("I", ota_seq_crc_next)
with open(f_name, "wb") as otadata_next_file:
start = (1 if otadata_compute_base == 0 else 0) * (SPI_FLASH_SEC_SIZE >> 1)
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.close()
otadata_next_file.write(otadata_contents)
try:
with open(temp_file.name, "wb") as otadata_next_file:
start = (1 if otadata_compute_base == 0 else 0) * (self.spi_flash_sec_size >> 1)
otadata_next_file.seek(start)
otadata_next_file.write(ota_seq_next)
otadata_next_file.write(self.otadata)
otadata_next_file.seek(start + 28)
otadata_next_file.write(ota_seq_crc_next)
otadata_next_file.seek(start)
otadata_next_file.write(ota_seq_next)
otadata_next_file.flush()
otadata_next_file.seek(start + 28)
otadata_next_file.write(ota_seq_crc_next)
_invoke_parttool(["write_partition", "--input", f_name], args)
status("Updated ota_data partition")
finally:
os.unlink(f_name)
otadata_next_file.flush()
self.target.write_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name)
finally:
os.unlink(temp_file.name)
def read_ota_partition(self, ota_id, output):
self.target.read_partition(self._get_partition_id_from_ota_id(ota_id), output)
def write_ota_partition(self, ota_id, input):
self.target.write_partition(self._get_partition_id_from_ota_id(ota_id), input)
def erase_ota_partition(self, ota_id):
self.target.erase_partition(self._get_partition_id_from_ota_id(ota_id))
def _get_partition_specifier(args):
if args.name:
return ["--partition-name", args.name]
else:
return ["--partition-type", "app", "--partition-subtype", "ota_" + str(args.slot)]
def _read_otadata(target):
target._check_otadata_partition()
otadata_info = target._get_otadata_info()
print(" {:8s} \t {:8s} | \t {:8s} \t {:8s}".format("OTA_SEQ", "CRC", "OTA_SEQ", "CRC"))
print("Firmware: 0x{:8x} \t0x{:8x} | \t0x{:8x} \t 0x{:8x}".format(otadata_info[0].seq, otadata_info[0].crc,
otadata_info[1].seq, otadata_info[1].crc))
def read_ota_partition(args):
invoke_args = ["read_partition", "--output", args.output]
_invoke_parttool(invoke_args, args, partition=_get_partition_specifier(args))
status("Read ota partition contents to file {}".format(args.output))
def _erase_otadata(target):
target.erase_otadata()
status("Erased ota_data partition contents")
def write_ota_partition(args):
invoke_args = ["write_partition", "--input", args.input]
_invoke_parttool(invoke_args, args, partition=_get_partition_specifier(args))
status("Written contents of file {} to ota partition".format(args.input))
def _switch_ota_partition(target, ota_id):
target.switch_ota_partition(ota_id)
def erase_ota_partition(args):
invoke_args = ["erase_partition"]
_invoke_parttool(invoke_args, args, partition=_get_partition_specifier(args))
def _read_ota_partition(target, ota_id, output):
target.read_ota_partition(ota_id, output)
status("Read ota partition contents to file {}".format(output))
def _write_ota_partition(target, ota_id, input):
target.write_ota_partition(ota_id, input)
status("Written contents of file {} to ota partition".format(input))
def _erase_ota_partition(target, ota_id):
target.erase_ota_partition(ota_id)
status("Erased contents of ota partition")
@@ -281,20 +254,29 @@ def main():
parser = argparse.ArgumentParser("ESP-IDF OTA Partitions Tool")
parser.add_argument("--quiet", "-q", help="suppress stderr messages", action="store_true")
parser.add_argument("--esptool-args", help="additional main arguments for esptool", nargs="+")
parser.add_argument("--esptool-write-args", help="additional subcommand arguments for esptool write_flash", nargs="+")
parser.add_argument("--esptool-read-args", help="additional subcommand arguments for esptool read_flash", nargs="+")
parser.add_argument("--esptool-erase-args", help="additional subcommand arguments for esptool erase_region", nargs="+")
# There are two possible sources for the partition table: a device attached to the host
# or a partition table CSV/binary file. These sources are mutually exclusive.
partition_table_info_source_args = parser.add_mutually_exclusive_group()
parser.add_argument("--port", "-p", help="port where the device to read the partition table from is attached")
partition_table_info_source_args.add_argument("--port", "-p", help="port where the device to read the partition table from is attached", default="")
partition_table_info_source_args.add_argument("--partition-table-file", "-f", help="file (CSV/binary) to read the partition table from", default="")
parser.add_argument("--baud", "-b", help="baudrate to use", type=int)
parser.add_argument("--partition-table-offset", "-o", help="offset to read the partition table from", default="0x8000")
parser.add_argument("--partition-table-offset", "-o", help="offset to read the partition table from", type=str)
parser.add_argument("--partition-table-file", "-f", help="file (CSV/binary) to read the partition table from; \
overrides device attached to specified port as the partition table source when defined")
subparsers = parser.add_subparsers(dest="operation", help="run otatool -h for additional help")
spi_flash_sec_size = argparse.ArgumentParser(add_help=False)
spi_flash_sec_size.add_argument("--spi-flash-sec-size", help="value of SPI_FLASH_SEC_SIZE macro", type=str)
# Specify the supported operations
subparsers.add_parser("read_otadata", help="read otadata partition")
subparsers.add_parser("read_otadata", help="read otadata partition", parents=[spi_flash_sec_size])
subparsers.add_parser("erase_otadata", help="erase otadata partition")
slot_or_name_parser = argparse.ArgumentParser(add_help=False)
@@ -302,7 +284,7 @@ def main():
slot_or_name_parser_args.add_argument("--slot", help="slot number of the ota partition", type=int)
slot_or_name_parser_args.add_argument("--name", help="name of the ota partition")
subparsers.add_parser("switch_otadata", help="switch otadata partition", parents=[slot_or_name_parser])
subparsers.add_parser("switch_ota_partition", help="switch otadata partition", parents=[slot_or_name_parser, spi_flash_sec_size])
read_ota_partition_subparser = subparsers.add_parser("read_ota_partition", help="read contents of an ota partition", parents=[slot_or_name_parser])
read_ota_partition_subparser.add_argument("--output", help="file to write the contents of the ota partition to")
@@ -322,17 +304,84 @@ def main():
parser.print_help()
sys.exit(1)
# Else execute the operation
operation_func = globals()[args.operation]
target_args = {}
if args.port:
target_args["port"] = args.port
if args.partition_table_file:
target_args["partition_table_file"] = args.partition_table_file
if args.partition_table_offset:
target_args["partition_table_offset"] = int(args.partition_table_offset, 0)
try:
if args.spi_flash_sec_size:
target_args["spi_flash_sec_size"] = int(args.spi_flash_sec_size, 0)
except AttributeError:
pass
if args.esptool_args:
target_args["esptool_args"] = args.esptool_args
if args.esptool_write_args:
target_args["esptool_write_args"] = args.esptool_write_args
if args.esptool_read_args:
target_args["esptool_read_args"] = args.esptool_read_args
if args.esptool_erase_args:
target_args["esptool_erase_args"] = args.esptool_erase_args
if args.baud:
target_args["baud"] = args.baud
target = OtatoolTarget(**target_args)
# Create the operation table and execute the operation
common_args = {'target':target}
ota_id = []
try:
if args.name is not None:
ota_id = ["name"]
else:
if args.slot is not None:
ota_id = ["slot"]
except AttributeError:
pass
otatool_ops = {
'read_otadata':(_read_otadata, []),
'erase_otadata':(_erase_otadata, []),
'switch_ota_partition':(_switch_ota_partition, ota_id),
'read_ota_partition':(_read_ota_partition, ["output"] + ota_id),
'write_ota_partition':(_write_ota_partition, ["input"] + ota_id),
'erase_ota_partition':(_erase_ota_partition, ota_id)
}
(op, op_args) = otatool_ops[args.operation]
for op_arg in op_args:
common_args.update({op_arg:vars(args)[op_arg]})
try:
common_args['ota_id'] = common_args.pop('name')
except KeyError:
try:
common_args['ota_id'] = common_args.pop('slot')
except KeyError:
pass
if quiet:
# If exceptions occur, suppress and exit quietly
try:
operation_func(args)
op(**common_args)
except Exception:
sys.exit(2)
else:
operation_func(args)
op(**common_args)
if __name__ == '__main__':

View File

@@ -1,6 +1,3 @@
set(COMPONENT_SRCDIRS ".")
set(COMPONENT_ADD_INCLUDEDIRS ".")
set(COMPONENT_REQUIRES unity test_utils app_update bootloader_support nvs_flash)
register_component()
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS "."
REQUIRES unity test_utils app_update bootloader_support nvs_flash)

View File

@@ -296,7 +296,7 @@ static void test_flow1(void)
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
// 4 Stage: run OTA1 -> check it -> copy OTA1 to OTA0 -> reboot --//--
// 5 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
static void test_flow2(void)
{
@@ -333,7 +333,7 @@ static void test_flow2(void)
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> corrupt ota data -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
static void test_flow3(void)
{
@@ -377,7 +377,7 @@ static void test_flow3(void)
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
// 3 Stage: run OTA1 -> check it -> corrupt ota sector2 -> reboot --//--
// 4 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
#define STORAGE_NAMESPACE "update_ota"
@@ -444,7 +444,7 @@ static void test_flow4(void)
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> set_pin_factory_reset -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
#endif
#ifdef CONFIG_BOOTLOADER_APP_TEST
@@ -487,7 +487,7 @@ static void test_flow5(void)
// 2 Stage: run factory -> check it -> copy factory to Test and set pin_test_app -> reboot --//--
// 3 Stage: run test -> check it -> reset pin_test_app -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
#endif
static const esp_partition_t* app_update(void)
@@ -581,7 +581,7 @@ static void test_rollback1_1(void)
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback() -> reboot --//--
// 4 Stage: run OTA0 -> check it -> esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1);
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1);
static void test_rollback2(void)
{
@@ -679,7 +679,7 @@ static void test_rollback2_1(void)
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback(), copy to next app slot -> reboot --//--
// 4 Stage: run OTA1 -> check it -> PENDING_VERIFY/esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
// 5 Stage: run OTA0(rollback) -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1);
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1);
static void test_erase_last_app_flow(void)
{
@@ -730,4 +730,4 @@ static void test_erase_last_app_rollback(void)
// 3 Stage: run OTA0 -> check it -> copy factory to OTA1 -> reboot --//--
// 4 Stage: run OTA1 -> check it -> erase OTA0 and rollback -> reboot
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback);
TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback);