1
1
use crate :: connection:: Connection ;
2
2
use crate :: elf:: { FirmwareImage , RomSegment } ;
3
3
use crate :: error:: Error ;
4
- use crate :: flasher:: { get_erase_size , Command , SpiAttachParams , FLASH_WRITE_SIZE } ;
5
- use crate :: flashtarget:: { begin_command, block_command , FlashTarget } ;
4
+ use crate :: flasher:: { Command , SpiAttachParams , FLASH_SECTOR_SIZE , FLASH_WRITE_SIZE } ;
5
+ use crate :: flashtarget:: { begin_command, block_command_with_timeout , FlashTarget } ;
6
6
use crate :: Chip ;
7
+ use flate2:: write:: { ZlibDecoder , ZlibEncoder } ;
8
+ use flate2:: Compression ;
7
9
use indicatif:: { ProgressBar , ProgressStyle } ;
10
+ use std:: io:: Write ;
8
11
9
12
pub struct Esp32Target {
10
13
chip : Chip ,
@@ -35,21 +38,26 @@ impl FlashTarget for Esp32Target {
35
38
segment : RomSegment ,
36
39
) -> Result < ( ) , Error > {
37
40
let addr = segment. addr ;
38
- let block_count = ( segment. data . len ( ) + FLASH_WRITE_SIZE - 1 ) / FLASH_WRITE_SIZE ;
41
+ let mut encoder = ZlibEncoder :: new ( Vec :: new ( ) , Compression :: best ( ) ) ;
42
+ encoder. write_all ( & segment. data ) ?;
43
+ let compressed = encoder. finish ( ) ?;
44
+ let block_count = ( compressed. len ( ) + FLASH_WRITE_SIZE - 1 ) / FLASH_WRITE_SIZE ;
45
+ let erase_count = ( segment. data . len ( ) + FLASH_SECTOR_SIZE - 1 ) / FLASH_SECTOR_SIZE ;
39
46
40
- let erase_size = segment. data . len ( ) as u32 ;
47
+ // round up to sector size
48
+ let erase_size = ( erase_count * FLASH_SECTOR_SIZE ) as u32 ;
41
49
42
50
begin_command (
43
51
connection,
44
- Command :: FlashBegin ,
52
+ Command :: FlashDeflateBegin ,
45
53
erase_size,
46
54
block_count as u32 ,
47
55
FLASH_WRITE_SIZE as u32 ,
48
56
addr,
49
57
self . chip != Chip :: Esp32 ,
50
58
) ?;
51
59
52
- let chunks = segment . data . chunks ( FLASH_WRITE_SIZE ) ;
60
+ let chunks = compressed . chunks ( FLASH_WRITE_SIZE ) ;
53
61
54
62
let ( _, chunk_size) = chunks. size_hint ( ) ;
55
63
let chunk_size = chunk_size. unwrap_or ( 0 ) as u64 ;
@@ -60,16 +68,25 @@ impl FlashTarget for Esp32Target {
60
68
. progress_chars ( "#>-" ) ,
61
69
) ;
62
70
71
+ // decode the chunks to see how much data the device will have to save
72
+ let mut decoder = ZlibDecoder :: new ( Vec :: new ( ) ) ;
73
+ let mut decoded_size = 0 ;
74
+
63
75
for ( i, block) in chunks. enumerate ( ) {
76
+ decoder. write_all ( block) ?;
77
+ decoder. flush ( ) ?;
78
+ let size = decoder. get_ref ( ) . len ( ) - decoded_size;
79
+ decoded_size = decoder. get_ref ( ) . len ( ) ;
80
+
64
81
pb_chunk. set_message ( format ! ( "segment 0x{:X} writing chunks" , addr) ) ;
65
- let block_padding = FLASH_WRITE_SIZE - block. len ( ) ;
66
- block_command (
82
+ block_command_with_timeout (
67
83
connection,
68
- Command :: FlashData ,
84
+ Command :: FlashDeflateData ,
69
85
block,
70
- block_padding ,
86
+ 0 ,
71
87
0xff ,
72
88
i as u32 ,
89
+ Command :: FlashDeflateData . timeout_for_size ( size as u32 ) ,
73
90
) ?;
74
91
pb_chunk. inc ( 1 ) ;
75
92
}
@@ -80,8 +97,8 @@ impl FlashTarget for Esp32Target {
80
97
}
81
98
82
99
fn finish ( & mut self , connection : & mut Connection , reboot : bool ) -> Result < ( ) , Error > {
83
- connection. with_timeout ( Command :: FlashEnd . timeout ( ) , |connection| {
84
- connection. write_command ( Command :: FlashEnd as u8 , & [ 1 ] [ ..] , 0 )
100
+ connection. with_timeout ( Command :: FlashDeflateEnd . timeout ( ) , |connection| {
101
+ connection. write_command ( Command :: FlashDeflateEnd as u8 , & [ 1 ] [ ..] , 0 )
85
102
} ) ?;
86
103
if reboot {
87
104
connection. reset ( )
0 commit comments