|
1 | 1 | # SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD |
2 | 2 | # SPDX-License-Identifier: Unlicense OR CC0-1.0 |
3 | | -import json |
4 | | -import logging |
5 | 3 | import os |
6 | 4 | import re |
7 | | -import subprocess |
8 | | -import time |
9 | | -from subprocess import Popen |
10 | | -from typing import Optional |
| 5 | +import typing |
11 | 6 |
|
12 | 7 | import pexpect |
13 | 8 | import pytest |
14 | 9 | from pytest_embedded_idf import IdfDut |
15 | 10 | from pytest_embedded_idf.utils import idf_parametrize |
16 | 11 |
|
17 | | -MAX_RETRIES = 3 |
18 | | -RETRY_DELAY = 3 # seconds |
| 12 | +if typing.TYPE_CHECKING: |
| 13 | + from conftest import OpenOCD |
19 | 14 |
|
20 | 15 |
|
21 | | -def run_openocd(dut: IdfDut) -> Optional[Popen]: |
22 | | - desc_path = os.path.join(dut.app.binary_path, 'project_description.json') |
23 | | - try: |
24 | | - with open(desc_path, 'r') as f: |
25 | | - project_desc = json.load(f) |
26 | | - except FileNotFoundError: |
27 | | - logging.error('Project description file not found at %s', desc_path) |
28 | | - return None |
29 | | - |
30 | | - openocd_scripts = os.getenv('OPENOCD_SCRIPTS') |
31 | | - if not openocd_scripts: |
32 | | - logging.error('OPENOCD_SCRIPTS environment variable is not set.') |
33 | | - return None |
34 | | - |
35 | | - debug_args = project_desc.get('debug_arguments_openocd') |
36 | | - if not debug_args: |
37 | | - logging.error("'debug_arguments_openocd' key is missing in project_description.json") |
38 | | - return None |
39 | | - |
40 | | - cmd = ['openocd'] + ['-s', openocd_scripts] + debug_args.split() |
41 | | - |
42 | | - # For debug purpose, make the value '4' |
43 | | - ocd_env = os.environ.copy() |
44 | | - ocd_env['LIBUSB_DEBUG'] = '1' |
45 | | - |
46 | | - for attempt in range(1, MAX_RETRIES + 1): |
47 | | - logging.info('Attempt %d: Running %s', attempt, cmd) |
48 | | - with open(os.path.join(dut.logdir, 'ocd.txt'), 'w') as ocd_log: |
49 | | - try: |
50 | | - ocd = subprocess.Popen(cmd, stdout=ocd_log, stderr=ocd_log, env=ocd_env) |
51 | | - time.sleep(1) |
52 | | - |
53 | | - # Check if the process is running successfully |
54 | | - if ocd.poll() is None: |
55 | | - return ocd |
56 | | - else: |
57 | | - logging.error('OpenOCD exited with error code %d', ocd.returncode) |
58 | | - except subprocess.SubprocessError as e: |
59 | | - logging.error('Error running OpenOCD: %s', e) |
60 | | - |
61 | | - logging.warning("OpenOCD couldn't be run. Retrying in %d seconds...", RETRY_DELAY) |
62 | | - time.sleep(RETRY_DELAY) |
63 | | - |
64 | | - logging.error('Failed to run OpenOCD after %d attempts.', MAX_RETRIES) |
65 | | - |
66 | | - return None |
67 | | - |
68 | | - |
69 | | -def _test_idf_gdb(dut: IdfDut) -> None: |
| 16 | +def _test_idf_gdb(openocd: 'OpenOCD', dut: IdfDut) -> None: |
70 | 17 | # Need to wait a moment to connect via OpenOCD after the hard reset happened. |
71 | 18 | # Along with this check that app runs ok |
72 | 19 | dut.expect('Hello world!') |
73 | 20 |
|
74 | 21 | # Don't need to have output from UART anymore |
75 | 22 | dut.serial.stop_redirect_thread() |
76 | 23 |
|
77 | | - ocd = run_openocd(dut) |
78 | | - assert ocd |
79 | | - |
80 | | - try: |
81 | | - with open(os.path.join(dut.logdir, 'gdb.txt'), 'w') as gdb_log, pexpect.spawn( |
82 | | - f'idf.py -B {dut.app.binary_path} gdb --batch', |
83 | | - timeout=60, |
84 | | - logfile=gdb_log, |
85 | | - encoding='utf-8', |
86 | | - codec_errors='ignore', |
87 | | - ) as p: |
88 | | - p.expect(re.compile(r'add symbol table from file.*bootloader.elf')) |
89 | | - p.expect( |
90 | | - re.compile(r'add symbol table from file.*rom.elf') |
91 | | - ) # if fail here: add target support here https://github.com/espressif/esp-rom-elfs |
92 | | - p.expect_exact('hit Temporary breakpoint 1, app_main ()') |
93 | | - finally: |
94 | | - # Check if the process is still running |
95 | | - if ocd.poll() is None: |
96 | | - ocd.terminate() |
97 | | - ocd.kill() |
| 24 | + with openocd.run(), open(os.path.join(dut.logdir, 'gdb.txt'), 'w') as gdb_log, pexpect.spawn( |
| 25 | + f'idf.py -B {dut.app.binary_path} gdb --batch', |
| 26 | + timeout=60, |
| 27 | + logfile=gdb_log, |
| 28 | + encoding='utf-8', |
| 29 | + codec_errors='ignore', |
| 30 | + ) as p: |
| 31 | + p.expect(re.compile(r'add symbol table from file.*bootloader.elf')) |
| 32 | + p.expect( |
| 33 | + re.compile(r'add symbol table from file.*rom.elf') |
| 34 | + ) # if fail here: add target support here https://github.com/espressif/esp-rom-elfs |
| 35 | + p.expect_exact('hit Temporary breakpoint 1, app_main ()') |
98 | 36 |
|
99 | 37 |
|
100 | 38 | @pytest.mark.jtag |
101 | | -@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target']) |
102 | | -def test_idf_gdb(dut: IdfDut) -> None: |
103 | | - _test_idf_gdb(dut) |
| 39 | +@idf_parametrize('target', ['esp32', 'esp32c2', 'esp32s2'], indirect=['target']) |
| 40 | +def test_idf_gdb(openocd: 'OpenOCD', dut: IdfDut) -> None: |
| 41 | + _test_idf_gdb(openocd, dut) |
104 | 42 |
|
105 | 43 |
|
106 | 44 | @pytest.mark.usb_serial_jtag |
107 | | -@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target']) |
108 | | -def test_idf_gdb_usj(dut: IdfDut) -> None: |
109 | | - _test_idf_gdb(dut) |
| 45 | +@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target']) |
| 46 | +def test_idf_gdb_usj(openocd: 'OpenOCD', dut: IdfDut) -> None: |
| 47 | + _test_idf_gdb(openocd, dut) |
0 commit comments