IDF Monitor uses the esp-idf-monitor_ package as a serial terminal program which relays serial data to and from the target device's serial port. It also provides some ESP-IDF-specific features.
For easy interaction with IDF Monitor, use the keyboard shortcuts given in the table. These keyboard shortcuts can be customized, for more details see `Configuration File`_ section.
- Reset target into bootloader to pause app via RTS and DTR lines
- Resets the target into the bootloader using the RTS and DTR lines (if connected). This stops the board from executing the application, making it useful when waiting for another device to start. For additional details, refer to :ref:`target-reset-into-bootloader`.
- Pauses idf_monitor to run the project``flash``target, then resumes idf_monitor. Any changed source files are recompiled and then re-flashed. Target``encrypted-flash``is run if idf_monitor was started with argument``-E``.
- Pauses idf_monitor to run the``app-flash``target, then resumes idf_monitor. Similar to the``flash`` target, but only the main app is built and re-flashed. Target``encrypted-app-flash``is run if idf_monitor was started with argument``-E``.
- Creates a file in the project directory and the output is written to that file until this is disabled with the same keyboard shortcut (or IDF Monitor exits).
- IDF Monitor can print a timestamp in the beginning of each line. The timestamp format can be changed by the ``--timestamp-format`` command line argument.
- Pauses IDF Monitor and runs GDB_ project debugger to debug the application at runtime. This requires :ref:`CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME` option to be enabled.
Whenever the chip outputs a hexadecimal address that points to executable code, IDF monitor looks up the location in the source code (file name and line number) and prints the location on the next line in yellow.
panic_abort (details=details@entry=0x3fc9a37c "abort() was called at PC 0x42067cd5 on core 0") at /home/marius/esp-idf_2/components/esp_system/panic.c:367
#0 panic_abort (details=details@entry=0x3fc9a37c "abort() was called at PC 0x42067cd5 on core 0") at /home/marius/esp-idf_2/components/esp_system/panic.c:367
#1 0x40386b02 in esp_system_abort (details=details@entry=0x3fc9a37c "abort() was called at PC 0x42067cd5 on core 0") at /home/marius/esp-idf_2/components/esp_system/system_api.c:108
#2 0x403906cc in abort () at /home/marius/esp-idf_2/components/newlib/abort.c:46
#3 0x42067cd8 in __assert_func (file=file@entry=0x3c0937f4 "", line=line@entry=42, func=func@entry=0x3c0937d4 <__func__.8540> "", failedexpr=failedexpr@entry=0x3c0917f8 "") at /builds/idf/crosstool-NG/.build/riscv32-esp-elf/src/newlib/newlib/libc/stdlib/assert.c:62
#4 0x4200729e in app_main () at ../main/iperf_example_main.c:42
#5 0x42086cd6 in main_task (args=<optimized out>) at /home/marius/esp-idf_2/components/freertos/port/port_common.c:133
#6 0x40389f3a in vPortEnterCritical () at /home/marius/esp-idf_2/components/freertos/port/riscv/port.c:129
If an address is not matched in the app source code, IDF monitor also checks the ROM code. Instead of printing the source file name and line number, only the function name followed by ``in ROM`` is displayed::
0x40081656: panic_abort at /Users/espressif/esp-idf/components/esp_system/panic.c:452
0x40085729: esp_system_abort at /Users/espressif/esp-idf/components/esp_system/port/esp_system_chip.c:90
0x4008a7ce: abort at /Users/espressif/esp-idf/components/newlib/abort.c:38
0x40007c69: ets_write_char in ROM
0x40008148: ets_printf in ROM
0x400d51d7: app_main at /Users/espressif/esp-idf/examples/get-started/hello_world/main/hello_world_main.c:49
0x400e31bc: main_task at /Users/espressif/esp-idf/components/freertos/app_startup.c:208 (discriminator 13)
0x40087bc5: vPortTaskWrapper at /Users/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:162
.....
..only:: CONFIG_IDF_TARGET_ARCH_RISCV
If an address is not matched in the app source code, IDF monitor also checks the ROM code. Instead of printing the source file name and line number, only the function name followed by ``in ROM`` is displayed::
abort() was called at PC 0x400481c1 on core 0
0x400481c1: ets_rsa_pss_verify in ROM
Stack dump detected
Core 0 register dump:
MEPC : 0x4038051c RA : 0x40383840 SP : 0x3fc8f6b0 GP : 0x3fc8b000
0x4038051c: panic_abort at /Users/espressif/esp-idf/components/esp_system/panic.c:452
0x40383840: __ubsan_include at /Users/espressif/esp-idf/components/esp_system/ubsan.c:313
The ROM ELF file is automatically loaded from a location based on the ``IDF_PATH`` and ``ESP_ROM_ELF_DIR`` environment variables. This can be overridden by calling ``esp_idf_monitor`` and providing a path to a specific ROM ELF file: ``python -m esp_idf_monitor --rom-elf-file [path to ROM ELF file]``.
Set environment variable ``ESP_MONITOR_DECODE`` to ``0`` or call esp_idf_monitor with specific command line option: ``python -m esp_idf_monitor --disable-address-decoding`` to disable address decoding.
By default, IDF Monitor will reset the target when connecting to it. The reset of the target chip is performed using the DTR and RTS serial lines. To prevent IDF Monitor from automatically resetting the target on connection, call IDF Monitor with the ``--no-reset`` option (e.g., ``idf.py monitor --no-reset``).
The ``--no-reset`` option applies the same behavior even when connecting IDF Monitor to a particular port (e.g., ``idf.py monitor --no-reset -p [PORT]``).
IDF Monitor provides the capability to reset a chip into the bootloader using a pre-defined reset sequence that has been tuned to work in most environments. Additionally, users have the flexibility to set a custom reset sequence, allowing for fine-tuning and adaptability to diverse scenarios.
Using Pre-defined Reset Sequence
--------------------------------
IDF Monitor's default reset sequence is designed to work seamlessly across a wide range of environments. To trigger a reset into the bootloader using the default sequence, no additional configuration is required.
For more advanced users or specific use cases, IDF Monitor supports the configuration of a custom reset sequence using :ref:`configuration-file`. This is particularly useful in extreme edge cases where the default sequence may not suffice.
The sequence is defined with a string in the following format:
- Consists of individual commands divided by ``|`` (e.g. ``R0|D1|W0.5``).
- Commands (e.g. ``R0``) are defined by a code (``R``) and an argument (``0``).
..list-table::
:header-rows:1
:widths:15 50 35
:align:center
* - Code
- Action
- Argument
* - D
- Set DTR control line
-``1``/``0``
* - R
- Set RTS control line
-``1``/``0``
* - U
- Set DTR and RTS control lines at the same time (Unix-like systems only)
-``0,0``/``0,1``/``1,0``/``1,1``
* - W
- Wait for ``N`` seconds (where ``N`` is a float)
- N
Example:
..code-block:: ini
[esp-idf-monitor]
custom_reset_sequence = U0,1|W0.1|D1|R0|W0.5|D0
Refer to `custom reset sequence`_ from Esptool documentation for further details. Please note that ``custom_reset_sequence`` is the only used value from the Esptool configuration, and others will be ignored in IDF Monitor.
Share Configuration Across Tools
--------------------------------
The configuration for the custom reset sequence can be specified in a shared configuration file between IDF Monitor and Esptool. In this case, your configuration file name should be either ``setup.cfg`` or ``tox.ini`` so it would be recognized by both tools.
Example of a shared configuration file:
..code-block:: ini
[esp-idf-monitor]
menu_key = T
skip_menu_key = True
[esptool]
custom_reset_sequence = U0,1|W0.1|D1|R0|W0.5|D0
..note::
When using the ``custom_reset_sequence`` parameter in both the ``[esp-idf-monitor]`` section and the ``[esptool]`` section, the configuration from the ``[esp-idf-monitor]`` section will take precedence in IDF Monitor. Any conflicting configuration in the ``[esptool]`` section will be ignored.
This precedence rule also applies when the configuration is spread across multiple files. The global esp-idf-monitor configuration will take precedence over the local esptool configuration.
GDBStub is a useful runtime debugging feature that runs on the target and connects to the host over the serial port to receive debugging commands. GDBStub supports commands such as reading memory and variables, examining call stack frames etc. Although GDBStub is less versatile than JTAG debugging, it does not require any special hardware (such as a JTAG to USB bridge) as communication is done entirely over the serial port.
A target can be configured to run GDBStub in the background by setting the :ref:`CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME`. GDBStub will run in the background until a ``Ctrl+C`` message is sent over the serial port and causes the GDBStub to break (i.e., stop the execution of) the program, thus allowing GDBStub to handle debugging commands.
Furthermore, the panic handler can be configured to run GDBStub on a crash by setting the :ref:`CONFIG_ESP_SYSTEM_PANIC` to ``GDBStub on panic``. When a crash occurs, GDBStub will output a special string pattern over the serial port to indicate that it is running.
In both cases (i.e., sending the ``Ctrl+C`` message, or receiving the special string pattern), IDF Monitor will automatically launch GDB in order to allow the user to send debugging commands. After GDB exits, the target is reset via the RTS serial line. If this line is not connected, users can reset their target (by pressing the board's Reset button).
IDF monitor can be invoked as ``idf.py monitor --print-filter="xyz"``, where ``--print-filter`` is the parameter for output filtering. The default value is an empty string, which means that everything is printed. Filtering can also be configured using the ``ESP_IDF_MONITOR_PRINT_FILTER`` environment variable.
..note::
When using both the environment variable ``ESP_IDF_MONITOR_PRINT_FILTER`` and the argument ``--print-filter``, the setting from the CLI argument will take precedence.
Restrictions on what to print can be specified as a series of ``<tag>:<log_level>`` items where ``<tag>`` is the tag string and ``<log_level>`` is a character from the set ``{N, E, W, I, D, V, *}`` referring to a level for :doc:`logging <../../api-reference/system/log>`.
For example, ``--print_filter="tag1:W"`` matches and prints only the outputs written with ``ESP_LOGW("tag1", ...)`` or at lower verbosity level, i.e., ``ESP_LOGE("tag1", ...)``. Not specifying a ``<log_level>`` or using ``*`` defaults to a Verbose level.
Use primary logging to disable at compilation the outputs you do not need through the :doc:`logging library <../../api-reference/system/log>`. Output filtering with the IDF monitor is a secondary solution that can be useful for adjusting the filtering options without recompiling the application.
If the last line of the output in your app is not followed by a carriage return, the output filtering might get confused, i.e., the monitor starts to print the line and later finds out that the line should not have been written. This is a known issue and can be avoided by always adding a carriage return (especially when no output follows immediately afterwards).
-``*`` can be used to match any tags. However, the string ``--print_filter="*:I tag1:E"`` with regards to ``tag1`` prints errors only, because the rule for ``tag1`` has a higher priority over the rule for ``*``.
- The default (empty) rule is equivalent to ``*:V`` because matching every tag at the Verbose level or lower means matching everything.
-``"*:N"`` suppresses not only the outputs from logging functions, but also the prints made by ``printf``, etc. To avoid this, use ``*:E`` or a higher verbosity level.
- Rules ``"tag1:V"``, ``"tag1:v"``, ``"tag1:"``, ``"tag1:*"``, and ``"tag1"`` are equivalent.
- Rule ``"tag1:W tag1:E"`` is equivalent to ``"tag1:E"`` because any consequent occurrence of the same tag name overwrites the previous one.
- Rule ``"tag1:I tag2:W"`` only prints ``tag1`` at the Info verbosity level or lower and ``tag2`` at the Warning verbosity level or lower.
- Rule ``"tag1:I tag2:W tag3:N"`` is essentially equivalent to the previous one because ``tag3:N`` specifies that ``tag3`` should not be printed.
-``tag3:N`` in the rule ``"tag1:I tag2:W tag3:N *:V"`` is more meaningful because without ``tag3:N`` the ``tag3`` messages could have been printed; the errors for ``tag1`` and ``tag2`` will be printed at the specified (or lower) verbosity level and everything else will be printed by default.
``esp-idf-monitor`` is using `C0 control codes`_ to interact with the console. Characters from the config file are converted to their C0 control codes. Available characters include the English alphabet (A-Z) and special symbols: ``[``, ``]``, ``\``, ``^``, ``_``.
..warning::
Please note that some characters may not work on all platforms or can be already reserved as a shortcut for something else. Use this feature with caution!
If a configuration file is still not found, the last inspected location is the home directory:
- Linux: ``/home/<user>/``
- MacOS ``/Users/<user>/``
- Windows: ``c:\Users\<user>\``
On Windows, the home directory can be set with the ``HOME`` or ``USERPROFILE`` environment variables. Therefore, the Windows configuration directory location also depends on these.
A different location for the configuration file can be specified with the ``ESP_IDF_MONITOR_CFGFILE`` environment variable, e.g., ``ESP_IDF_MONITOR_CFGFILE = ~/custom_config.cfg``. This overrides the search priorities described above.
``esp-idf-monitor`` will read settings from other usual configuration files if no other configuration file is used. It automatically reads from ``setup.cfg`` or ``tox.ini`` if they exist.
The configuration file is in .ini file format: it must be introduced by an ``[esp-idf-monitor]`` header to be recognized as valid. This section then contains name = value entries. Lines beginning with ``#`` or ``;`` are ignored as comments.
If you encounter any issues while using IDF Monitor, check our `GitHub repository <https://github.com/espressif/esp-idf-monitor/issues>`_ for a list of known issues and their current status. If you come across a problem that hasn't been documented yet, we encourage you to create a new issue report.