Skip to content

Commit

Permalink
Merge branch 'espressif:master' into main_work
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason2866 authored Apr 21, 2024
2 parents f849d1d + d2bfaad commit 2356b18
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 5 deletions.
7 changes: 7 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,13 @@ target_esp32s3_jtag_serial:
script:
- coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32S3_JTAG_SERIAL --preload-port /dev/serial_ports/ESP32S3_PRELOAD --chip esp32s3 --baud 115200

target_esp32s3_sdm:
extends: .target_esptool_test
tags:
- esptool_esp32s3_sdm_target
script:
- coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool_sdm.py --port /dev/serial_ports/ESP32S3_SDM --chip esp32s3 --baud 115200

# ESP32C2
target_esp32c2_40mhz:
extends: .target_esptool_test
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ The following tests are not run automatically by GitHub Actions, because they ne

Some tests might fail at higher baud rates on some hardware.

* ``test_esptool_sdm.py`` contains integration tests for ``esptool.py`` with chips in secure download mode. It needs to be run against real Espressif hardware (with active SDM). The command line format is the same as for ``test_esptool.py``.

The following tests are not run automatically by GitHub Actions, but can be run locally in a command line:

* ``test_espefuse.py`` tests ``espefuse.py`` functionality. To run it:
Expand Down
17 changes: 15 additions & 2 deletions espefuse/efuse/base_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,14 @@ def get_offsets(self):

return [self.parent.read_reg(offs) for offs in get_offsets(self)]

def read(self):
def read(self, print_info=True):
words = self.get_words()
data = BitArray()
for word in reversed(words):
data.append("uint:32=%d" % word)
self.bitarray.overwrite(data, pos=0)
self.print_block(self.bitarray, "read_regs")
if print_info:
self.print_block(self.bitarray, "read_regs")

def print_block(self, bit_string, comment, debug=False):
if self.parent.debug or debug:
Expand Down Expand Up @@ -386,6 +387,18 @@ def burn_words(self, words):
)
break
if not self.fail and self.num_errors == 0:
self.read(print_info=False)
if self.wr_bitarray & self.bitarray != self.wr_bitarray:
# if the required bits are not set then we need to re-burn it again.
if burns < 2:
print(
f"\nRepeat burning BLOCK{self.id} (#{burns + 2}) because not all bits were set"
)
continue
else:
print(
f"\nAfter {burns + 1} attempts, the required data was not set to BLOCK{self.id}"
)
break

def burn(self):
Expand Down
6 changes: 3 additions & 3 deletions test/test_esptool.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,17 @@ def run_esptool_process(cmd):
print(output) # for more complete stdout logs on failure
return output

def run_esptool_error(self, args, baud=None):
def run_esptool_error(self, args, baud=None, chip=None):
"""
Run esptool.py similar to run_esptool, but expect an error.
Verifies the error is an expected error not an unhandled exception,
and returns the output from esptool.py as a string.
"""
with pytest.raises(subprocess.CalledProcessError) as fail:
self.run_esptool(args, baud)
self.run_esptool(args, baud, chip)
failure = fail.value
assert failure.returncode == 2 # esptool.FatalError return code
assert failure.returncode in [1, 2] # UnsupportedCmdError and FatalError codes
return failure.output.decode("utf-8")

@classmethod
Expand Down
69 changes: 69 additions & 0 deletions test/test_esptool_sdm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Unit tests (really integration tests) for esptool.py using the pytest framework
# Uses a device in the Secure Download Mode connected to the serial port.
#
# RUNNING THIS WILL MESS UP THE DEVICE'S SPI FLASH CONTENTS
#
# How to use:
#
# Run with a physical connection to a chip:
# - `pytest test_esptool_sdm.py --chip esp32 --port /dev/ttyUSB0 --baud 115200`
#
# where - --port - a serial port for esptool.py operation
# - --chip - ESP chip name
# - --baud - baud rate
# - --with-trace - trace all interactions (True or False)

from test_esptool import EsptoolTestCase, arg_chip, esptool, pytest


@pytest.mark.skipif(
arg_chip == "esp8266", reason="ESP8266 does not support Secure Download Mode"
)
class TestSecureDownloadMode(EsptoolTestCase):
expected_chip_name = esptool.util.expand_chip_name(arg_chip)

def test_auto_detect(self):
output = self.run_esptool_error("flash_id", chip="auto")

if arg_chip in ["esp32", "esp32s2"]: # no autodetection with get_security_info
assert "Secure Download Mode is enabled" in output
assert "Unsupported detection protocol" in output
else:
assert "Unsupported detection protocol" not in output
assert f"Detecting chip type... {self.expected_chip_name}" in output
assert "Stub loader is not supported in Secure Download Mode" in output
assert (
f"Chip is {self.expected_chip_name} in Secure Download Mode" in output
)

# Commands not supported in SDM
def test_sdm_incompatible_commands(self):
output = self.run_esptool_error("flash_id") # flash_id
assert "This command (0xa) is not supported in Secure Download Mode" in output

output = self.run_esptool_error("read_flash 0 10 out.bin") # read_flash
assert "This command (0xe) is not supported in Secure Download Mode" in output

output = self.run_esptool_error("erase_flash") # erase_flash
assert (
f"{self.expected_chip_name} ROM does not support function erase_flash"
in output
)

# Commands supported in SDM
def test_sdm_compatible_commands(self):
output = self.run_esptool("write_flash 0x0 images/one_kb.bin") # write_flash
assert "Security features enabled, so not changing any flash settings" in output
assert "Wrote 1024 bytes" in output
assert "Hash of data verified." not in output # Verification not supported

output = self.run_esptool_error(
"write_flash --flash_size detect 0x0 images/one_kb.bin"
)
assert (
"Detecting flash size is not supported in secure download mode." in output
)

if arg_chip != "esp32": # esp32 does not support get_security_info
output = self.run_esptool("get_security_info") # get_security_info
assert "Security Information:" in output

0 comments on commit 2356b18

Please sign in to comment.