diff --git a/all_local_packages.txt b/all_local_packages.txt index 830f5c96..5d368c30 100644 --- a/all_local_packages.txt +++ b/all_local_packages.txt @@ -5,3 +5,4 @@ -e ./pytest-embedded-jtag/ -e ./pytest-embedded-qemu/ -e ./pytest-embedded-arduino/ +-e ./pytest-embedded-nuttx/ diff --git a/pytest-embedded-nuttx/pytest_embedded_nuttx/app.py b/pytest-embedded-nuttx/pytest_embedded_nuttx/app.py index 467712a2..4557b487 100644 --- a/pytest-embedded-nuttx/pytest_embedded_nuttx/app.py +++ b/pytest-embedded-nuttx/pytest_embedded_nuttx/app.py @@ -22,9 +22,9 @@ def __init__( super().__init__(**kwargs) self.file_extension = file_extension - self.app_file, self.bootloader_file, self.merge_file = self._get_bin_files() + self.app_file, self.bootloader_file, self.merge_file, self.vefuse_file = self._get_bin_files() - def _get_bin_files(self) -> tuple[Path | None, Path | None, Path | None]: + def _get_bin_files(self) -> tuple[Path | None, Path | None, Path | None, Path | None]: """ Get path to binary files available in the app_path. If either the application image or bootloader is not found, @@ -37,6 +37,7 @@ def _get_bin_files(self) -> tuple[Path | None, Path | None, Path | None]: search_pattern = '*' + self.file_extension bin_files = list(search_path.rglob(search_pattern)) app_file, bootloader_file, merge_file = None, None, None + vefuse_file = None logging.info('Searching %s', str(search_path)) if not bin_files: @@ -44,6 +45,9 @@ def _get_bin_files(self) -> tuple[Path | None, Path | None, Path | None]: for file_path in bin_files: file_name = str(file_path.stem) + if 'vefuse' in file_name: + vefuse_file = file_path + logging.info('Virtual E-Fuse file: %s', vefuse_file.as_posix()) if 'nuttx' in file_name: if 'merged' in file_name: merge_file = file_path @@ -59,4 +63,4 @@ def _get_bin_files(self) -> tuple[Path | None, Path | None, Path | None]: logging.error('App file not found: %s', app_file) print(bin_files) - return app_file, bootloader_file, merge_file + return app_file, bootloader_file, merge_file, vefuse_file diff --git a/pytest-embedded-nuttx/pytest_embedded_nuttx/serial.py b/pytest-embedded-nuttx/pytest_embedded_nuttx/serial.py index 5a6d50b0..f3942fbf 100644 --- a/pytest-embedded-nuttx/pytest_embedded_nuttx/serial.py +++ b/pytest-embedded-nuttx/pytest_embedded_nuttx/serial.py @@ -15,7 +15,8 @@ class NuttxSerial(EspSerial): # Default offset for the primary MCUBoot slot across # all Espressif devices on NuttX - MCUBOOT_PRIMARY_SLOT_OFFSET = 0x10000 + MCUBOOT_PRIMARY_SLOT_OFFSET = 0x20000 + VIRTUAL_EFUSE_OFFSET = 0x10000 SERIAL_BAUDRATE = 115200 binary_offsets: ClassVar[dict[str, int]] = { @@ -82,13 +83,19 @@ def get_key_from_value(dictionary, val): self.flash_mode = 'dio' @EspSerial.use_esptool() - def flash(self) -> None: + def flash( + self, + virtual_efuse_offset: int = VIRTUAL_EFUSE_OFFSET, + mcuboot_primary_slot_offset: int = MCUBOOT_PRIMARY_SLOT_OFFSET, + ) -> None: """Flash the binary files to the board.""" flash_files = [] if self.app.bootloader_file: + if self.app.vefuse_file: + flash_files.extend((str(virtual_efuse_offset), self.app.vefuse_file.as_posix())) flash_files.extend((str(self.binary_offsets[self.target]), self.app.bootloader_file.as_posix())) - flash_files.extend((str(self.MCUBOOT_PRIMARY_SLOT_OFFSET), self.app.app_file.as_posix())) + flash_files.extend((str(mcuboot_primary_slot_offset), self.app.app_file.as_posix())) else: flash_files.extend((str(self.binary_offsets[self.target]), self.app.app_file.as_posix())) @@ -101,6 +108,11 @@ def flash(self) -> None: self.flash_freq, ] + print(f'Flash files: {flash_files}') + print(f'Flash settings: {flash_settings}') + print(f'Virtual E-Fuse offset: {hex(virtual_efuse_offset)}') + print(f'MCUBoot primary slot offset: {hex(mcuboot_primary_slot_offset)}') + esptool.main( [ '--chip', diff --git a/pytest-embedded-nuttx/tests/test_nuttx.py b/pytest-embedded-nuttx/tests/test_nuttx.py index 6383f3b6..8d6a3d2e 100644 --- a/pytest-embedded-nuttx/tests/test_nuttx.py +++ b/pytest-embedded-nuttx/tests/test_nuttx.py @@ -48,6 +48,7 @@ def test_nuttx_app_mcuboot(dut, app, target): assert '4MB' == dut.serial.flash_size assert 'dio' == dut.serial.flash_mode assert None != app.bootloader_file + assert None == app.vefuse_file def test_nuttx_app_mcuboot_flash(serial, dut): serial.erase_flash() @@ -73,6 +74,47 @@ def test_hello_mcuboot(dut): result.assert_outcomes(passed=3) +def test_nuttx_app_mcuboot_with_virtual_efuse(testdir): + """This test takes vefuse.bin in consideration. This is a scenario + where the bootloader is flashed with virtual efuse enabled, which + changes the location in flash for MCUBoot and application. + This was added to NuttX on september 2025. + """ + testdir.makepyfile(""" + import pytest + + def test_nuttx_app_mcuboot(dut, app, target): + assert 'esp32' == target + assert '40m' == dut.serial.flash_freq + assert '4MB' == dut.serial.flash_size + assert 'dio' == dut.serial.flash_mode + assert None != app.bootloader_file + assert None != app.vefuse_file + + def test_nuttx_app_mcuboot_flash(serial, dut): + serial.erase_flash() + serial.flash() + dut.reset_to_nsh() + + def test_hello_mcuboot(dut): + dut.reset_to_nsh() + dut.write("ls /dev") + dut.expect("console") + """) + + result = testdir.runpytest( + '-s', + '--embedded-services', + 'nuttx,esp', + '--target', + 'esp32', + '--app-path', + os.path.join(testdir.tmpdir, 'hello_world_nuttx_virtual_efuse'), + ) + + result.assert_outcomes(passed=3) + + qemu_bin_required = pytest.mark.skipif( shutil.which('qemu-system-xtensa') is None, reason='Please make sure that `qemu-system-xtensa` is in your PATH env var. Build QEMU for ESP32 locally and then ' diff --git a/tests/fixtures/hello_world_nuttx_mcuboot/mcuboot-esp32.bin b/tests/fixtures/hello_world_nuttx_mcuboot/mcuboot-esp32.bin index e376cd18..50cd06c1 100644 Binary files a/tests/fixtures/hello_world_nuttx_mcuboot/mcuboot-esp32.bin and b/tests/fixtures/hello_world_nuttx_mcuboot/mcuboot-esp32.bin differ diff --git a/tests/fixtures/hello_world_nuttx_mcuboot/nuttx.bin b/tests/fixtures/hello_world_nuttx_mcuboot/nuttx.bin index 02b6a0af..2c2f85e5 100644 Binary files a/tests/fixtures/hello_world_nuttx_mcuboot/nuttx.bin and b/tests/fixtures/hello_world_nuttx_mcuboot/nuttx.bin differ diff --git a/tests/fixtures/hello_world_nuttx_virtual_efuse/mcuboot-esp32.bin b/tests/fixtures/hello_world_nuttx_virtual_efuse/mcuboot-esp32.bin new file mode 100644 index 00000000..50cd06c1 Binary files /dev/null and b/tests/fixtures/hello_world_nuttx_virtual_efuse/mcuboot-esp32.bin differ diff --git a/tests/fixtures/hello_world_nuttx_virtual_efuse/nuttx.bin b/tests/fixtures/hello_world_nuttx_virtual_efuse/nuttx.bin new file mode 100644 index 00000000..7a1deae5 Binary files /dev/null and b/tests/fixtures/hello_world_nuttx_virtual_efuse/nuttx.bin differ diff --git a/tests/fixtures/hello_world_nuttx_virtual_efuse/vefuse.bin b/tests/fixtures/hello_world_nuttx_virtual_efuse/vefuse.bin new file mode 100644 index 00000000..e69de29b