@@ -291,9 +291,6 @@ class ESPLoader(object):
291
291
IROM_MAP_START = 0x40200000
292
292
IROM_MAP_END = 0x40300000
293
293
294
- # The number of bytes in the UART response that signify command status
295
- STATUS_BYTES_LENGTH = 4
296
-
297
294
# Bootloader flashing offset
298
295
BOOTLOADER_FLASH_OFFSET = 0x0
299
296
@@ -518,36 +515,54 @@ def command(
518
515
raise FatalError ("Response doesn't match request." )
519
516
520
517
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 ,
522
525
):
523
526
"""
524
527
Execute a command with 'command', check the result code and throw an appropriate
525
528
FatalError if it fails.
526
529
527
530
Returns the "result" of a successful command.
528
531
"""
529
- val , data = self .command (op , data , chk , timeout = timeout )
530
532
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
532
537
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 :
542
561
raise FatalError .WithResult (f"Failed to { op_description } " , status_bytes )
543
562
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 ]
548
565
else :
549
- # otherwise, just return the 'val' field which comes from the reply header
550
- # (this is used by read_reg)
551
566
return val
552
567
553
568
def flush_input (self ):
@@ -856,17 +871,10 @@ def _post_connect(self):
856
871
857
872
def read_reg (self , addr , timeout = DEFAULT_TIMEOUT ):
858
873
"""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
864
877
)
865
- if byte (data , 0 ) != 0 :
866
- raise FatalError .WithResult (
867
- "Failed to read register address %08x" % addr , data
868
- )
869
- return val
870
878
871
879
def write_reg (self , addr , value , mask = 0xFFFFFFFF , delay_us = 0 , delay_after_us = 0 ):
872
880
"""Write to memory address in target"""
@@ -1099,11 +1107,25 @@ def parse_security_flags(flags_value):
1099
1107
parsed_flags [flag_name ] = (flags_value & flag_mask ) != 0
1100
1108
return parsed_flags
1101
1109
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
1107
1129
1108
1130
security_info = {
1109
1131
"flags" : res [0 ],
@@ -1347,20 +1369,21 @@ def flash_defl_finish(self, reboot=False):
1347
1369
def flash_md5sum (self , addr , size ):
1348
1370
# the MD5 command returns additional bytes in the standard
1349
1371
# command reply slot
1372
+ RESP_DATA_LEN = 32
1373
+ RESP_DATA_LEN_STUB = 16
1350
1374
timeout = timeout_per_mb (MD5_TIMEOUT_PER_MB , size )
1351
1375
res = self .check_command (
1352
1376
"calculate md5sum" ,
1353
1377
self .ESP_CMDS ["SPI_FLASH_MD5" ],
1354
1378
struct .pack ("<IIII" , addr , size , 0 , 0 ),
1379
+ resp_data_len = RESP_DATA_LEN_STUB if self .IS_STUB else RESP_DATA_LEN ,
1355
1380
timeout = timeout ,
1356
1381
)
1357
1382
1358
- if len ( res ) == 32 :
1383
+ if not self . IS_STUB :
1359
1384
return res .decode ("utf-8" ) # already hex formatted
1360
- elif len (res ) == 16 :
1361
- return hexify (res ).lower ()
1362
1385
else :
1363
- raise FatalError ( "MD5Sum command returned unexpected result: %r" % res )
1386
+ return hexify ( res ). lower ( )
1364
1387
1365
1388
@stub_and_esp32_function_only
1366
1389
def change_baud (self , baud ):
@@ -1756,7 +1779,6 @@ class StubMixin:
1756
1779
"""
1757
1780
1758
1781
FLASH_WRITE_SIZE = 0x4000 # Default value, can be overridden
1759
- STATUS_BYTES_LENGTH = 2
1760
1782
IS_STUB = True
1761
1783
1762
1784
def __init__ (self , rom_loader ):
0 commit comments