mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 21:24:32 +02:00
Merge branch 'contrib/github_pr_15974' into 'master'
fix(tools/idf-qemu): Append qemu_extra_args after monitor -serial not before (GitHub PR) Closes IDFGH-15315 See merge request espressif/esp-idf!39257
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
import atexit
|
import atexit
|
||||||
import binascii
|
import binascii
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -18,7 +19,10 @@ from typing import List
|
|||||||
from click.core import Context
|
from click.core import Context
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from idf_py_actions.tools import PropertyDict, ensure_build_directory, red_print, yellow_print
|
from idf_py_actions.tools import PropertyDict
|
||||||
|
from idf_py_actions.tools import ensure_build_directory
|
||||||
|
from idf_py_actions.tools import red_print
|
||||||
|
from idf_py_actions.tools import yellow_print
|
||||||
except ImportError:
|
except ImportError:
|
||||||
PropertyDict = Any
|
PropertyDict = Any
|
||||||
|
|
||||||
@@ -37,6 +41,7 @@ class QemuTarget:
|
|||||||
"""
|
"""
|
||||||
Target-specific information related to QEMU.
|
Target-specific information related to QEMU.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
target: str # chip name, e.g. esp32, esp32c3
|
target: str # chip name, e.g. esp32, esp32c3
|
||||||
qemu_prog: str # name of the QEMU binary, e.g. qemu-system-xtensa
|
qemu_prog: str # name of the QEMU binary, e.g. qemu-system-xtensa
|
||||||
install_package: str # name of the tools.json package from which to install the QEMU binary
|
install_package: str # name of the tools.json package from which to install the QEMU binary
|
||||||
@@ -60,10 +65,11 @@ QEMU_TARGETS: Dict[str, QemuTarget] = {
|
|||||||
'00000000000000000000000000800000000000000000100000000000000000000000000000000000'
|
'00000000000000000000000000800000000000000000100000000000000000000000000000000000'
|
||||||
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
'00000000'),
|
'00000000'
|
||||||
|
),
|
||||||
'-global driver=esp32.gpio,property=strap_mode,value=0x0f',
|
'-global driver=esp32.gpio,property=strap_mode,value=0x0f',
|
||||||
'nvram.esp32.efuse'),
|
'nvram.esp32.efuse',
|
||||||
|
),
|
||||||
'esp32c3': QemuTarget(
|
'esp32c3': QemuTarget(
|
||||||
'esp32c3',
|
'esp32c3',
|
||||||
'qemu-system-riscv32',
|
'qemu-system-riscv32',
|
||||||
@@ -96,10 +102,11 @@ QEMU_TARGETS: Dict[str, QemuTarget] = {
|
|||||||
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
'000000000000000000000000000000000000000000000000'),
|
'000000000000000000000000000000000000000000000000'
|
||||||
|
),
|
||||||
'-global driver=esp32c3.gpio,property=strap_mode,value=0x02',
|
'-global driver=esp32c3.gpio,property=strap_mode,value=0x02',
|
||||||
'nvram.esp32c3.efuse'),
|
'nvram.esp32c3.efuse',
|
||||||
|
),
|
||||||
'esp32s3': QemuTarget(
|
'esp32s3': QemuTarget(
|
||||||
'esp32s3',
|
'esp32s3',
|
||||||
'qemu-system-xtensa',
|
'qemu-system-xtensa',
|
||||||
@@ -132,9 +139,11 @@ QEMU_TARGETS: Dict[str, QemuTarget] = {
|
|||||||
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
'000000000000000000000000000000000000000000000000'),
|
'000000000000000000000000000000000000000000000000'
|
||||||
|
),
|
||||||
'-global driver=esp32s3.gpio,property=strap_mode,value=0x07',
|
'-global driver=esp32s3.gpio,property=strap_mode,value=0x07',
|
||||||
'nvram.esp32c3.efuse'), # Not esp32s3, QEMU-201
|
'nvram.esp32c3.efuse',
|
||||||
|
), # Not esp32s3, QEMU-201
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,6 +151,7 @@ class QemuTaskRunOptions:
|
|||||||
"""
|
"""
|
||||||
Some options related to QEMU execution, which depend on the presence of other tasks: gdb and monitor.
|
Some options related to QEMU execution, which depend on the presence of other tasks: gdb and monitor.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.bg_mode = False
|
self.bg_mode = False
|
||||||
self.wait_for_gdb = False
|
self.wait_for_gdb = False
|
||||||
@@ -213,7 +223,16 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
project_desc = json.load(f)
|
project_desc = json.load(f)
|
||||||
return project_desc
|
return project_desc
|
||||||
|
|
||||||
def qemu(action: str, ctx: Context, args: PropertyDict, qemu_extra_args: str, gdb: bool, graphics: bool, efuse_file: str, flash_file: str) -> None:
|
def qemu(
|
||||||
|
action: str,
|
||||||
|
ctx: Context,
|
||||||
|
args: PropertyDict,
|
||||||
|
qemu_extra_args: str,
|
||||||
|
gdb: bool,
|
||||||
|
graphics: bool,
|
||||||
|
efuse_file: str,
|
||||||
|
flash_file: str,
|
||||||
|
) -> None:
|
||||||
project_desc = _get_project_desc(args, ctx)
|
project_desc = _get_project_desc(args, ctx)
|
||||||
|
|
||||||
# Determine the target and check if we have the necessary QEMU binary
|
# Determine the target and check if we have the necessary QEMU binary
|
||||||
@@ -223,9 +242,11 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
red_print(f'QEMU is not supported for target {target}')
|
red_print(f'QEMU is not supported for target {target}')
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
if not shutil.which(qemu_target_info.qemu_prog):
|
if not shutil.which(qemu_target_info.qemu_prog):
|
||||||
red_print(f'{qemu_target_info.qemu_prog} is not installed. Please install it using '
|
red_print(
|
||||||
|
f'{qemu_target_info.qemu_prog} is not installed. Please install it using '
|
||||||
f'"python $IDF_PATH/tools/idf_tools.py install {qemu_target_info.install_package}" '
|
f'"python $IDF_PATH/tools/idf_tools.py install {qemu_target_info.install_package}" '
|
||||||
'or build it from source if the pre-built version is not available for your platform.')
|
'or build it from source if the pre-built version is not available for your platform.'
|
||||||
|
)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
# Generate flash image and efuse image
|
# Generate flash image and efuse image
|
||||||
@@ -237,14 +258,24 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
open(bin_path, 'rb').close()
|
open(bin_path, 'rb').close()
|
||||||
yellow_print(f'Using provided flash image: {bin_path}')
|
yellow_print(f'Using provided flash image: {bin_path}')
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
red_print(f'The provided flash image file \"{bin_path}\" could not be found')
|
red_print(f'The provided flash image file "{bin_path}" could not be found')
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
else:
|
else:
|
||||||
bin_path = os.path.join(args.build_dir, 'qemu_flash.bin')
|
bin_path = os.path.join(args.build_dir, 'qemu_flash.bin')
|
||||||
yellow_print(f'Generating flash image: {bin_path}')
|
yellow_print(f'Generating flash image: {bin_path}')
|
||||||
subprocess.check_call([
|
subprocess.check_call(
|
||||||
sys.executable, '-m', 'esptool', f'--chip={target}', 'merge_bin', f'--output={bin_path}',
|
[
|
||||||
f'--fill-flash-size={flash_size}', '@flash_args'], cwd=args.build_dir)
|
sys.executable,
|
||||||
|
'-m',
|
||||||
|
'esptool',
|
||||||
|
f'--chip={target}',
|
||||||
|
'merge_bin',
|
||||||
|
f'--output={bin_path}',
|
||||||
|
f'--fill-flash-size={flash_size}',
|
||||||
|
'@flash_args',
|
||||||
|
],
|
||||||
|
cwd=args.build_dir,
|
||||||
|
)
|
||||||
|
|
||||||
if efuse_file:
|
if efuse_file:
|
||||||
efuse_bin_path = efuse_file
|
efuse_bin_path = efuse_file
|
||||||
@@ -264,13 +295,17 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
# When boot mode is specified, the flash image is not required.
|
# When boot mode is specified, the flash image is not required.
|
||||||
if not options.boot_mode:
|
if not options.boot_mode:
|
||||||
qemu_args += [
|
qemu_args += [
|
||||||
'-drive', f'file={bin_path},if=mtd,format=raw',
|
'-drive',
|
||||||
|
f'file={bin_path},if=mtd,format=raw',
|
||||||
]
|
]
|
||||||
|
|
||||||
qemu_args += [
|
qemu_args += [
|
||||||
'-drive', f'file={efuse_bin_path},if=none,format=raw,id=efuse',
|
'-drive',
|
||||||
'-global', f'driver={qemu_target_info.efuse_device},property=drive,value=efuse',
|
f'file={efuse_bin_path},if=none,format=raw,id=efuse',
|
||||||
'-global', f'driver=timer.{target}.timg,property=wdt_disable,value=true',
|
'-global',
|
||||||
|
f'driver={qemu_target_info.efuse_device},property=drive,value=efuse',
|
||||||
|
'-global',
|
||||||
|
f'driver=timer.{target}.timg,property=wdt_disable,value=true',
|
||||||
]
|
]
|
||||||
|
|
||||||
if '-nic' not in qemu_extra_args:
|
if '-nic' not in qemu_extra_args:
|
||||||
@@ -279,9 +314,6 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
if options.wait_for_gdb or gdb:
|
if options.wait_for_gdb or gdb:
|
||||||
qemu_args += ['-gdb', f'tcp::{QEMU_PORT_GDB}', '-S']
|
qemu_args += ['-gdb', f'tcp::{QEMU_PORT_GDB}', '-S']
|
||||||
|
|
||||||
if qemu_extra_args:
|
|
||||||
qemu_args += qemu_extra_args.split(' ')
|
|
||||||
|
|
||||||
if graphics:
|
if graphics:
|
||||||
qemu_args += ['-display', 'sdl']
|
qemu_args += ['-display', 'sdl']
|
||||||
else:
|
else:
|
||||||
@@ -293,6 +325,12 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
# Launch QEMU!
|
# Launch QEMU!
|
||||||
if not options.bg_mode:
|
if not options.bg_mode:
|
||||||
qemu_args += ['-serial', 'mon:stdio']
|
qemu_args += ['-serial', 'mon:stdio']
|
||||||
|
|
||||||
|
# Adding qemu_extra_args at the end ensures the monitor is the
|
||||||
|
# primary serial port if another -serial argument is present.
|
||||||
|
if qemu_extra_args:
|
||||||
|
qemu_args += shlex.split(qemu_extra_args)
|
||||||
|
|
||||||
yellow_print('Running qemu (fg): ' + ' '.join(qemu_args))
|
yellow_print('Running qemu (fg): ' + ' '.join(qemu_args))
|
||||||
subprocess.run(qemu_args)
|
subprocess.run(qemu_args)
|
||||||
else:
|
else:
|
||||||
@@ -301,14 +339,22 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
else:
|
else:
|
||||||
qemu_args += ['-serial', f'tcp::{QEMU_PORT_SERIAL},server,nowait']
|
qemu_args += ['-serial', f'tcp::{QEMU_PORT_SERIAL},server,nowait']
|
||||||
|
|
||||||
|
# Adding qemu_extra_args at the end ensures the monitor is the
|
||||||
|
# primary serial port if another -serial argument is present.
|
||||||
|
if qemu_extra_args:
|
||||||
|
qemu_args += shlex.split(qemu_extra_args)
|
||||||
|
|
||||||
yellow_print('Running qemu (bg): ' + ' '.join(qemu_args))
|
yellow_print('Running qemu (bg): ' + ' '.join(qemu_args))
|
||||||
qemu_proc = subprocess.Popen(qemu_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
|
qemu_proc = subprocess.Popen(
|
||||||
|
qemu_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE
|
||||||
|
)
|
||||||
wait_for_socket(QEMU_PORT_SERIAL)
|
wait_for_socket(QEMU_PORT_SERIAL)
|
||||||
|
|
||||||
def cleanup_qemu() -> None:
|
def cleanup_qemu() -> None:
|
||||||
if qemu_proc:
|
if qemu_proc:
|
||||||
qemu_proc.terminate()
|
qemu_proc.terminate()
|
||||||
qemu_proc.wait()
|
qemu_proc.wait()
|
||||||
|
|
||||||
atexit.register(cleanup_qemu)
|
atexit.register(cleanup_qemu)
|
||||||
if qemu_proc.poll() is not None:
|
if qemu_proc.poll() is not None:
|
||||||
yellow_print('QEMU exited with error')
|
yellow_print('QEMU exited with error')
|
||||||
@@ -337,9 +383,11 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'names': ['-d', '--gdb'],
|
'names': ['-d', '--gdb'],
|
||||||
'help': ('Wait for gdb to connect. '
|
'help': (
|
||||||
|
'Wait for gdb to connect. '
|
||||||
'Use this option to run "idf.py qemu --gdb monitor" in one terminal window '
|
'Use this option to run "idf.py qemu --gdb monitor" in one terminal window '
|
||||||
'and "idf.py gdb" in another. The program will start running when gdb connects.'),
|
'and "idf.py gdb" in another. The program will start running when gdb connects.'
|
||||||
|
),
|
||||||
'is_flag': True,
|
'is_flag': True,
|
||||||
'default': False,
|
'default': False,
|
||||||
},
|
},
|
||||||
@@ -351,20 +399,24 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'names': ['--efuse-file'],
|
'names': ['--efuse-file'],
|
||||||
'help': ('File used to store efuse values. If not specified, qemu_efuse.bin file '
|
'help': (
|
||||||
'in build directory is used.'),
|
'File used to store efuse values. If not specified, qemu_efuse.bin file '
|
||||||
|
'in build directory is used.'
|
||||||
|
),
|
||||||
'is_flag': False,
|
'is_flag': False,
|
||||||
'default': '',
|
'default': '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'names': ['--flash-file'],
|
'names': ['--flash-file'],
|
||||||
'help': ('File used as the qemu flash image. If not specified, qemu_flash.bin file '
|
'help': (
|
||||||
'in build directory is used.'),
|
'File used as the qemu flash image. If not specified, qemu_flash.bin file '
|
||||||
|
'in build directory is used.'
|
||||||
|
),
|
||||||
'is_flag': False,
|
'is_flag': False,
|
||||||
'default': '',
|
'default': '',
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
]
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return qemu_actions
|
return qemu_actions
|
||||||
|
Reference in New Issue
Block a user