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}