mirror of
https://github.com/espressif/esptool.git
synced 2025-10-21 23:30:34 +08:00
feat: Recover from serial errors when flashing
Closes https://github.com/espressif/esptool/issues/182
This commit is contained in:
@@ -73,6 +73,7 @@ ERASE_WRITE_TIMEOUT_PER_MB = 40 # timeout (per megabyte) for erasing and writin
|
|||||||
MEM_END_ROM_TIMEOUT = 0.05 # short timeout for ESP_MEM_END, as it may never respond
|
MEM_END_ROM_TIMEOUT = 0.05 # short timeout for ESP_MEM_END, as it may never respond
|
||||||
DEFAULT_SERIAL_WRITE_TIMEOUT = 10 # timeout for serial port write
|
DEFAULT_SERIAL_WRITE_TIMEOUT = 10 # timeout for serial port write
|
||||||
DEFAULT_CONNECT_ATTEMPTS = 7 # default number of times to try connection
|
DEFAULT_CONNECT_ATTEMPTS = 7 # default number of times to try connection
|
||||||
|
WRITE_BLOCK_ATTEMPTS = 3 # number of times to try writing a data block
|
||||||
|
|
||||||
STUBS_DIR = os.path.join(os.path.dirname(__file__), "./targets/stub_flasher/")
|
STUBS_DIR = os.path.join(os.path.dirname(__file__), "./targets/stub_flasher/")
|
||||||
|
|
||||||
@@ -803,29 +804,51 @@ class ESPLoader(object):
|
|||||||
return num_blocks
|
return num_blocks
|
||||||
|
|
||||||
def flash_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
|
def flash_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
|
||||||
"""Write block to flash"""
|
"""Write block to flash, retry if fail"""
|
||||||
self.check_command(
|
for attempts_left in range(WRITE_BLOCK_ATTEMPTS - 1, -1, -1):
|
||||||
"write to target Flash after seq %d" % seq,
|
try:
|
||||||
self.ESP_FLASH_DATA,
|
self.check_command(
|
||||||
struct.pack("<IIII", len(data), seq, 0, 0) + data,
|
"write to target Flash after seq %d" % seq,
|
||||||
self.checksum(data),
|
self.ESP_FLASH_DATA,
|
||||||
timeout=timeout,
|
struct.pack("<IIII", len(data), seq, 0, 0) + data,
|
||||||
)
|
self.checksum(data),
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
except FatalError:
|
||||||
|
if attempts_left:
|
||||||
|
self.trace(
|
||||||
|
"Block write failed, "
|
||||||
|
f"retrying with {attempts_left} attempts left"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
def flash_encrypt_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
|
def flash_encrypt_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
|
||||||
"""Encrypt before writing to flash"""
|
"""Encrypt, write block to flash, retry if fail"""
|
||||||
if self.SUPPORTS_ENCRYPTED_FLASH and not self.IS_STUB:
|
if self.SUPPORTS_ENCRYPTED_FLASH and not self.IS_STUB:
|
||||||
# ROM support performs the encrypted writes via the normal write command,
|
# ROM support performs the encrypted writes via the normal write command,
|
||||||
# triggered by flash_begin(begin_rom_encrypted=True)
|
# triggered by flash_begin(begin_rom_encrypted=True)
|
||||||
return self.flash_block(data, seq, timeout)
|
return self.flash_block(data, seq, timeout)
|
||||||
|
|
||||||
self.check_command(
|
for attempts_left in range(WRITE_BLOCK_ATTEMPTS - 1, -1, -1):
|
||||||
"Write encrypted to target Flash after seq %d" % seq,
|
try:
|
||||||
self.ESP_FLASH_ENCRYPT_DATA,
|
self.check_command(
|
||||||
struct.pack("<IIII", len(data), seq, 0, 0) + data,
|
"Write encrypted to target Flash after seq %d" % seq,
|
||||||
self.checksum(data),
|
self.ESP_FLASH_ENCRYPT_DATA,
|
||||||
timeout=timeout,
|
struct.pack("<IIII", len(data), seq, 0, 0) + data,
|
||||||
)
|
self.checksum(data),
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
except FatalError:
|
||||||
|
if attempts_left:
|
||||||
|
self.trace(
|
||||||
|
"Encrypted block write failed, "
|
||||||
|
f"retrying with {attempts_left} attempts left"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
def flash_finish(self, reboot=False):
|
def flash_finish(self, reboot=False):
|
||||||
"""Leave flash mode and run/reboot"""
|
"""Leave flash mode and run/reboot"""
|
||||||
@@ -959,14 +982,25 @@ class ESPLoader(object):
|
|||||||
|
|
||||||
@stub_and_esp32_function_only
|
@stub_and_esp32_function_only
|
||||||
def flash_defl_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
|
def flash_defl_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
|
||||||
"""Write block to flash, send compressed"""
|
"""Write block to flash, send compressed, retry if fail"""
|
||||||
self.check_command(
|
for attempts_left in range(WRITE_BLOCK_ATTEMPTS - 1, -1, -1):
|
||||||
"write compressed data to flash after seq %d" % seq,
|
try:
|
||||||
self.ESP_FLASH_DEFL_DATA,
|
self.check_command(
|
||||||
struct.pack("<IIII", len(data), seq, 0, 0) + data,
|
"write compressed data to flash after seq %d" % seq,
|
||||||
self.checksum(data),
|
self.ESP_FLASH_DEFL_DATA,
|
||||||
timeout=timeout,
|
struct.pack("<IIII", len(data), seq, 0, 0) + data,
|
||||||
)
|
self.checksum(data),
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
except FatalError:
|
||||||
|
if attempts_left:
|
||||||
|
self.trace(
|
||||||
|
"Compressed block write failed, "
|
||||||
|
f"retrying with {attempts_left} attempts left"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
@stub_and_esp32_function_only
|
@stub_and_esp32_function_only
|
||||||
def flash_defl_finish(self, reboot=False):
|
def flash_defl_finish(self, reboot=False):
|
||||||
|
Reference in New Issue
Block a user