@@ -17,12 +17,15 @@ export interface FlashOptions {
1717
1818export interface LoaderOptions {
1919 transport : Transport ;
20+ port : SerialPort ;
2021 baudrate : number ;
2122 terminal ?: IEspLoaderTerminal ;
2223 romBaudrate : number ;
2324 debugLogging ?: boolean ;
2425}
2526
27+ type FlashReadCallback = ( ( packet : Uint8Array , progress : number , totalSize : number ) => void ) | null ;
28+
2629async function magic2Chip ( magic : number ) : Promise < ROM | null > {
2730 switch ( magic ) {
2831 case 0x00f01d83 : {
@@ -86,6 +89,7 @@ export class ESPLoader {
8689 // Only Stub supported commands
8790 ESP_ERASE_FLASH = 0xd0 ;
8891 ESP_ERASE_REGION = 0xd1 ;
92+ ESP_READ_FLASH = 0xd2 ;
8993 ESP_RUN_USER_CODE = 0xd3 ;
9094
9195 ESP_IMAGE_MAGIC = 0xe9 ;
@@ -98,6 +102,7 @@ export class ESPLoader {
98102 ERASE_WRITE_TIMEOUT_PER_MB = 40000 ;
99103 MD5_TIMEOUT_PER_MB = 8000 ;
100104 CHIP_ERASE_TIMEOUT = 120000 ;
105+ FLASH_READ_TIMEOUT = 100000 ;
101106 MAX_TIMEOUT = this . CHIP_ERASE_TIMEOUT * 2 ;
102107
103108 CHIP_DETECT_MAGIC_REG_ADDR = 0x40001000 ;
@@ -112,6 +117,16 @@ export class ESPLoader {
112117 0x18 : "16MB" ,
113118 } ;
114119
120+ DETECTED_FLASH_SIZES_NUM : { [ key : number ] : number } = {
121+ 0x12 : 256 ,
122+ 0x13 : 512 ,
123+ 0x14 : 1024 ,
124+ 0x15 : 2048 ,
125+ 0x16 : 4096 ,
126+ 0x17 : 8192 ,
127+ 0x18 : 16384 ,
128+ } ;
129+
115130 USB_JTAG_SERIAL_PID = 0x1001 ;
116131
117132 chip ! : ROM ;
@@ -140,6 +155,9 @@ export class ESPLoader {
140155 if ( options . debugLogging ) {
141156 this . debugLogging = options . debugLogging ;
142157 }
158+ if ( options . port ) {
159+ this . transport = new Transport ( options . port ) ;
160+ }
143161
144162 this . info ( "esptool.js" ) ;
145163 this . info ( "Serial port " + this . transport . get_info ( ) ) ;
@@ -230,6 +248,26 @@ export class ESPLoader {
230248 }
231249 }
232250
251+ async read_packet ( op : number | null = null , timeout = 3000 ) : Promise < [ number , Uint8Array ] > {
252+ // Check up-to next 100 packets for valid response packet
253+ for ( let i = 0 ; i < 100 ; i ++ ) {
254+ const p = await this . transport . read ( timeout ) ;
255+ const resp = p [ 0 ] ;
256+ const op_ret = p [ 1 ] ;
257+ const val = this . _bytearray_to_int ( p [ 4 ] , p [ 5 ] , p [ 6 ] , p [ 7 ] ) ;
258+ const data = p . slice ( 8 ) ;
259+ if ( resp == 1 ) {
260+ if ( op == null || op_ret == op ) {
261+ return [ val , data ] ;
262+ } else if ( data [ 0 ] != 0 && data [ 1 ] == this . ROM_INVALID_RECV_MSG ) {
263+ await this . flush_input ( ) ;
264+ throw new ESPError ( "unsupported command error" ) ;
265+ }
266+ }
267+ }
268+ throw new ESPError ( "invalid response" ) ;
269+ }
270+
233271 async command (
234272 op : number | null = null ,
235273 data : Uint8Array = new Uint8Array ( 0 ) ,
@@ -259,23 +297,7 @@ export class ESPLoader {
259297 return [ 0 , new Uint8Array ( 0 ) ] ;
260298 }
261299
262- // Check up-to next 100 packets for valid response packet
263- for ( let i = 0 ; i < 100 ; i ++ ) {
264- const p = await this . transport . read ( timeout ) ;
265- const resp = p [ 0 ] ;
266- const op_ret = p [ 1 ] ;
267- const val = this . _bytearray_to_int ( p [ 4 ] , p [ 5 ] , p [ 6 ] , p [ 7 ] ) ;
268- const data = p . slice ( 8 ) ;
269- if ( resp == 1 ) {
270- if ( op == null || op_ret == op ) {
271- return [ val , data ] ;
272- } else if ( data [ 0 ] != 0 && data [ 1 ] == this . ROM_INVALID_RECV_MSG ) {
273- await this . flush_input ( ) ;
274- throw new ESPError ( "unsupported command error" ) ;
275- }
276- }
277- }
278- throw new ESPError ( "invalid response" ) ;
300+ return this . read_packet ( op , timeout ) ;
279301 }
280302
281303 async read_reg ( addr : number , timeout = 3000 ) {
@@ -718,6 +740,38 @@ export class ESPLoader {
718740 return strmd5 ;
719741 }
720742
743+ async read_flash ( addr : number , size : number , onPacketReceived : FlashReadCallback = null ) {
744+ let pkt = this . _appendArray ( this . _int_to_bytearray ( addr ) , this . _int_to_bytearray ( size ) ) ;
745+ pkt = this . _appendArray ( pkt , this . _int_to_bytearray ( 0x1000 ) ) ;
746+ pkt = this . _appendArray ( pkt , this . _int_to_bytearray ( 1024 ) ) ;
747+
748+ const res = await this . check_command ( "read flash" , this . ESP_READ_FLASH , pkt ) ;
749+
750+ if ( res != 0 ) {
751+ throw new ESPError ( "Failed to read memory: " + res ) ;
752+ }
753+
754+ let resp = new Uint8Array ( 0 ) ;
755+ while ( resp . length < size ) {
756+ const packet = await this . transport . read ( this . FLASH_READ_TIMEOUT ) ;
757+
758+ if ( packet instanceof Uint8Array ) {
759+ if ( packet . length > 0 ) {
760+ resp = this . _appendArray ( resp , packet ) ;
761+ await this . transport . write ( this . _int_to_bytearray ( resp . length ) ) ;
762+
763+ if ( onPacketReceived ) {
764+ onPacketReceived ( packet , resp . length , size ) ;
765+ }
766+ }
767+ } else {
768+ throw new ESPError ( "Failed to read memory: " + packet ) ;
769+ }
770+ }
771+
772+ return resp ;
773+ }
774+
721775 async run_stub ( ) {
722776 this . info ( "Uploading stub..." ) ;
723777
@@ -777,8 +831,19 @@ export class ESPLoader {
777831 await this . transport . disconnect ( ) ;
778832 await this . _sleep ( 50 ) ;
779833 await this . transport . connect ( this . baudrate ) ;
834+
835+ /* original code seemed absolutely unreliable. use retries and less sleep */
780836 try {
781- await this . transport . rawRead ( 500 ) ;
837+ let i = 64 ;
838+ while ( i -- ) {
839+ try {
840+ await this . sync ( ) ;
841+ break ;
842+ } catch ( error ) {
843+ this . debug ( ( error as Error ) . message ) ;
844+ }
845+ await this . _sleep ( 10 ) ;
846+ }
782847 } catch ( e ) {
783848 this . debug ( ( e as Error ) . message ) ;
784849 }
@@ -1026,6 +1091,13 @@ export class ESPLoader {
10261091 this . info ( "Detected flash size: " + this . DETECTED_FLASH_SIZES [ flid_lowbyte ] ) ;
10271092 }
10281093
1094+ async get_flash_size ( ) {
1095+ this . debug ( "flash_id" ) ;
1096+ const flashid = await this . read_flash_id ( ) ;
1097+ const flid_lowbyte = ( flashid >> 16 ) & 0xff ;
1098+ return this . DETECTED_FLASH_SIZES_NUM [ flid_lowbyte ] ;
1099+ }
1100+
10291101 async hard_reset ( ) {
10301102 await this . transport . setRTS ( true ) ; // EN->LOW
10311103 await this . _sleep ( 100 ) ;
0 commit comments