@@ -438,7 +438,7 @@ <h2>Browser support</h2>
438438 monitorConnected : false ,
439439 } ;
440440
441- const PAGE_VERSION = "1.0.8 " ;
441+ const PAGE_VERSION = "1.0.9 " ;
442442 const FLASH_BAUD = 115200 ;
443443 const monitorEncoder = new TextEncoder ( ) ;
444444
@@ -520,8 +520,7 @@ <h2>Browser support</h2>
520520 monitorLog ( `[${ time } ] ${ msg } \n` ) ;
521521 } ;
522522
523- const bufferToBinaryString = ( buffer ) => {
524- const bytes = new Uint8Array ( buffer ) ;
523+ const bytesToBinaryString = ( bytes ) => {
525524 const chunk = 0x8000 ;
526525 let result = "" ;
527526 for ( let i = 0 ; i < bytes . length ; i += chunk ) {
@@ -530,6 +529,19 @@ <h2>Browser support</h2>
530529 return result ;
531530 } ;
532531
532+ const bufferToBinaryString = ( buffer ) => bytesToBinaryString ( new Uint8Array ( buffer ) ) ;
533+
534+ const padBytesTo = ( data , alignment , padCharacter = 0xff ) => {
535+ const bytes = data instanceof Uint8Array ? data : new Uint8Array ( data ) ;
536+ const padMod = bytes . length % alignment ;
537+ if ( padMod === 0 ) return bytes ;
538+ const padding = new Uint8Array ( alignment - padMod ) . fill ( padCharacter ) ;
539+ const padded = new Uint8Array ( bytes . length + padding . length ) ;
540+ padded . set ( bytes , 0 ) ;
541+ padded . set ( padding , bytes . length ) ;
542+ return padded ;
543+ } ;
544+
533545 const resolveManifestPath = ( path ) => {
534546 if ( ! path ) return path ;
535547 try {
@@ -850,11 +862,93 @@ <h2>Browser support</h2>
850862 log ( `Fetching ${ url } @ 0x${ part . offset . toString ( 16 ) } ` ) ;
851863 const { buf, usedUrl } = await resolveAssetUrl ( url ) ;
852864 log ( `Fetched ${ usedUrl } ` ) ;
853- files . push ( { data : bufferToBinaryString ( buf ) , address : part . offset } ) ;
865+ files . push ( { data : bufferToBinaryString ( buf ) , bytes : new Uint8Array ( buf ) , address : part . offset } ) ;
854866 }
855867 return files ;
856868 } ;
857869
870+ const writeFlashViaRom = async ( loader , files , flashOptions ) => {
871+ if ( ! loader ) throw new Error ( "ESP loader is not ready" ) ;
872+
873+ loader . info ( "Using uncompressed ROM flash path for ESP32-C5 to avoid compressed-flash failures." ) ;
874+
875+ if ( flashOptions . flashSize && flashOptions . flashSize !== "keep" ) {
876+ const flashEnd = loader . flashSizeBytes ( flashOptions . flashSize ) ;
877+ for ( let i = 0 ; i < files . length ; i += 1 ) {
878+ const size = files [ i ] ?. bytes ?. length ?? files [ i ] ?. data ?. length ?? 0 ;
879+ if ( size + files [ i ] . address > flashEnd ) {
880+ throw new Error ( `File ${ i + 1 } doesn't fit in the available flash` ) ;
881+ }
882+ }
883+ }
884+
885+ for ( let i = 0 ; i < files . length ; i += 1 ) {
886+ let image = files [ i ] . bytes instanceof Uint8Array
887+ ? new Uint8Array ( files [ i ] . bytes )
888+ : loader . bstrToUi8 ( files [ i ] . data || "" ) ;
889+
890+ if ( image . length === 0 ) continue ;
891+
892+ image = padBytesTo ( image , 4 ) ;
893+ const address = files [ i ] . address ;
894+ image = await loader . _updateImageFlashParams (
895+ image ,
896+ address ,
897+ flashOptions . flashMode ,
898+ flashOptions . flashFreq ,
899+ flashOptions . flashSize ,
900+ ) ;
901+
902+ const calcmd5 = flashOptions . calculateMD5Hash
903+ ? String ( flashOptions . calculateMD5Hash ( bytesToBinaryString ( image ) ) )
904+ : null ;
905+
906+ const totalBytes = image . length ;
907+ const blocks = await loader . flashBegin ( totalBytes , address ) ;
908+ let seq = 0 ;
909+ let imageOffset = 0 ;
910+ let timeout = loader . DEFAULT_TIMEOUT || 3000 ;
911+ if ( flashOptions . reportProgress ) flashOptions . reportProgress ( i , 0 , totalBytes ) ;
912+
913+ const t1 = Date . now ( ) ;
914+ while ( imageOffset < image . length ) {
915+ const blockSize = Math . min ( loader . FLASH_WRITE_SIZE , image . length - imageOffset ) ;
916+ const block = image . slice ( imageOffset , imageOffset + blockSize ) ;
917+ const pct = Math . min ( 100 , Math . floor ( ( 100 * ( seq + 1 ) ) / Math . max ( blocks , 1 ) ) ) ;
918+ loader . info ( `Writing at 0x${ ( address + imageOffset ) . toString ( 16 ) } ... (${ pct } %)` ) ;
919+
920+ if ( typeof loader . timeoutPerMb === "function" ) {
921+ timeout = Math . max ( loader . DEFAULT_TIMEOUT || 3000 , loader . timeoutPerMb ( loader . ERASE_WRITE_TIMEOUT_PER_MB , block . length ) ) ;
922+ }
923+
924+ await loader . flashBlock ( block , seq , timeout ) ;
925+ imageOffset += blockSize ;
926+ seq += 1 ;
927+
928+ if ( flashOptions . reportProgress ) {
929+ flashOptions . reportProgress ( i , imageOffset , totalBytes ) ;
930+ }
931+ }
932+
933+ await loader . flashFinish ( false , timeout ) ;
934+
935+ const elapsedSeconds = ( ( Date . now ( ) - t1 ) / 1000 ) . toFixed ( 3 ) ;
936+ loader . info ( `Wrote ${ totalBytes } bytes at 0x${ address . toString ( 16 ) } in ${ elapsedSeconds } seconds.` ) ;
937+
938+ if ( calcmd5 ) {
939+ loader . info ( "File md5: " + calcmd5 ) ;
940+ const flashMd5 = await loader . flashMd5sum ( address , totalBytes ) ;
941+ loader . info ( "Flash md5: " + flashMd5 ) ;
942+ if ( String ( flashMd5 ) !== calcmd5 ) {
943+ throw new Error ( "MD5 of file does not match data in flash!" ) ;
944+ }
945+ loader . info ( "Hash of data verified." ) ;
946+ }
947+ }
948+
949+ loader . info ( "Leaving..." ) ;
950+ } ;
951+
858952const flash = async ( ) => {
859953 ensureSupport ( ) ;
860954 if ( ! state . esploader ) {
@@ -889,7 +983,13 @@ <h2>Browser support</h2>
889983 } ,
890984 calculateMD5Hash : ( image ) => CryptoJS . MD5 ( CryptoJS . enc . Latin1 . parse ( image ) ) ,
891985 } ;
892- await state . esploader . writeFlash ( flashOptions ) ;
986+ const romChipName = state . esploader ?. chip ?. CHIP_NAME || "" ;
987+ if ( ! flashingFromStub && romChipName === "ESP32-C5" ) {
988+ log ( "Using uncompressed ROM flash path for ESP32-C5 to bypass FLASH_DEFL failures in esptool-js." ) ;
989+ await writeFlashViaRom ( state . esploader , files , flashOptions ) ;
990+ } else {
991+ await state . esploader . writeFlash ( flashOptions ) ;
992+ }
893993 await state . esploader . after ( ) ;
894994 ui . progress . style . width = "100%" ;
895995 setStatus ( "Flash complete. Press RESET if the board doesn't reboot." ) ;
0 commit comments