1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use alloc::vec::Vec;
use core::time::Duration;
#[derive(Clone, Debug)]
pub(crate) struct ErasePlan(pub Vec<(u8, usize, u32, Option<Duration>)>);
impl ErasePlan {
pub fn new(insts: &[(usize, u8, Option<Duration>)], start: usize, length: usize) -> Self {
log::trace!("Creating erase plan, start={} length={}", start, length);
let mut plan = Vec::new();
let mut insts = insts.to_vec();
insts.sort();
let end = start + length;
let mut pos = start;
while pos < end {
log::trace!("Evaluating candidates, pos={} end={}", pos, end);
let mut candidate = (0, usize::MAX, 0, 0, None);
for (erase_size, opcode, duration) in insts.iter() {
let erase_base = pos - (pos % erase_size);
let erase_end = erase_base + erase_size - 1;
let mut bytes = erase_size - (pos - erase_base);
if erase_end > end {
bytes -= erase_end - end + 1;
}
log::trace!(
" Candidate 0x{:02X} ({} bytes): base={} end={} bytes={}",
opcode,
erase_size,
erase_base,
erase_end,
bytes
);
if bytes > candidate.0 || (bytes == candidate.0 && *erase_size < candidate.1) {
candidate = (bytes, *erase_size, *opcode, erase_base, *duration);
}
}
log::trace!("Candidate selected: {:?}", candidate);
pos += candidate.0;
plan.push((candidate.2, candidate.1, candidate.3 as u32, candidate.4));
}
log::debug!("Erase plan: {:?}", plan);
ErasePlan(plan)
}
#[cfg(feature = "std")]
pub fn total_size(&self) -> usize {
self.0.iter().map(|x| x.1).sum()
}
}
#[test]
fn test_erase_plan() {
let insts = &[(4, 1, None), (32, 2, None), (64, 3, None)];
assert_eq!(ErasePlan::new(insts, 0, 4).0, alloc::vec![(1, 4, 0, None)]);
assert_eq!(
ErasePlan::new(insts, 0, 64).0,
alloc::vec![(3, 64, 0, None)]
);
assert_eq!(
ErasePlan::new(insts, 0, 192).0,
alloc::vec![(3, 64, 0, None), (3, 64, 64, None), (3, 64, 128, None)]
);
assert_eq!(
ErasePlan::new(insts, 0, 70).0,
alloc::vec![(3, 64, 0, None), (2, 32, 64, None)]
);
assert_eq!(
ErasePlan::new(insts, 0, 66).0,
alloc::vec![(3, 64, 0, None), (1, 4, 64, None)]
);
assert_eq!(
ErasePlan::new(insts, 62, 64).0,
alloc::vec![(1, 4, 60, None), (3, 64, 64, None)]
);
assert_eq!(
ErasePlan::new(insts, 62, 68).0,
alloc::vec![(1, 4, 60, None), (3, 64, 64, None), (1, 4, 128, None)]
);
}