Skip to content

Commit c92a2eb

Browse files
committed
chore(stm32h7-qspi): Deduplicate QSPI interrupt handling
1 parent 3084591 commit c92a2eb

File tree

1 file changed

+58
-61
lines changed

1 file changed

+58
-61
lines changed

drv/stm32h7-qspi/src/lib.rs

Lines changed: 58 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ impl Qspi {
142142
}
143143

144144
/// Helper for error paths.
145+
///
146+
/// Disables FIFO Threshold, Transfer Complete, Transfer Error, and Timeout
147+
/// interrupts.
145148
fn disable_all_interrupts(&self) {
146149
self.reg.cr.modify(|_, w| {
147150
w.ftie()
@@ -155,6 +158,49 @@ impl Qspi {
155158
});
156159
}
157160

161+
/// Returns the number of valid bytes being held in the FIFO queue if a
162+
/// QSPI timeout or transfer error hasn't occurred.
163+
fn get_fifo_level(&self) -> Result<usize, QspiError> {
164+
let sr = self.reg.sr.read();
165+
166+
// Check timeout bit.
167+
if sr.tof().bit_is_set() {
168+
// Clear timeout bit and return.
169+
self.reg.fcr.modify(|_, w| w.ctof().set_bit());
170+
return Err(QspiError::Timeout);
171+
}
172+
// Check transfer error bit.
173+
if sr.tef().bit_is_set() {
174+
// Clear transfer error bit and return.
175+
self.reg.fcr.modify(|_, w| w.ctef().set_bit());
176+
return Err(QspiError::TransferError);
177+
}
178+
// Re-enable transfer error and timeout interrupts to make sure we
179+
// catch any future errors.
180+
self.reg
181+
.cr
182+
.modify(|_, w| w.teie().set_bit().toie().set_bit());
183+
Ok(usize::from(sr.flevel().bits()))
184+
}
185+
186+
/// Wait for the Transfer Complete flag to get set.
187+
///
188+
/// Note: this function returning does not guarantee that the BUSY flag is
189+
/// clear.
190+
fn wait_for_transfer_complete(&self) {
191+
// Disable FIFO threshold interrupt, and enable transfer complete
192+
// interrupts.
193+
self.reg
194+
.cr
195+
.modify(|_, w| w.ftie().clear_bit().tcie().set_bit());
196+
while self.transfer_not_complete() {
197+
// Unmask our interrupt.
198+
sys_irq_control(self.interrupt, true);
199+
// And wait for it to arrive.
200+
sys_recv_notification(self.interrupt);
201+
}
202+
}
203+
158204
fn write_impl(
159205
&self,
160206
command: Command,
@@ -213,24 +259,10 @@ impl Qspi {
213259
// off the front.
214260
let mut data = data;
215261
while !data.is_empty() {
216-
let sr = self.reg.sr.read();
217-
218-
if sr.tof().bit_is_set() {
219-
self.reg.fcr.modify(|_, w| w.ctof().set_bit());
220-
return Err(QspiError::Timeout);
221-
}
222-
if sr.tef().bit_is_set() {
223-
self.reg.fcr.modify(|_, w| w.ctef().set_bit());
224-
return Err(QspiError::TransferError);
225-
}
226-
227-
// Make sure our errors are enabled
228-
self.reg
229-
.cr
230-
.modify(|_, w| w.teie().set_bit().toie().set_bit());
262+
// Check for any errors
263+
let fl = self.get_fifo_level()?;
231264

232265
// How much space is in the FIFO?
233-
let fl = usize::from(sr.flevel().bits());
234266
let ffree = FIFO_SIZE - fl;
235267
if ffree >= FIFO_THRESH.min(data.len()) {
236268
// Calculate the write size. Note that this may be bigger than
@@ -268,18 +300,11 @@ impl Qspi {
268300
}
269301

270302
// We're now interested in transfer complete, not FIFO ready.
271-
self.reg
272-
.cr
273-
.modify(|_, w| w.ftie().clear_bit().tcie().set_bit());
274-
while self.transfer_not_complete() {
275-
// Unmask our interrupt.
276-
sys_irq_control(self.interrupt, true);
277-
// And wait for it to arrive.
278-
sys_recv_notification(self.interrupt);
279-
}
280-
self.reg.cr.modify(|_, w| {
281-
w.tcie().clear_bit().teie().clear_bit().toie().clear_bit()
282-
});
303+
self.wait_for_transfer_complete();
304+
305+
// Clean up by disabling our interrupt sources.
306+
self.disable_all_interrupts();
307+
283308
Ok(())
284309
}
285310

@@ -340,22 +365,10 @@ impl Qspi {
340365
// perform transfers.
341366
let mut out = out;
342367
while !out.is_empty() {
343-
let sr = self.reg.sr.read();
368+
// Get the FIFO level if no errors have occurred.
369+
let fl = self.get_fifo_level()?;
344370

345-
if sr.tof().bit_is_set() {
346-
self.reg.fcr.modify(|_, w| w.ctof().set_bit());
347-
return Err(QspiError::Timeout);
348-
}
349-
if sr.tef().bit_is_set() {
350-
self.reg.fcr.modify(|_, w| w.ctef().set_bit());
351-
return Err(QspiError::TransferError);
352-
}
353-
// Make sure our errors are enabled
354-
self.reg
355-
.cr
356-
.modify(|_, w| w.teie().set_bit().toie().set_bit());
357371
// Is there enough to read that we want to bother with it?
358-
let fl = usize::from(sr.flevel().bits());
359372
if fl < FIFO_THRESH.min(out.len()) {
360373
// Nope! Let's wait for more bytes.
361374

@@ -403,27 +416,11 @@ impl Qspi {
403416
// necessarily imply the BUSY flag is clear, but since commands are
404417
// issued into a FIFO, we can issue the next command even while BUSY is
405418
// set, it appears.
406-
self.reg
407-
.cr
408-
.modify(|_, w| w.ftie().clear_bit().tcie().set_bit());
409-
while self.transfer_not_complete() {
410-
// Unmask our interrupt.
411-
sys_irq_control(self.interrupt, true);
412-
// And wait for it to arrive.
413-
sys_recv_notification(self.interrupt);
414-
}
419+
self.wait_for_transfer_complete();
415420

416421
// Clean up by disabling our interrupt sources.
417-
self.reg.cr.modify(|_, w| {
418-
w.ftie()
419-
.clear_bit()
420-
.tcie()
421-
.clear_bit()
422-
.teie()
423-
.clear_bit()
424-
.toie()
425-
.clear_bit()
426-
});
422+
self.disable_all_interrupts();
423+
427424
Ok(())
428425
}
429426

0 commit comments

Comments
 (0)