Skip to content

Commit 44be30c

Browse files
committed
Use variable timeouts for different flash operations
Some operations (like erasing or writing flash) will depend on the size being erased or written. For larger sizes (e.g 1MB), 3 seconds is often not enough. Timeouts taken from esptool.py.
1 parent 77ed92f commit 44be30c

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)