Skip to content

Commit e2c81cf

Browse files
committed
chore(stm32h7-qspi): Deduplicate QSPI interrupt handling
1 parent 63b81c8 commit e2c81cf

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
@@ -167,6 +167,9 @@ impl Qspi {
167167
}
168168

169169
/// Helper for error paths.
170+
///
171+
/// Disables FIFO Threshold, Transfer Complete, Transfer Error, and Timeout
172+
/// interrupts.
170173
fn disable_all_interrupts(&self) {
171174
self.reg.cr.modify(|_, w| {
172175
w.ftie()
@@ -180,6 +183,49 @@ impl Qspi {
180183
});
181184
}
182185

186+
/// Returns the number of valid bytes being held in the FIFO queue if a
187+
/// QSPI timeout or transfer error hasn't occurred.
188+
fn get_fifo_level(&self) -> Result<usize, QspiError> {
189+
let sr = self.reg.sr.read();
190+
191+
// Check timeout bit.
192+
if sr.tof().bit_is_set() {
193+
// Clear timeout bit and return.
194+
self.reg.fcr.modify(|_, w| w.ctof().set_bit());
195+
return Err(QspiError::Timeout);
196+
}
197+
// Check transfer error bit.
198+
if sr.tef().bit_is_set() {
199+
// Clear transfer error bit and return.
200+
self.reg.fcr.modify(|_, w| w.ctef().set_bit());
201+
return Err(QspiError::TransferError);
202+
}
203+
// Re-enable transfer error and timeout interrupts to make sure we
204+
// catch any future errors.
205+
self.reg
206+
.cr
207+
.modify(|_, w| w.teie().set_bit().toie().set_bit());
208+
Ok(usize::from(sr.flevel().bits()))
209+
}
210+
211+
/// Wait for the Transfer Complete flag to get set.
212+
///
213+
/// Note: this function returning does not guarantee that the BUSY flag is
214+
/// clear.
215+
fn wait_for_transfer_complete(&self) {
216+
// Disable FIFO threshold interrupt, and enable transfer complete
217+
// interrupts.
218+
self.reg
219+
.cr
220+
.modify(|_, w| w.ftie().clear_bit().tcie().set_bit());
221+
while self.transfer_not_complete() {
222+
// Unmask our interrupt.
223+
sys_irq_control(self.interrupt, true);
224+
// And wait for it to arrive.
225+
sys_recv_notification(self.interrupt);
226+
}
227+
}
228+
183229
fn write_impl(
184230
&self,
185231
command: Command,
@@ -238,24 +284,10 @@ impl Qspi {
238284
// off the front.
239285
let mut data = data;
240286
while !data.is_empty() {
241-
let sr = self.reg.sr.read();
242-
243-
if sr.tof().bit_is_set() {
244-
self.reg.fcr.modify(|_, w| w.ctof().set_bit());
245-
return Err(QspiError::Timeout);
246-
}
247-
if sr.tef().bit_is_set() {
248-
self.reg.fcr.modify(|_, w| w.ctef().set_bit());
249-
return Err(QspiError::TransferError);
250-
}
251-
252-
// Make sure our errors are enabled
253-
self.reg
254-
.cr
255-
.modify(|_, w| w.teie().set_bit().toie().set_bit());
287+
// Check for any errors
288+
let fl = self.get_fifo_level()?;
256289

257290
// How much space is in the FIFO?
258-
let fl = usize::from(sr.flevel().bits());
259291
let ffree = FIFO_SIZE - fl;
260292
if ffree >= FIFO_THRESH.min(data.len()) {
261293
// Calculate the write size. Note that this may be bigger than
@@ -293,18 +325,11 @@ impl Qspi {
293325
}
294326

295327
// We're now interested in transfer complete, not FIFO ready.
296-
self.reg
297-
.cr
298-
.modify(|_, w| w.ftie().clear_bit().tcie().set_bit());
299-
while self.transfer_not_complete() {
300-
// Unmask our interrupt.
301-
sys_irq_control(self.interrupt, true);
302-
// And wait for it to arrive.
303-
sys_recv_notification(self.interrupt);
304-
}
305-
self.reg.cr.modify(|_, w| {
306-
w.tcie().clear_bit().teie().clear_bit().toie().clear_bit()
307-
});
328+
self.wait_for_transfer_complete();
329+
330+
// Clean up by disabling our interrupt sources.
331+
self.disable_all_interrupts();
332+
308333
Ok(())
309334
}
310335

@@ -375,22 +400,10 @@ impl Qspi {
375400
// perform transfers.
376401
let mut out = out;
377402
while !out.is_empty() {
378-
let sr = self.reg.sr.read();
403+
// Get the FIFO level if no errors have occurred.
404+
let fl = self.get_fifo_level()?;
379405

380-
if sr.tof().bit_is_set() {
381-
self.reg.fcr.modify(|_, w| w.ctof().set_bit());
382-
return Err(QspiError::Timeout);
383-
}
384-
if sr.tef().bit_is_set() {
385-
self.reg.fcr.modify(|_, w| w.ctef().set_bit());
386-
return Err(QspiError::TransferError);
387-
}
388-
// Make sure our errors are enabled
389-
self.reg
390-
.cr
391-
.modify(|_, w| w.teie().set_bit().toie().set_bit());
392406
// Is there enough to read that we want to bother with it?
393-
let fl = usize::from(sr.flevel().bits());
394407
if fl < FIFO_THRESH.min(out.len()) {
395408
// Nope! Let's wait for more bytes.
396409

@@ -438,27 +451,11 @@ impl Qspi {
438451
// necessarily imply the BUSY flag is clear, but since commands are
439452
// issued into a FIFO, we can issue the next command even while BUSY is
440453
// set, it appears.
441-
self.reg
442-
.cr
443-
.modify(|_, w| w.ftie().clear_bit().tcie().set_bit());
444-
while self.transfer_not_complete() {
445-
// Unmask our interrupt.
446-
sys_irq_control(self.interrupt, true);
447-
// And wait for it to arrive.
448-
sys_recv_notification(self.interrupt);
449-
}
454+
self.wait_for_transfer_complete();
450455

451456
// Clean up by disabling our interrupt sources.
452-
self.reg.cr.modify(|_, w| {
453-
w.ftie()
454-
.clear_bit()
455-
.tcie()
456-
.clear_bit()
457-
.teie()
458-
.clear_bit()
459-
.toie()
460-
.clear_bit()
461-
});
457+
self.disable_all_interrupts();
458+
462459
Ok(())
463460
}
464461

0 commit comments

Comments
 (0)