diff options
author | Thorsten von Eicken <tve@voneicken.com> | 2020-04-01 22:59:08 -0700 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2020-05-03 15:00:45 +1000 |
commit | 952ff8a8ea9ae6128ff5225b180d8daaacf447e4 (patch) | |
tree | c69c41d01035ec4ee279a43f460c821cf1af04f3 /tests/esp32/partition_ota.py | |
parent | 7d97d241e861ba4cbd44d3695d4db6184974f8f9 (diff) | |
download | micropython-952ff8a8ea9ae6128ff5225b180d8daaacf447e4.tar.gz micropython-952ff8a8ea9ae6128ff5225b180d8daaacf447e4.zip |
esp32: Improve support for OTA updates.
This commit adds several small items to improve the support for OTA
updates on an esp32:
- a partition table for 4MB flash modules that has two OTA partitions ready
to go to do updates
- a GENERIC_OTA board that uses that partition table and that enables
automatic roll-back in the bootloader
- a new esp32.Partition.mark_app_valid_cancel_rollback() class-method to
signal that the boot is successful and should not be rolled back at the
next reset
- an automated test for doing an OTA update
- documentation updates
Diffstat (limited to 'tests/esp32/partition_ota.py')
-rw-r--r-- | tests/esp32/partition_ota.py | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/tests/esp32/partition_ota.py b/tests/esp32/partition_ota.py new file mode 100644 index 0000000000..765630c8ce --- /dev/null +++ b/tests/esp32/partition_ota.py @@ -0,0 +1,117 @@ +# Test ESP32 OTA updates, including automatic roll-back. +# Running this test requires firmware with an OTA Partition, such as the GENERIC_OTA "board". +# This test also requires patience as it copies the boot partition into the other OTA slot. + +import machine +from esp32 import Partition + +# start by checking that the running partition table has OTA partitions, 'cause if +# it doesn't there's nothing we can test +cur = Partition(Partition.RUNNING) +cur_name = cur.info()[4] +if not cur_name.startswith("ota_"): + print("SKIP") + raise SystemExit + +DEBUG = True + + +def log(*args): + if DEBUG: + print(*args) + + +# replace boot.py with the test code that will run on each reboot +import uos + +try: + uos.rename("boot.py", "boot-orig.py") +except: + pass +with open("boot.py", "w") as f: + f.write("DEBUG=" + str(DEBUG)) + f.write( + """ +import machine +from esp32 import Partition +cur = Partition(Partition.RUNNING) +cur_name = cur.info()[4] + +def log(*args): + if DEBUG: print(*args) + +from step import STEP, EXPECT +log("Running partition: " + cur_name + " STEP=" + str(STEP) + " EXPECT=" + EXPECT) +if cur_name != EXPECT: + print("\\x04FAILED: step " + str(STEP) + " expected " + EXPECT + " got " + cur_name + "\\x04") + +if STEP == 0: + log("Not confirming boot ok and resetting back into first") + nxt = cur.get_next_update() + with open("step.py", "w") as f: + f.write("STEP=1\\nEXPECT=\\"" + nxt.info()[4] + "\\"\\n") + machine.reset() +elif STEP == 1: + log("Booting into second partition again") + nxt = cur.get_next_update() + nxt.set_boot() + with open("step.py", "w") as f: + f.write("STEP=2\\nEXPECT=\\"" + nxt.info()[4] + "\\"\\n") + machine.reset() +elif STEP == 2: + log("Confirming boot ok and rebooting into same partition") + Partition.mark_app_valid_cancel_rollback() + with open("step.py", "w") as f: + f.write("STEP=3\\nEXPECT=\\"" + cur_name + "\\"\\n") + machine.reset() +elif STEP == 3: + log("Booting into original partition") + nxt = cur.get_next_update() + nxt.set_boot() + with open("step.py", "w") as f: + f.write("STEP=4\\nEXPECT=\\"" + nxt.info()[4] + "\\"\\n") + machine.reset() +elif STEP == 4: + log("Confirming boot ok and DONE!") + Partition.mark_app_valid_cancel_rollback() + import uos + uos.remove("step.py") + uos.remove("boot.py") + uos.rename("boot-orig.py", "boot.py") + print("\\nSUCCESS!\\n\\x04\\x04") + +""" + ) + + +def copy_partition(src, dest): + log("Partition copy: {} --> {}".format(src.info(), dest.info())) + sz = src.info()[3] + if dest.info()[3] != sz: + raise ValueError("Sizes don't match: {} vs {}".format(sz, dest.info()[3])) + addr = 0 + blk = bytearray(4096) + while addr < sz: + if sz - addr < 4096: + blk = blk[: sz - addr] + if addr & 0xFFFF == 0: + # need to show progress to run-tests else it times out + print(" ... 0x{:06x}".format(addr)) + src.readblocks(addr >> 12, blk) + dest.writeblocks(addr >> 12, blk) + addr += len(blk) + + +# get things started by copying the current partition into the next slot and rebooting +print("Copying current to next partition") +nxt = cur.get_next_update() +copy_partition(cur, nxt) +print("Partition copied, booting into it") +nxt.set_boot() + +# the step.py file is used to keep track of state across reboots +# EXPECT is the name of the partition we expect to reboot into +with open("step.py", "w") as f: + f.write('STEP=0\nEXPECT="' + nxt.info()[4] + '"\n') + +machine.reset() |