diff --git a/tools/test_apps/system/panic/panic_base/pytest_panic.py b/tools/test_apps/system/panic/panic_base/pytest_panic.py index 470807134ea..f6508d3b216 100644 --- a/tools/test_apps/system/panic/panic_base/pytest_panic.py +++ b/tools/test_apps/system/panic/panic_base/pytest_panic.py @@ -35,11 +35,13 @@ def configs_for_app(app_path: str, configs: Sequence[str]) -> list[tuple[str, st return [(app_path, config) for config in configs] -def configs_with_esp32s2_xfail( - configs: Sequence[tuple[str, str] | tuple[str, str, Any]], reason: str +def configs_with_xfail( + configs: Sequence[tuple[str, str] | tuple[str, str, Any]], + reason: str, + targets: Sequence[str] = ('esp32s2',), ) -> list[tuple[str, str] | tuple[str, str, Any]]: return [ - (entry[0], entry[1], pytest.mark.xfail(reason=reason, run=False)) if entry[1] == 'esp32s2' else entry + (entry[0], entry[1], pytest.mark.xfail(reason=reason, run=False)) if entry[1] in targets else entry for entry in configs ] @@ -618,7 +620,8 @@ def test_panic_handler_crash1(dut: PanicTestDut, config: str, test_func_name: st ######################### # Memprot-related tests are supported only on targets with PMS/PMA peripheral; -# currently ESP32-S2, ESP32-C3, ESP32-C2, ESP32-H2, ESP32-H21, ESP32-C6, ESP32-P4, ESP32-C5 and ESP32-C61 are supported +# currently ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C2, ESP32-H2, ESP32-H21, ESP32-C6, ESP32-P4, +# ESP32-C5, ESP32-C61, ESP32-H4 are supported # ESP32-P4 rev < 3.0 runs on a dedicated rev 1.x runner (its binary is built for # and only boots on rev < 3.0 silicon), so its configs carry the esp32p4_rev1 marker. P4_REV_LESS_THAN_V3_MARKER = pytest.mark.esp32p4_rev1 @@ -627,6 +630,7 @@ CONFIGS_MEMPROT_IDRAM = list( zip( [ 'memprot_esp32s2', + 'memprot_esp32s3', 'memprot_esp32c3', 'memprot_esp32c2', 'memprot_esp32c5', @@ -639,6 +643,7 @@ CONFIGS_MEMPROT_IDRAM = list( ], [ 'esp32s2', + 'esp32s3', 'esp32c3', 'esp32c2', 'esp32c5', @@ -662,6 +667,7 @@ CONFIGS_MEMPROT_RTC_FAST_MEM = list( zip( [ 'memprot_esp32s2', + 'memprot_esp32s3', 'memprot_esp32c3', 'memprot_esp32c5', 'memprot_esp32c6', @@ -670,7 +676,7 @@ CONFIGS_MEMPROT_RTC_FAST_MEM = list( 'memprot_esp32h21', 'memprot_esp32s31', ], - ['esp32s2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32h21', 'esp32s31'], + ['esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32h21', 'esp32s31'], ) ) + [ ('memprot_esp32p4_rev_less_than_v3', 'esp32p4', P4_REV_LESS_THAN_V3_MARKER), @@ -792,6 +798,13 @@ def iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.expect(r'Write operation at address [0-9xa-f]+ not permitted \((\S+)\)') dut.expect_reg_dump(0) dut.expect_backtrace() + elif dut.target == 'esp32s3': + dut.expect_gme('Memory protection fault') + dut.expect(r' memory type: (\S+)') + dut.expect(r' faulting address: [0-9xa-f]+') + dut.expect(r' operation type: (\S+)') + dut.expect_reg_dump(0) + dut.expect_backtrace() elif dut.target == 'esp32c3': dut.expect_exact(r'Test error: Test function has returned') else: @@ -824,6 +837,13 @@ def iram_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.expect(r'Write operation at address [0-9xa-f]+ not permitted \((\S+)\)') dut.expect_reg_dump(0) dut.expect_backtrace() + elif dut.target == 'esp32s3': + dut.expect_gme('Memory protection fault') + dut.expect(r' memory type: (\S+)') + dut.expect(r' faulting address: [0-9xa-f]+') + dut.expect(r' operation type: (\S+)') + dut.expect_reg_dump(0) + dut.expect_backtrace() elif dut.target == 'esp32c3': dut.expect_gme('Memory protection fault') dut.expect(r' memory type: (\S+)') @@ -915,10 +935,10 @@ def iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> None: @pytest.mark.generic @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') -# TODO: IDF-6820: ESP32-S2 -> Fix incorrect panic reason: Unhandled debug exception +# TODO: IDF-6820: ESP32-S2 / ESP32-S3 -> Fix incorrect panic reason: Unhandled debug exception @idf_parametrize( 'config,target,markers', - configs_with_esp32s2_xfail(CONFIGS_MEMPROT_IDRAM, 'Incorrect panic reason may be observed'), + configs_with_xfail(CONFIGS_MEMPROT_IDRAM, 'Incorrect panic reason may be observed', targets=('esp32s2', 'esp32s3')), indirect=['config', 'target'], ) def test_iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> None: @@ -940,6 +960,11 @@ def dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.expect(r'Unknown operation at address [0-9xa-f]+ not permitted \((\S+)\)') dut.expect_reg_dump(0) dut.expect_backtrace(corrupted=True) + elif dut.target == 'esp32s3': + dut.expect_gme('Cache error', core=None) + dut.expect_exact('MMU entry fault error') + dut.expect_reg_dump(0) + dut.expect_backtrace() else: dut.expect_gme('Instruction access fault') dut.expect_reg_dump(0) @@ -953,7 +978,7 @@ def dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: # TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs @idf_parametrize( 'config,target,markers', - configs_with_esp32s2_xfail(CONFIGS_MEMPROT_IDRAM, 'Multiple panic reasons for the same test may surface'), + configs_with_xfail(CONFIGS_MEMPROT_IDRAM, 'Multiple panic reasons for the same test may surface'), indirect=['config', 'target'], ) def test_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: @@ -974,6 +999,11 @@ def dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.expect_gme('InstructionFetchError') dut.expect_reg_dump(0) dut.expect_backtrace(corrupted=True) + elif dut.target == 'esp32s3': + dut.expect_gme('Cache error', core=None) + dut.expect_exact('MMU entry fault error') + dut.expect_reg_dump(0) + dut.expect_backtrace(corrupted=True) else: dut.expect_gme('Instruction access fault') dut.expect_reg_dump(0) @@ -987,7 +1017,7 @@ def dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: # TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs @idf_parametrize( 'config,target,markers', - configs_with_esp32s2_xfail(CONFIGS_MEMPROT_IDRAM, 'Multiple panic reasons for the same test may surface'), + configs_with_xfail(CONFIGS_MEMPROT_IDRAM, 'Multiple panic reasons for the same test may surface'), indirect=['config', 'target'], ) def test_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: @@ -1024,6 +1054,12 @@ def test_rtc_fast_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) dut.expect(r'Read operation at address [0-9xa-f]+ not permitted \((\S+)\)') dut.expect_reg_dump(0) dut.expect_backtrace() + elif dut.target == 'esp32s3': + dut.expect(r' memory type: (\S+)') + dut.expect(r' faulting address: [0-9xa-f]+') + dut.expect(r' operation type: (\S+)') + dut.expect_reg_dump(0) + dut.expect_backtrace() elif dut.target == 'esp32c3': dut.expect(r' memory type: (\S+)') dut.expect(r' faulting address: [0-9xa-f]+') @@ -1039,7 +1075,7 @@ def test_rtc_fast_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) # TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs @idf_parametrize( 'config,target,markers', - configs_with_esp32s2_xfail(CONFIGS_MEMPROT_RTC_FAST_MEM, 'Multiple panic reasons for the same test may surface'), + configs_with_xfail(CONFIGS_MEMPROT_RTC_FAST_MEM, 'Multiple panic reasons for the same test may surface'), indirect=['config', 'target'], ) def test_rtc_fast_reg3_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: @@ -1050,6 +1086,13 @@ def test_rtc_fast_reg3_execute_violation(dut: PanicTestDut, test_func_name: str) dut.expect(r'Unknown operation at address [0-9xa-f]+ not permitted \((\S+)\)') dut.expect_reg_dump(0) dut.expect_backtrace() + elif dut.target == 'esp32s3': + dut.expect_gme('Memory protection fault') + dut.expect(r' memory type: (\S+)') + dut.expect(r' faulting address: [0-9xa-f]+') + dut.expect(r' operation type: (\S+)') + dut.expect_reg_dump(0) + dut.expect_backtrace() elif dut.target == 'esp32c3': dut.expect_gme('Memory protection fault') dut.expect(r' memory type: (\S+)') diff --git a/tools/test_apps/system/panic/panic_base/test_panic_util/panic_dut.py b/tools/test_apps/system/panic/panic_base/test_panic_util/panic_dut.py index fac02e09fe6..a358cf79933 100644 --- a/tools/test_apps/system/panic/panic_base/test_panic_util/panic_dut.py +++ b/tools/test_apps/system/panic/panic_base/test_panic_util/panic_dut.py @@ -104,9 +104,16 @@ class PanicTestDut(IdfDut): result = self.expect(pattern, return_what_before_match=True).decode('utf-8') return result.strip() - def expect_gme(self, reason: str) -> None: - """Expect method for Guru Meditation Errors""" - self.expect_exact(f"Guru Meditation Error: Core 0 panic'ed ({reason})") + def expect_gme(self, reason: str, core: int | None = 0) -> None: + """Expect method for Guru Meditation Errors + + Pass core=None to accept any core id, including the -1 reported for + faults which cannot be attributed to a single core. + """ + if core is None: + self.expect(rf"Guru Meditation Error: Core\s+\S+ panic'ed \({re.escape(reason)}\)") + else: + self.expect_exact(f"Guru Meditation Error: Core {core} panic'ed ({reason})") def expect_reg_dump(self, core: int | None = None) -> None: if core is None: