@@ -291,9 +291,6 @@ class ESPLoader(object):
291291 IROM_MAP_START = 0x40200000
292292 IROM_MAP_END = 0x40300000
293293
294- # The number of bytes in the UART response that signify command status
295- STATUS_BYTES_LENGTH = 4
296-
297294 # Bootloader flashing offset
298295 BOOTLOADER_FLASH_OFFSET = 0x0
299296
@@ -518,36 +515,54 @@ def command(
518515 raise FatalError ("Response doesn't match request." )
519516
520517 def check_command (
521- self , op_description , op = None , data = b"" , chk = 0 , timeout = DEFAULT_TIMEOUT
518+ self ,
519+ op_description ,
520+ op = None ,
521+ data = b"" ,
522+ chk = 0 ,
523+ resp_data_len = 0 ,
524+ timeout = DEFAULT_TIMEOUT ,
522525 ):
523526 """
524527 Execute a command with 'command', check the result code and throw an appropriate
525528 FatalError if it fails.
526529
527530 Returns the "result" of a successful command.
528531 """
529- val , data = self .command (op , data , chk , timeout = timeout )
530532
531- # things are a bit weird here, bear with us
533+ # The status bytes are first two bytes after the expected response data,
534+ # ROM bootloaders of the chips (except ESP8266) return another 2 bytes,
535+ # which are reserved for future use, these are ignored here.
536+ STATUS_BYTES_LENGTH = 2
532537
533- # the status bytes are the last 2/4 bytes in the data (depending on chip)
534- if len (data ) < self .STATUS_BYTES_LENGTH :
535- raise FatalError (
536- f"Failed to { op_description } . "
537- f"Only got { len (data )} byte status response."
538- )
539- status_bytes = data [- self .STATUS_BYTES_LENGTH :]
540- # only care if the first one is non-zero. If it is, the second byte is a reason.
541- if byte (status_bytes , 0 ) != 0 :
538+ # Execute the command and get the result
539+ val , data = self .command (op , data , chk , timeout = timeout )
540+
541+ # Check if we have enough data,
542+ # including the expected response data and status bytes
543+ if len (data ) < resp_data_len + STATUS_BYTES_LENGTH :
544+ # If we don't have enough data, check the first 2 bytes as status
545+ status_bytes = data [0 :2 ]
546+ # Only care if the first byte is non-zero.
547+ # If it is, the second byte is a reason.
548+ if status_bytes [0 ] != 0 :
549+ raise FatalError .WithResult (f"Failed to { op_description } " , status_bytes )
550+ else :
551+ raise FatalError (
552+ f"Failed to { op_description } . "
553+ f"Only got { len (data )} byte status response."
554+ )
555+ # The status bytes are positioned after the expected response data
556+ # (first two bytes after resp_data_len are the status bytes)
557+ status_bytes = data [resp_data_len : resp_data_len + STATUS_BYTES_LENGTH ]
558+ # Only care if the first byte is non-zero.
559+ # If it is, the second byte is a reason.
560+ if status_bytes [0 ] != 0 :
542561 raise FatalError .WithResult (f"Failed to { op_description } " , status_bytes )
543562
544- # if we had more data than just the status bytes, return it as the result
545- # (this is used by the md5sum command, maybe other commands?)
546- if len (data ) > self .STATUS_BYTES_LENGTH :
547- return data [: - self .STATUS_BYTES_LENGTH ]
563+ if resp_data_len > 0 :
564+ return data [:resp_data_len ]
548565 else :
549- # otherwise, just return the 'val' field which comes from the reply header
550- # (this is used by read_reg)
551566 return val
552567
553568 def flush_input (self ):
@@ -856,17 +871,10 @@ def _post_connect(self):
856871
857872 def read_reg (self , addr , timeout = DEFAULT_TIMEOUT ):
858873 """Read memory address in target"""
859- # we don't call check_command here because read_reg() function is called
860- # when detecting chip type, and the way we check for success
861- # (STATUS_BYTES_LENGTH) is different for different chip types (!)
862- val , data = self .command (
863- self .ESP_CMDS ["READ_REG" ], struct .pack ("<I" , addr ), timeout = timeout
874+ command = struct .pack ("<I" , addr )
875+ return self .check_command (
876+ "read target memory" , self .ESP_CMDS ["READ_REG" ], command , timeout = timeout
864877 )
865- if byte (data , 0 ) != 0 :
866- raise FatalError .WithResult (
867- "Failed to read register address %08x" % addr , data
868- )
869- return val
870878
871879 def write_reg (self , addr , value , mask = 0xFFFFFFFF , delay_us = 0 , delay_after_us = 0 ):
872880 """Write to memory address in target"""
@@ -1099,11 +1107,25 @@ def parse_security_flags(flags_value):
10991107 parsed_flags [flag_name ] = (flags_value & flag_mask ) != 0
11001108 return parsed_flags
11011109
1102- res = self .check_command (
1103- "get security info" , self .ESP_CMDS ["GET_SECURITY_INFO" ], b""
1104- )
1105- esp32s2 = True if len (res ) == 12 else False
1106- res = struct .unpack ("<IBBBBBBBB" if esp32s2 else "<IBBBBBBBBII" , res )
1110+ # Try with 20 bytes first (most chips), fall back to 12 bytes (ESP32-S2)
1111+ try :
1112+ res = self .check_command (
1113+ "get security info" ,
1114+ self .ESP_CMDS ["GET_SECURITY_INFO" ],
1115+ b"" ,
1116+ resp_data_len = 20 ,
1117+ )
1118+ res = struct .unpack ("<IBBBBBBBBII" , res )
1119+ esp32s2 = False
1120+ except FatalError :
1121+ res = self .check_command (
1122+ "get security info" ,
1123+ self .ESP_CMDS ["GET_SECURITY_INFO" ],
1124+ b"" ,
1125+ resp_data_len = 12 ,
1126+ )
1127+ res = struct .unpack ("<IBBBBBBBB" , res )
1128+ esp32s2 = True
11071129
11081130 security_info = {
11091131 "flags" : res [0 ],
@@ -1347,20 +1369,21 @@ def flash_defl_finish(self, reboot=False):
13471369 def flash_md5sum (self , addr , size ):
13481370 # the MD5 command returns additional bytes in the standard
13491371 # command reply slot
1372+ RESP_DATA_LEN = 32
1373+ RESP_DATA_LEN_STUB = 16
13501374 timeout = timeout_per_mb (MD5_TIMEOUT_PER_MB , size )
13511375 res = self .check_command (
13521376 "calculate md5sum" ,
13531377 self .ESP_CMDS ["SPI_FLASH_MD5" ],
13541378 struct .pack ("<IIII" , addr , size , 0 , 0 ),
1379+ resp_data_len = RESP_DATA_LEN_STUB if self .IS_STUB else RESP_DATA_LEN ,
13551380 timeout = timeout ,
13561381 )
13571382
1358- if len ( res ) == 32 :
1383+ if not self . IS_STUB :
13591384 return res .decode ("utf-8" ) # already hex formatted
1360- elif len (res ) == 16 :
1361- return hexify (res ).lower ()
13621385 else :
1363- raise FatalError ( "MD5Sum command returned unexpected result: %r" % res )
1386+ return hexify ( res ). lower ( )
13641387
13651388 @stub_and_esp32_function_only
13661389 def change_baud (self , baud ):
@@ -1756,7 +1779,6 @@ class StubMixin:
17561779 """
17571780
17581781 FLASH_WRITE_SIZE = 0x4000 # Default value, can be overridden
1759- STATUS_BYTES_LENGTH = 2
17601782 IS_STUB = True
17611783
17621784 def __init__ (self , rom_loader ):
0 commit comments