Skip to content

Commit b5282f2

Browse files
authored
Merge pull request #36 from kelnos/variable-timeouts
Use variable timeouts for different flash operations
2 parents 77ed92f + 44be30c commit b5282f2

File tree

1 file changed

+75
-27
lines changed

1 file changed

+75
-27
lines changed

espflash/src/flasher.rs

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ const FLASH_WRITE_SIZE: usize = 0x400;
2020
// register used for chip detect
2121
const CHIP_DETECT_MAGIC_REG_ADDR: u32 = 0x40001000;
2222

23+
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(3);
24+
const ERASE_REGION_TIMEOUT_PER_MB: Duration = Duration::from_secs(30);
25+
const ERASE_WRITE_TIMEOUT_PER_MB: Duration = Duration::from_secs(40);
26+
const MEM_END_TIMEOUT: Duration = Duration::from_millis(50);
27+
const SYNC_TIMEOUT: Duration = Duration::from_millis(100);
28+
2329
#[derive(Copy, Clone, Debug)]
2430
#[repr(u8)]
2531
#[allow(dead_code)]
@@ -38,6 +44,31 @@ enum Command {
3844
ChangeBaud = 0x0F,
3945
}
4046

47+
impl Command {
48+
pub fn timeout(&self) -> Duration {
49+
match self {
50+
Command::MemEnd => MEM_END_TIMEOUT,
51+
Command::Sync => SYNC_TIMEOUT,
52+
_ => DEFAULT_TIMEOUT,
53+
}
54+
}
55+
56+
pub fn timeout_for_size(&self, size: u32) -> Duration {
57+
fn calc_timeout(timeout_per_mb: Duration, size: u32) -> Duration {
58+
let mb = size as f64 / 1_000_000.0;
59+
std::cmp::max(
60+
DEFAULT_TIMEOUT,
61+
Duration::from_millis((timeout_per_mb.as_millis() as f64 * mb) as u64),
62+
)
63+
}
64+
match self {
65+
Command::FlashBegin => calc_timeout(ERASE_REGION_TIMEOUT_PER_MB, size),
66+
Command::FlashData => calc_timeout(ERASE_WRITE_TIMEOUT_PER_MB, size),
67+
_ => self.timeout(),
68+
}
69+
}
70+
}
71+
4172
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
4273
#[allow(dead_code)]
4374
#[repr(u8)]
@@ -171,7 +202,7 @@ impl Flasher {
171202
spi_params: SpiAttachParams::default(), // may be set when trying to attach to flash
172203
};
173204
flasher.start_connection()?;
174-
flasher.connection.set_timeout(Duration::from_secs(3))?;
205+
flasher.connection.set_timeout(DEFAULT_TIMEOUT)?;
175206
flasher.chip_detect()?;
176207
flasher.spi_autodetect()?;
177208

@@ -224,7 +255,7 @@ impl Flasher {
224255

225256
fn sync(&mut self) -> Result<(), Error> {
226257
self.connection
227-
.with_timeout(Duration::from_millis(100), |connection| {
258+
.with_timeout(Command::Sync.timeout(), |connection| {
228259
let data = &[
229260
0x07, 0x07, 0x12, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
230261
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
@@ -295,8 +326,11 @@ impl Flasher {
295326
bytes
296327
};
297328

298-
self.connection.command(command as u8, data, 0)?;
299-
Ok(())
329+
self.connection
330+
.with_timeout(command.timeout_for_size(size), |connection| {
331+
connection.command(command as u8, data, 0)?;
332+
Ok(())
333+
})
300334
}
301335

302336
fn block_command(
@@ -322,18 +356,21 @@ impl Flasher {
322356
check = checksum(&[padding_byte], check);
323357
}
324358

325-
self.connection.command(
326-
command as u8,
327-
(length as u16, |encoder: &mut Encoder| {
328-
encoder.write(bytes_of(&params))?;
329-
encoder.write(data)?;
330-
let padding = &[padding_byte; FLASH_WRITE_SIZE][0..padding];
331-
encoder.write(padding)?;
359+
self.connection
360+
.with_timeout(command.timeout_for_size(data.len() as u32), |connection| {
361+
connection.command(
362+
command as u8,
363+
(length as u16, |encoder: &mut Encoder| {
364+
encoder.write(bytes_of(&params))?;
365+
encoder.write(data)?;
366+
let padding = &[padding_byte; FLASH_WRITE_SIZE][0..padding];
367+
encoder.write(padding)?;
368+
Ok(())
369+
}),
370+
check as u32,
371+
)?;
332372
Ok(())
333-
}),
334-
check as u32,
335-
)?;
336-
Ok(())
373+
})
337374
}
338375

339376
fn mem_finish(&mut self, entry: u32) -> Result<(), Error> {
@@ -342,14 +379,16 @@ impl Flasher {
342379
entry,
343380
};
344381
self.connection
345-
.write_command(Command::MemEnd as u8, bytes_of(&params), 0)?;
346-
Ok(())
382+
.with_timeout(Command::MemEnd.timeout(), |connection| {
383+
connection.write_command(Command::MemEnd as u8, bytes_of(&params), 0)
384+
})
347385
}
348386

349387
fn flash_finish(&mut self, reboot: bool) -> Result<(), Error> {
350388
self.connection
351-
.write_command(Command::FlashEnd as u8, &[(!reboot) as u8][..], 0)?;
352-
Ok(())
389+
.with_timeout(Command::FlashEnd.timeout(), |connection| {
390+
connection.write_command(Command::FlashEnd as u8, &[(!reboot) as u8][..], 0)
391+
})
353392
}
354393

355394
fn enable_flash(&mut self, spi_attach_params: SpiAttachParams) -> Result<(), Error> {
@@ -360,7 +399,9 @@ impl Flasher {
360399
_ => {
361400
let spi_params = spi_attach_params.encode();
362401
self.connection
363-
.command(Command::SpiAttach as u8, spi_params.as_slice(), 0)?;
402+
.with_timeout(Command::SpiAttach.timeout(), |connection| {
403+
connection.command(Command::SpiAttach as u8, spi_params.as_slice(), 0)
404+
})?;
364405
}
365406
}
366407
Ok(())
@@ -439,7 +480,9 @@ impl Flasher {
439480

440481
fn read_reg(&mut self, reg: u32) -> Result<u32, Error> {
441482
self.connection
442-
.command(Command::ReadReg as u8, &reg.to_le_bytes()[..], 0)
483+
.with_timeout(Command::ReadReg.timeout(), |connection| {
484+
connection.command(Command::ReadReg as u8, &reg.to_le_bytes()[..], 0)
485+
})
443486
}
444487

445488
fn write_reg(&mut self, addr: u32, value: u32, mask: Option<u32>) -> Result<(), Error> {
@@ -450,7 +493,9 @@ impl Flasher {
450493
delay_us: 0,
451494
};
452495
self.connection
453-
.command(Command::WriteReg as u8, bytes_of(&params), 0)?;
496+
.with_timeout(Command::WriteReg.timeout(), |connection| {
497+
connection.command(Command::WriteReg as u8, bytes_of(&params), 0)
498+
})?;
454499
Ok(())
455500
}
456501

@@ -553,11 +598,14 @@ impl Flasher {
553598
let new_speed = (speed.speed() as u32).to_le_bytes();
554599
let old_speed = 0u32.to_le_bytes();
555600

556-
self.connection.command(
557-
Command::ChangeBaud as u8,
558-
&[new_speed, old_speed].concat()[..],
559-
0,
560-
)?;
601+
self.connection
602+
.with_timeout(Command::ChangeBaud.timeout(), |connection| {
603+
connection.command(
604+
Command::ChangeBaud as u8,
605+
&[new_speed, old_speed].concat()[..],
606+
0,
607+
)
608+
})?;
561609
self.connection.set_baud(speed)?;
562610
std::thread::sleep(Duration::from_secs_f32(0.05));
563611
self.connection.flush()?;

0 commit comments

Comments
 (0)