probe_rs/flashing/progress.rs
1use super::FlashLayout;
2use std::time::Duration;
3
4/// A structure to manage the flashing procedure progress reporting.
5///
6/// This struct stores a handler closure which will be called every time an event happens during the flashing process.
7/// Such an event can be start or finish of the flashing procedure or a progress report, as well as some more events.
8///
9/// # Example
10///
11/// ```
12/// use probe_rs::flashing::FlashProgress;
13///
14/// // Print events
15/// let progress = FlashProgress::new(|event| println!("Event: {:#?}", event));
16/// ```
17pub struct FlashProgress<'a> {
18 handler: Box<dyn FnMut(ProgressEvent) + 'a>,
19}
20
21impl<'a> Default for FlashProgress<'a> {
22 fn default() -> Self {
23 Self::empty()
24 }
25}
26
27impl<'a> FlashProgress<'a> {
28 /// Create a new `FlashProgress` structure with a given `handler` to be called on events.
29 pub fn new(handler: impl FnMut(ProgressEvent) + 'a) -> Self {
30 Self {
31 handler: Box::new(handler),
32 }
33 }
34
35 /// Create a new `FlashProgress` structure with an empty handler.
36 pub fn empty() -> Self {
37 Self {
38 handler: Box::new(|_| {}),
39 }
40 }
41
42 /// Emit a flashing progress event.
43 pub fn emit(&mut self, event: ProgressEvent) {
44 (self.handler)(event);
45 }
46
47 // --- Methods for emitting specific kinds of events.
48
49 /// Signal that the flashing algorithm was set up and is initialized.
50 pub(super) fn initialized(&mut self, phases: Vec<FlashLayout>) {
51 self.emit(ProgressEvent::FlashLayoutReady {
52 flash_layout: phases,
53 });
54 }
55
56 /// Signal that a new progress bar should be created.
57 pub(super) fn add_progress_bar(&mut self, operation: ProgressOperation, total: Option<u64>) {
58 self.emit(ProgressEvent::AddProgressBar { operation, total });
59 }
60
61 /// Signal that the procedure started.
62 pub(super) fn started(&mut self, operation: ProgressOperation) {
63 self.emit(ProgressEvent::Started(operation));
64 }
65
66 /// Signal that the procedure has made progress.
67 pub(super) fn progressed(&mut self, operation: ProgressOperation, size: u64, time: Duration) {
68 self.emit(ProgressEvent::Progress {
69 operation,
70 size,
71 time,
72 });
73 }
74
75 /// Signal that the procedure failed.
76 pub(super) fn failed(&mut self, operation: ProgressOperation) {
77 self.emit(ProgressEvent::Failed(operation));
78 }
79
80 /// Signal that the procedure completed successfully.
81 pub(super) fn finished(&mut self, operation: ProgressOperation) {
82 self.emit(ProgressEvent::Finished(operation));
83 }
84
85 /// Signal that a flashing algorithm produced a diagnostic message.
86 pub(super) fn message(&mut self, message: String) {
87 self.emit(ProgressEvent::DiagnosticMessage { message });
88 }
89
90 // --- Methods for emitting events for a specific operation.
91
92 /// Signal that the erasing procedure started.
93 pub(super) fn started_erasing(&mut self) {
94 self.started(ProgressOperation::Erase);
95 }
96
97 /// Signal that the filling procedure started.
98 pub(super) fn started_filling(&mut self) {
99 self.started(ProgressOperation::Fill);
100 }
101
102 /// Signal that the programming procedure started.
103 pub(super) fn started_programming(&mut self) {
104 self.started(ProgressOperation::Program);
105 }
106
107 /// Signal that the verifying procedure started.
108 pub(crate) fn started_verifying(&mut self) {
109 self.started(ProgressOperation::Verify);
110 }
111
112 /// Signal that the sector erasing procedure has made progress.
113 pub(super) fn sector_erased(&mut self, size: u64, time: Duration) {
114 self.progressed(ProgressOperation::Erase, size, time);
115 }
116
117 /// Signal that the page filling procedure has made progress.
118 pub(super) fn page_filled(&mut self, size: u64, time: Duration) {
119 self.progressed(ProgressOperation::Fill, size, time);
120 }
121
122 /// Signal that the page programming procedure has made progress.
123 pub(super) fn page_programmed(&mut self, size: u64, time: Duration) {
124 self.progressed(ProgressOperation::Program, size, time);
125 }
126
127 /// Signal that the page filling procedure has made progress.
128 pub(super) fn page_verified(&mut self, size: u64, time: Duration) {
129 self.progressed(ProgressOperation::Verify, size, time);
130 }
131
132 /// Signal that the erasing procedure failed.
133 pub(super) fn failed_erasing(&mut self) {
134 self.failed(ProgressOperation::Erase);
135 }
136
137 /// Signal that the filling procedure failed.
138 pub(super) fn failed_filling(&mut self) {
139 self.failed(ProgressOperation::Fill);
140 }
141
142 /// Signal that the programming procedure failed.
143 pub(super) fn failed_programming(&mut self) {
144 self.failed(ProgressOperation::Program);
145 }
146
147 /// Signal that the verifying procedure failed.
148 pub(super) fn failed_verifying(&mut self) {
149 self.failed(ProgressOperation::Verify);
150 }
151
152 /// Signal that the programming procedure completed successfully.
153 pub(super) fn finished_programming(&mut self) {
154 self.finished(ProgressOperation::Program);
155 }
156
157 /// Signal that the erasing procedure completed successfully.
158 pub(super) fn finished_erasing(&mut self) {
159 self.finished(ProgressOperation::Erase);
160 }
161
162 /// Signal that the filling procedure completed successfully.
163 pub(super) fn finished_filling(&mut self) {
164 self.finished(ProgressOperation::Fill);
165 }
166
167 /// Signal that the verifying procedure completed successfully.
168 pub(super) fn finished_verifying(&mut self) {
169 self.finished(ProgressOperation::Verify);
170 }
171}
172
173/// The operation that is currently in progress.
174#[derive(Clone, Copy, Debug)]
175pub enum ProgressOperation {
176 /// Reading back flash contents to restore erased regions that should be kept unchanged.
177 Fill,
178
179 /// Erasing flash sectors.
180 Erase,
181
182 /// Writing data to flash.
183 Program,
184
185 /// Checking flash contents.
186 Verify,
187}
188
189/// Possible events during the flashing process.
190///
191/// If flashing works without problems, the events will arrive in the
192/// following order:
193///
194/// * `FlashLayoutReady`
195/// * A number of `AddProgressBar` events
196/// * `Started`, `Progress`, and `Finished` events for each operation
197///
198/// If an error occurs in any stage, the `Failed` event will be returned,
199/// and no further events will be returned.
200#[derive(Debug, Clone)]
201pub enum ProgressEvent {
202 /// The flash layout is ready.
203 FlashLayoutReady {
204 /// The flash layout.
205 flash_layout: Vec<FlashLayout>,
206 },
207
208 /// Display a new progress bar to the user.
209 AddProgressBar {
210 /// The operation that the progress bar is for.
211 operation: ProgressOperation,
212 /// The total size of the operation, if known.
213 ///
214 /// If `None`, the total size is indeterminate.
215 total: Option<u64>,
216 },
217
218 /// Started an operation with the given total size.
219 Started(ProgressOperation),
220
221 /// An operation has made progress.
222 Progress {
223 /// The operation that made progress.
224 operation: ProgressOperation,
225 /// The size of the page in bytes.
226 size: u64,
227 /// The time it took to perform the operation.
228 time: Duration,
229 },
230
231 /// An operation has failed.
232 Failed(ProgressOperation),
233
234 /// An operation has finished successfully.
235 Finished(ProgressOperation),
236
237 /// A message was received from the algo.
238 DiagnosticMessage {
239 /// The message that was emitted.
240 message: String,
241 },
242}