1
1
use bytemuck:: { __core:: time:: Duration , bytes_of, Pod , Zeroable } ;
2
- use indicatif:: { ProgressBar , ProgressStyle } ;
3
2
use serial:: { BaudRate , SerialPort } ;
4
3
use strum_macros:: Display ;
5
4
6
- use std:: { mem :: size_of , thread:: sleep} ;
5
+ use std:: thread:: sleep;
7
6
7
+ use crate :: elf:: RomSegment ;
8
+ use crate :: flashtarget:: { ChipTarget , FlashTarget , RamTarget } ;
8
9
use crate :: {
9
10
chip:: Chip , connection:: Connection , elf:: FirmwareImage , encoder:: SlipEncoder , error:: RomError ,
10
11
Error , PartitionTable ,
11
12
} ;
12
13
13
- type Encoder < ' a > = SlipEncoder < ' a , Box < dyn SerialPort > > ;
14
+ pub ( crate ) type Encoder < ' a > = SlipEncoder < ' a , Box < dyn SerialPort > > ;
14
15
15
- const MAX_RAM_BLOCK_SIZE : usize = 0x1800 ;
16
16
const FLASH_SECTOR_SIZE : usize = 0x1000 ;
17
17
const FLASH_BLOCK_SIZE : usize = 0x100 ;
18
18
const FLASH_SECTORS_PER_BLOCK : usize = FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE ;
19
- const FLASH_WRITE_SIZE : usize = 0x400 ;
19
+ pub ( crate ) const FLASH_WRITE_SIZE : usize = 0x400 ;
20
20
21
21
// register used for chip detect
22
22
const CHIP_DETECT_MAGIC_REG_ADDR : u32 = 0x40001000 ;
@@ -30,7 +30,7 @@ const SYNC_TIMEOUT: Duration = Duration::from_millis(100);
30
30
#[ derive( Copy , Clone , Debug ) ]
31
31
#[ allow( dead_code) ]
32
32
#[ repr( u8 ) ]
33
- enum Command {
33
+ pub ( crate ) enum Command {
34
34
FlashBegin = 0x02 ,
35
35
FlashData = 0x03 ,
36
36
FlashEnd = 0x04 ,
@@ -109,7 +109,7 @@ impl FlashSize {
109
109
110
110
#[ derive( Copy , Clone ) ]
111
111
#[ repr( C ) ]
112
- struct SpiAttachParams {
112
+ pub struct SpiAttachParams {
113
113
clk : u8 ,
114
114
q : u8 ,
115
115
d : u8 ,
@@ -341,64 +341,6 @@ impl Flasher {
341
341
} )
342
342
}
343
343
344
- fn block_command (
345
- & mut self ,
346
- command : Command ,
347
- data : & [ u8 ] ,
348
- padding : usize ,
349
- padding_byte : u8 ,
350
- sequence : u32 ,
351
- ) -> Result < ( ) , Error > {
352
- let params = BlockParams {
353
- size : ( data. len ( ) + padding) as u32 ,
354
- sequence,
355
- dummy1 : 0 ,
356
- dummy2 : 0 ,
357
- } ;
358
-
359
- let length = size_of :: < BlockParams > ( ) + data. len ( ) + padding;
360
-
361
- let mut check = checksum ( data, CHECKSUM_INIT ) ;
362
-
363
- for _ in 0 ..padding {
364
- check = checksum ( & [ padding_byte] , check) ;
365
- }
366
-
367
- self . connection
368
- . with_timeout ( command. timeout_for_size ( data. len ( ) as u32 ) , |connection| {
369
- connection. command (
370
- command as u8 ,
371
- ( length as u16 , |encoder : & mut Encoder | {
372
- encoder. write ( bytes_of ( & params) ) ?;
373
- encoder. write ( data) ?;
374
- let padding = & [ padding_byte; FLASH_WRITE_SIZE ] [ 0 ..padding] ;
375
- encoder. write ( padding) ?;
376
- Ok ( ( ) )
377
- } ) ,
378
- check as u32 ,
379
- ) ?;
380
- Ok ( ( ) )
381
- } )
382
- }
383
-
384
- fn mem_finish ( & mut self , entry : u32 ) -> Result < ( ) , Error > {
385
- let params = EntryParams {
386
- no_entry : ( entry == 0 ) as u32 ,
387
- entry,
388
- } ;
389
- self . connection
390
- . with_timeout ( Command :: MemEnd . timeout ( ) , |connection| {
391
- connection. write_command ( Command :: MemEnd as u8 , bytes_of ( & params) , 0 )
392
- } )
393
- }
394
-
395
- fn flash_finish ( & mut self , reboot : bool ) -> Result < ( ) , Error > {
396
- self . connection
397
- . with_timeout ( Command :: FlashEnd . timeout ( ) , |connection| {
398
- connection. write_command ( Command :: FlashEnd as u8 , & [ ( !reboot) as u8 ] [ ..] , 0 )
399
- } )
400
- }
401
-
402
344
fn enable_flash ( & mut self , spi_attach_params : SpiAttachParams ) -> Result < ( ) , Error > {
403
345
match self . chip {
404
346
Chip :: Esp8266 => {
@@ -523,31 +465,24 @@ impl Flasher {
523
465
pub fn load_elf_to_ram ( & mut self , elf_data : & [ u8 ] ) -> Result < ( ) , Error > {
524
466
let image = FirmwareImage :: from_data ( elf_data) . map_err ( |_| Error :: InvalidElf ) ?;
525
467
468
+ let mut target = RamTarget :: new ( ) ;
469
+ target. begin ( & mut self . connection , & image) ?;
470
+
526
471
if image. rom_segments ( self . chip ) . next ( ) . is_some ( ) {
527
472
return Err ( Error :: ElfNotRamLoadable ) ;
528
473
}
529
474
530
475
for segment in image. ram_segments ( self . chip ) {
531
- let padding = 4 - segment. data . len ( ) % 4 ;
532
- let block_count =
533
- ( segment. data . len ( ) + padding + MAX_RAM_BLOCK_SIZE - 1 ) / MAX_RAM_BLOCK_SIZE ;
534
- self . begin_command (
535
- Command :: MemBegin ,
536
- segment. data . len ( ) as u32 ,
537
- block_count as u32 ,
538
- MAX_RAM_BLOCK_SIZE as u32 ,
539
- segment. addr ,
476
+ target. write_segment (
477
+ & mut self . connection ,
478
+ RomSegment {
479
+ addr : segment. addr ,
480
+ data : segment. data . into ( ) ,
481
+ } ,
540
482
) ?;
541
-
542
- for ( i, block) in segment. data . chunks ( MAX_RAM_BLOCK_SIZE ) . enumerate ( ) {
543
- let block_padding = if i == block_count - 1 { padding } else { 0 } ;
544
- self . block_command ( Command :: MemData , block, block_padding, 0 , i as u32 ) ?;
545
- }
546
483
}
547
484
548
- self . mem_finish ( image. entry ( ) ) ?;
549
-
550
- Ok ( ( ) )
485
+ target. finish ( & mut self . connection , true )
551
486
}
552
487
553
488
/// Load an elf image to flash and execute it
@@ -557,56 +492,20 @@ impl Flasher {
557
492
bootloader : Option < Vec < u8 > > ,
558
493
partition_table : Option < PartitionTable > ,
559
494
) -> Result < ( ) , Error > {
560
- self . enable_flash ( self . spi_params ) ?;
561
-
562
495
let mut image = FirmwareImage :: from_data ( elf_data) . map_err ( |_| Error :: InvalidElf ) ?;
563
496
image. flash_size = self . flash_size ( ) ;
564
497
498
+ let mut target = ChipTarget :: new ( self . chip , self . spi_params ) ;
499
+ target. begin ( & mut self . connection , & image) ?;
500
+
565
501
for segment in self
566
502
. chip
567
503
. get_flash_segments ( & image, bootloader, partition_table)
568
504
{
569
- let segment = segment?;
570
- let addr = segment. addr ;
571
- let block_count = ( segment. data . len ( ) + FLASH_WRITE_SIZE - 1 ) / FLASH_WRITE_SIZE ;
572
-
573
- let erase_size = match self . chip {
574
- Chip :: Esp8266 => get_erase_size ( addr as usize , segment. data . len ( ) ) as u32 ,
575
- _ => segment. data . len ( ) as u32 ,
576
- } ;
577
-
578
- self . begin_command (
579
- Command :: FlashBegin ,
580
- erase_size,
581
- block_count as u32 ,
582
- FLASH_WRITE_SIZE as u32 ,
583
- addr,
584
- ) ?;
585
-
586
- let chunks = segment. data . chunks ( FLASH_WRITE_SIZE ) ;
587
-
588
- let ( _, chunk_size) = chunks. size_hint ( ) ;
589
- let chunk_size = chunk_size. unwrap_or ( 0 ) as u64 ;
590
- let pb_chunk = ProgressBar :: new ( chunk_size) ;
591
- pb_chunk. set_style (
592
- ProgressStyle :: default_bar ( )
593
- . template ( "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}" )
594
- . progress_chars ( "#>-" ) ,
595
- ) ;
596
-
597
- for ( i, block) in chunks. enumerate ( ) {
598
- pb_chunk. set_message ( format ! ( "segment 0x{:X} writing chunks" , addr) ) ;
599
- let block_padding = FLASH_WRITE_SIZE - block. len ( ) ;
600
- self . block_command ( Command :: FlashData , block, block_padding, 0xff , i as u32 ) ?;
601
- pb_chunk. inc ( 1 ) ;
602
- }
603
-
604
- pb_chunk. finish_with_message ( format ! ( "segment 0x{:X}" , addr) ) ;
505
+ target. write_segment ( & mut self . connection , segment?) ?;
605
506
}
606
507
607
- self . flash_finish ( false ) ?;
608
-
609
- self . connection . reset ( ) ?;
508
+ target. finish ( & mut self . connection , true ) ?;
610
509
611
510
Ok ( ( ) )
612
511
}
@@ -630,7 +529,7 @@ impl Flasher {
630
529
}
631
530
}
632
531
633
- fn get_erase_size ( offset : usize , size : usize ) -> usize {
532
+ pub ( crate ) fn get_erase_size ( offset : usize , size : usize ) -> usize {
634
533
let sector_count = ( size + FLASH_SECTOR_SIZE - 1 ) / FLASH_SECTOR_SIZE ;
635
534
let start_sector = offset / FLASH_SECTOR_SIZE ;
636
535
@@ -646,7 +545,7 @@ fn get_erase_size(offset: usize, size: usize) -> usize {
646
545
}
647
546
}
648
547
649
- const CHECKSUM_INIT : u8 = 0xEF ;
548
+ pub ( crate ) const CHECKSUM_INIT : u8 = 0xEF ;
650
549
651
550
pub fn checksum ( data : & [ u8 ] , mut checksum : u8 ) -> u8 {
652
551
for byte in data {
0 commit comments