Skip to content

Commit

Permalink
feat(hard_reset): Support custom hard reset sequence configuration
Browse files Browse the repository at this point in the history
Closes #1004
  • Loading branch information
radimkarnis authored and dobairoland committed Oct 18, 2024
1 parent 6abd05d commit 1b15738
Show file tree
Hide file tree
Showing 9 changed files with 33 additions and 17 deletions.
19 changes: 16 additions & 3 deletions docs/en/esptool/configuration-file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,19 @@ Complete list of configurable options:
+------------------------------+-----------------------------------------------------------+----------+
| custom_reset_sequence | Custom reset sequence for resetting into the bootloader | |
+------------------------------+-----------------------------------------------------------+----------+
| custom_hard_reset_sequence | Custom reset sequence for hard resetting the chip | |
+------------------------------+-----------------------------------------------------------+----------+

Custom Reset Sequence
---------------------
Custom Reset Sequences
----------------------

The ``custom_reset_sequence`` configuration option allows you to define a reset sequence which will get
used when an :ref:`automatic reset into the serial bootloader <automatic-bootloader>` is performed.

The sequence is defined with a string in the following format:
The ``custom_hard_reset_sequence`` option allows you to define a reset sequence which will get
used when a hard reset (a reset out of the bootloader) is performed.

A 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``).
Expand Down Expand Up @@ -148,3 +153,11 @@ For example: ``D0|R1|W0.1|D1|R0|W0.5|D0`` represents the following classic reset
_setRTS(False) # EN=HIGH, chip out of reset
time.sleep(0.05)
_setDTR(False) # IO0=HIGH, done
Similarly, ``R1|W0.1|R0`` represents the classic hard reset sequence:

.. code-block:: python
_setRTS(True) # EN=LOW, chip in reset
time.sleep(0.1)
_setRTS(False) # EN=HIGH, chip out of reset
6 changes: 5 additions & 1 deletion esp_rfc2217_server/esp_port_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ def _hard_reset_thread(self):
"""
if self.logger:
self.logger.info("Activating hard reset in thread")
HardReset(self.serial)()
cfg_custom_hard_reset_sequence = cfg.get("custom_hard_reset_sequence")
if cfg_custom_hard_reset_sequence is not None:
CustomReset(self.serial, cfg_custom_hard_reset_sequence)()
else:
HardReset(self.serial)()

def _reset_thread(self):
"""
Expand Down
1 change: 1 addition & 0 deletions esptool/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"reset_delay",
"open_port_attempts",
"custom_reset_sequence",
"custom_hard_reset_sequence",
]


Expand Down
8 changes: 6 additions & 2 deletions esptool/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1525,9 +1525,13 @@ def get_crystal_freq(self):
)
return norm_xtal

def hard_reset(self):
def hard_reset(self, uses_usb=False):
print("Hard resetting via RTS pin...")
HardReset(self._port)()
cfg_custom_hard_reset_sequence = cfg.get("custom_hard_reset_sequence")
if cfg_custom_hard_reset_sequence is not None:
CustomReset(self._port, cfg_custom_hard_reset_sequence)()
else:
HardReset(self._port, uses_usb)()

def soft_reset(self, stay_in_bootloader):
if not self.IS_STUB:
Expand Down
2 changes: 1 addition & 1 deletion esptool/reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,5 @@ def _parse_string_to_seq(self, seq_str):
cmds = seq_str.split("|")
fn_calls_list = [self.format_dict[cmd[0]].format(cmd[1:]) for cmd in cmds]
except Exception as e:
raise FatalError(f'Invalid "custom_reset_sequence" option format: {e}')
raise FatalError(f"Invalid custom reset sequence option format: {e}")
return "\n".join(fn_calls_list)
4 changes: 1 addition & 3 deletions esptool/targets/esp32c5.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from .esp32c6 import ESP32C6ROM
from ..loader import ESPLoader
from ..reset import HardReset
from ..util import FatalError


Expand Down Expand Up @@ -128,8 +127,7 @@ def get_crystal_freq_rom_expect(self):
) >> self.PCR_SYSCLK_XTAL_FREQ_S

def hard_reset(self):
print("Hard resetting via RTS pin...")
HardReset(self._port, self.uses_usb_jtag_serial())()
ESPLoader.hard_reset(self, self.uses_usb_jtag_serial())

def change_baud(self, baud):
if not self.IS_STUB:
Expand Down
4 changes: 1 addition & 3 deletions esptool/targets/esp32s2.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from .esp32 import ESP32ROM
from ..loader import ESPLoader
from ..reset import HardReset
from ..util import FatalError, NotImplementedInROMError


Expand Down Expand Up @@ -310,8 +309,7 @@ def hard_reset(self):
if uses_usb_otg:
self._check_if_can_reset()

print("Hard resetting via RTS pin...")
HardReset(self._port, uses_usb_otg)()
ESPLoader.hard_reset(self, uses_usb_otg)

def change_baud(self, baud):
ESPLoader.change_baud(self, baud)
Expand Down
4 changes: 1 addition & 3 deletions esptool/targets/esp32s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from .esp32 import ESP32ROM
from ..loader import ESPLoader
from ..reset import HardReset
from ..util import FatalError, NotImplementedInROMError


Expand Down Expand Up @@ -382,8 +381,7 @@ def hard_reset(self):
# Skip if response was not valid and proceed to reset; e.g. when monitoring while resetting
pass

print("Hard resetting via RTS pin...")
HardReset(self._port, uses_usb_otg)()
ESPLoader.hard_reset(self, uses_usb_otg)

def change_baud(self, baud):
ESPLoader.change_baud(self, baud)
Expand Down
2 changes: 1 addition & 1 deletion test/test_esptool.py
Original file line number Diff line number Diff line change
Expand Up @@ -1604,7 +1604,7 @@ def test_custom_reset_sequence(self):
with self.ConfigFile(config_file_path, invalid_reset_seq_config):
output = self.run_esptool_error("flash_id")
assert f"Loaded custom configuration from {config_file_path}" in output
assert 'Invalid "custom_reset_sequence" option format:' in output
assert "Invalid custom reset sequence option format:" in output

def test_open_port_attempts(self):
# Test that the open_port_attempts option is loaded correctly
Expand Down

0 comments on commit 1b15738

Please sign in to comment.