diff --git a/tcl/target/esp_common.cfg b/tcl/target/esp_common.cfg index a1b55f4e6..3947b9430 100644 --- a/tcl/target/esp_common.cfg +++ b/tcl/target/esp_common.cfg @@ -396,6 +396,8 @@ proc esp_gcov_dump {} { # special function to program ESP chip, it differs from the original 'program' that # it verifies written image by reading flash directly, instead of reading memory mapped flash regions proc program_esp {filename args} { + global _FLASH_VOLTAGE + set exit 0 set compress 0 set clock_boost 1 @@ -443,6 +445,28 @@ proc program_esp {filename args} { program_error "** OpenOCD init failed **" 1 } + if { [info exists _FLASH_VOLTAGE] } { + foreach tgt [target names] { + set state [$tgt curstate] + if {$state eq "running"} { + # When the flash is empty, the TDI pin remains floating and may be sampled at an incorrect level by the + # bootstrap circuit. This can cause the flash to operate at an unexpected voltage. + # To address this, we ensure the TDI pin is set to the correct level before re-sampling the bootstrap + # registers. OpenOCD will poll once to adjust the TDI level and then wait for the target to undergo a + # WDT reset, which triggers re-sampling of the bootstrap pin. + # The observed interval between two WDT resets is approximately 350ms. + # This workaround is applied while the target is running because a WDT reset is the only way + # to force the target to re-sample the bootstrap pin. + # Additionally, if the flash is empty, the CPU will not be able to load firmware, which guarantees that + # the watchdog timer will be triggerred continuously, causing resets + # until the firmware is properly loaded. + poll + sleep 350 + break + } + } + } + # reset target and call any init scripts if {[catch {reset init}] != 0} { program_error "** Unable to reset target **" $exit