]> granicus.if.org Git - esp-idf/commitdiff
idf_monitor: Small fixes (baud rate, EOL, /dev/tty.X on macOS, Ctrl-T on failure)
authorAngus Gratton <angus@espressif.com>
Fri, 17 Mar 2017 10:41:18 +0000 (18:41 +0800)
committerAngus Gratton <angus@espressif.com>
Tue, 21 Mar 2017 08:00:32 +0000 (16:00 +0800)
* "make monitor" not passed the configured baud rate
  Closes #436 https://github.com/espressif/esp-idf/issues/436
* Pass toolchain prefix from sdkconfig into monitor tool
* Allow setting EOL in idf_monitor.py, use CRLF by default
* Detect if /dev/tty.X is used on macOS, warn and replace with /dev/cu.X
* If a build fails or gdb exits, ignore Ctrl-T (allowing Ctrl-T Ctrl-A/F to be same key sequence everywhere)
* Add a note about winpty on Windows
  Ref https://github.com/espressif/esp-idf/commit/02fdf8271de3a6db2ab9d4d6f023c160c84ebdbe#commitcomment-21369196

components/esptool_py/Makefile.projbuild
docs/idf-monitor.rst
tools/idf_monitor.py

index 860e038383039339937a07bd82c3a6b9cb4ac2b4..b35dc11126297f2681363525bfbb1109c174d904 100644 (file)
@@ -83,12 +83,14 @@ endif
 simple_monitor: $(call prereq_if_explicit,%flash)
        $(MONITOR_PYTHON) -m serial.tools.miniterm --rts 0 --dtr 0 --raw $(ESPPORT) $(MONITORBAUD)
 
+MONITOR_OPTS := --baud $(MONITORBAUD) --port $(ESPPORT) --toolchain-prefix $(CONFIG_TOOLPREFIX) --make "$(MAKE)"
+
 monitor: $(call prereq_if_explicit,%flash)
        $(summary) MONITOR
        [ -f $(APP_ELF) ] || echo "*** 'make monitor' target requires an app to be compiled and flashed first."
        [ -f $(APP_ELF) ] || echo "*** Run 'make flash monitor' to build, flash and monitor"
        [ -f $(APP_ELF) ] || echo "*** Or alternatively 'make simple_monitor' to view the serial port as-is."
        [ -f $(APP_ELF) ] || exit 1
-       $(MONITOR_PYTHON) $(IDF_PATH)/tools/idf_monitor.py --port $(ESPPORT) --make "$(MAKE)" $(APP_ELF)
+       $(MONITOR_PYTHON) $(IDF_PATH)/tools/idf_monitor.py $(MONITOR_OPTS) $(APP_ELF)
 
 .PHONY: erase_flash
index a0a2c5cba69acc85b35476f5352313010d7ce2d0..61dfd0afd3136d3213fa229be2599af0db65bc1b 100644 (file)
@@ -102,6 +102,7 @@ Known Issues with idf_monitor
 Issues Observed on Windows
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+- If you are using the supported Windows environment and receive the error "winpty: command not found" then run ``pacman -S winpty`` to fix.
 - Arrow keys and some other special keys in gdb don't work, due to Windows Console limitations.
 - Occasionally when "make" exits, it may stall for up to 30 seconds before idf_monitor resumes.
 - Occasionally when "gdb" is run, it may stall for a short time before it begins communicating with the gdbstub.
index 0bd5f3368e3d53ea59c8dd2fc04e542a28fe4924..a8ddf77e7962acce9b643a71e34a4cbf3da9a54c 100644 (file)
@@ -70,6 +70,8 @@ TAG_SERIAL = 1
 # regex matches an potential PC value (0x4xxxxxxx)
 MATCH_PCADDR = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE)
 
+DEFAULT_TOOLCHAIN_PREFIX = "xtensa-esp32-elf-"
+
 class StoppableThread(object):
     """
     Provide a Thread-like class which can be 'cancelled' via a subclass-provided
@@ -193,7 +195,7 @@ class Monitor(object):
 
     Main difference is that all event processing happens in the main thread, not the worker threads.
     """
-    def __init__(self, serial_instance, elf_file, make="make"):
+    def __init__(self, serial_instance, elf_file, make="make", toolchain_prefix=DEFAULT_TOOLCHAIN_PREFIX, eol="CRLF"):
         super(Monitor, self).__init__()
         self.event_queue = queue.Queue()
         self.console = miniterm.Console()
@@ -207,9 +209,16 @@ class Monitor(object):
         self.serial_reader = SerialReader(self.serial, self.event_queue)
         self.elf_file = elf_file
         self.make = make
+        self.toolchain_prefix = DEFAULT_TOOLCHAIN_PREFIX
         self.menu_key = CTRL_T
         self.exit_key = CTRL_RBRACKET
 
+        self.translate_eol = {
+            "CRLF": lambda c: c.replace(b"\n", b"\r\n"),
+            "CR":   lambda c: c.replace(b"\n", b"\r"),
+            "LF":   lambda c: c.replace(b"\r", b"\n"),
+        }[eol]
+
         # internal state
         self._pressed_menu_key = False
         self._read_line = b""
@@ -246,6 +255,7 @@ class Monitor(object):
             self.serial_reader.stop()
         else:
             try:
+                key = self.translate_eol(key)
                 self.serial.write(codecs.encode(key))
             except serial.SerialException:
                 pass # this shouldn't happen, but sometimes port has closed in serial thread
@@ -327,7 +337,9 @@ class Monitor(object):
                              .format(key_description(CTRL_A)))
             sys.stderr.write("--- Press any other key to resume monitor (resets target).\n")
             sys.stderr.write(ANSI_NORMAL)
-            k = self.console.getkey()
+            k = CTRL_T  # ignore CTRL-T here, so people can muscle-memory Ctrl-T Ctrl-F, etc.
+            while k == CTRL_T:
+                k = self.console.getkey()
         finally:
             self.console.cleanup()
         if k == self.exit_key:
@@ -350,8 +362,8 @@ class Monitor(object):
 
     def lookup_pc_address(self, pc_addr):
         translation = subprocess.check_output(
-            ["xtensa-esp32-elf-addr2line", "-pfia",
-             "-e", self.elf_file, pc_addr],
+            ["%saddr2line" % self.toolchain_prefix,
+             "-pfia", "-e", self.elf_file, pc_addr],
             cwd=".")
         if not "?? ??:0" in translation:
             sys.stderr.write(ANSI_YELLOW + translation + ANSI_NORMAL)
@@ -375,7 +387,7 @@ class Monitor(object):
         with self:  # disable console control
             sys.stderr.write(ANSI_NORMAL)
             try:
-                subprocess.call(["xtensa-esp32-elf-gdb",
+                subprocess.call(["%sgdb" % self.toolchain_prefix,
                                 "-ex", "set serial baud %d" % self.serial.baudrate,
                                 "-ex", "target remote %s" % self.serial.port,
                                 "-ex", "interrupt",  # monitor has already parsed the first 'reason' command, need a second
@@ -404,12 +416,29 @@ def main():
         help='Command to run make',
         type=str, default='make')
 
+    parser.add_argument(
+        '--toolchain-prefix',
+        help="Triplet prefix to add before cross-toolchain names",
+        default=DEFAULT_TOOLCHAIN_PREFIX)
+
+    parser.add_argument(
+        "--eol",
+        choices=['CR', 'LF', 'CRLF'],
+        type=lambda c: c.upper(),
+        help="End of line to use when sending to the serial port",
+        default='CRLF')
+
     parser.add_argument(
         'elf_file', help='ELF file of application',
         type=argparse.FileType('r'))
 
     args = parser.parse_args()
 
+    if args.port.startswith("/dev/tty."):
+        args.port = args.port.replace("/dev/tty.", "/dev/cu.")
+        sys.stderr.write("WARNING: Serial ports accessed as /dev/tty.* will hang gdb if launched. ")
+        sys.stderr.write("Using %s instead...\n" % args.port)
+
     serial_instance = serial.serial_for_url(args.port, args.baud,
                                             do_not_open=True)
     serial_instance.dtr = False
@@ -428,7 +457,7 @@ def main():
     except KeyError:
         pass  # not running a make jobserver
 
-    monitor = Monitor(serial_instance, args.elf_file.name, args.make)
+    monitor = Monitor(serial_instance, args.elf_file.name, args.make, args.eol)
 
     sys.stderr.write('--- idf_monitor on {p.name} {p.baudrate} ---\n'.format(
         p=serial_instance))