diff --git a/tools/idf_monitor.py b/tools/idf_monitor.py index 46ae347615..3afe78152d 100755 --- a/tools/idf_monitor.py +++ b/tools/idf_monitor.py @@ -9,7 +9,7 @@ # - If core dump output is detected, it is converted to a human-readable report # by espcoredump.py. # -# SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 # # Contains elements taken from miniterm "Very simple serial terminal" which @@ -33,7 +33,6 @@ from builtins import bytes from typing import Any, List, Optional, Type, Union import serial -import serial.tools.list_ports # Windows console stuff from idf_monitor_base.ansi_color_converter import get_ansi_converter from idf_monitor_base.argument_parser import get_parser @@ -53,7 +52,7 @@ from idf_monitor_base.output_helpers import normal_print, yellow_print from idf_monitor_base.serial_handler import SerialHandler, SerialHandlerNoElf, run_make from idf_monitor_base.serial_reader import LinuxReader, SerialReader from idf_monitor_base.web_socket_client import WebSocketClient -from serial.tools import miniterm +from serial.tools import list_ports, miniterm key_description = miniterm.key_description @@ -291,6 +290,21 @@ def main() -> None: # avoid the modification of args.port. port = args.port + # if no port was set, detect connected ports and use one of them + if port is None: + try: + port_list = list_ports.comports() + port = port_list[-1].device + # keep the `/dev/ttyUSB0` default port on linux if connected + if sys.platform == 'linux': + for p in port_list: + if p.device == '/dev/ttyUSB0': + port = p.device + break + yellow_print(f'--- Using autodetected port {port}') + except IndexError: + sys.exit('No serial ports detected.') + # GDB uses CreateFile to open COM port, which requires the COM name to be r'\\.\COMx' if the COM # number is larger than 10 if os.name == 'nt' and port.startswith('COM'): diff --git a/tools/idf_monitor_base/argument_parser.py b/tools/idf_monitor_base/argument_parser.py index c92beccbbd..a47bc48bfd 100644 --- a/tools/idf_monitor_base/argument_parser.py +++ b/tools/idf_monitor_base/argument_parser.py @@ -1,8 +1,9 @@ -# SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import argparse import os +import sys from .constants import DEFAULT_PRINT_FILTER, DEFAULT_TOOLCHAIN_PREFIX, PANIC_DECODE_BACKTRACE, PANIC_DECODE_DISABLE from .coredump import COREDUMP_DECODE_DISABLE, COREDUMP_DECODE_INFO @@ -13,8 +14,9 @@ def get_parser(): # type: () -> argparse.ArgumentParser parser.add_argument( '--port', '-p', - help='Serial port device', - default=os.environ.get('ESPTOOL_PORT', '/dev/ttyUSB0') + help='Serial port device. If not set, a connected port will be used.' + + (' Defaults to `/dev/ttyUSB0` if connected.' if sys.platform == 'linux' else ''), + default=os.environ.get('ESPTOOL_PORT', None) ) parser.add_argument( diff --git a/tools/idf_monitor_base/serial_reader.py b/tools/idf_monitor_base/serial_reader.py index eca3c22d02..28a57d2a4f 100644 --- a/tools/idf_monitor_base/serial_reader.py +++ b/tools/idf_monitor_base/serial_reader.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import queue @@ -7,6 +7,7 @@ import sys import time import serial +from serial.tools import list_ports from .constants import CHECK_ALIVE_FLAG_TIMEOUT, MINIMAL_EN_LOW_DELAY, RECONNECT_DELAY, TAG_SERIAL from .output_helpers import red_print, yellow_print @@ -49,7 +50,13 @@ class SerialReader(Reader): self.serial.rts = high # IO0=HIGH self.serial.dtr = self.serial.dtr # usbser.sys workaround # Current state not reset the target! - self.serial.open() + try: + self.serial.open() + except serial.serialutil.SerialException: + # if connection to port fails suggest other available ports + port_list = '\n'.join([p.device for p in list_ports.comports()]) + yellow_print(f'Connection to {self.serial.portstr} failed. Available ports:\n{port_list}') + return if not self.gdb_exit and self.reset: self.serial.dtr = high # Set dtr to reset state (affected by rts) self.serial.rts = low # Set rts/dtr to the reset state