Skip to content

Commit 8be3fba

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

File tree

1 file changed

+60
-61
lines changed

1 file changed

+60
-61
lines changed

drv/stm32h7-qspi/src/lib.rs

Lines changed: 60 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,51 @@ 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+
#[inline(always)]
189+
fn get_fifo_level(&self) -> Result<usize, QspiError> {
190+
let sr = self.reg.sr.read();
191+
192+
// Check timeout bit.
193+
if sr.tof().bit_is_set() {
194+
// Clear timeout bit and return.
195+
self.reg.fcr.modify(|_, w| w.ctof().set_bit());
196+
return Err(QspiError::Timeout);
197+
}
198+
// Check transfer error bit.
199+
if sr.tef().bit_is_set() {
200+
// Clear transfer error bit and return.
201+
self.reg.fcr.modify(|_, w| w.ctef().set_bit());
202+
return Err(QspiError::TransferError);
203+
}
204+
// Re-enable transfer error and timeout interrupts to make sure we
205+
// catch any future errors.
206+
self.reg
207+
.cr
208+
.modify(|_, w| w.teie().set_bit().toie().set_bit());
209+
Ok(usize::from(sr.flevel().bits()))
210+
}
211+
212+
/// Wait for the Transfer Complete flag to get set.
213+
///
214+
/// Note: this function returning does not guarantee that the BUSY flag is
215+
/// clear.
216+
#[inline(always)]
217+
fn wait_for_transfer_complete(&self) {
218+
// Disable FIFO threshold interrupt, and enable transfer complete
219+
// interrupts.
220+
self.reg
221+
.cr
222+
.modify(|_, w| w.ftie().clear_bit().tcie().set_bit());
223+
while self.transfer_not_complete() {
224+
// Unmask our interrupt.
225+
sys_irq_control(self.interrupt, true);
226+
// And wait for it to arrive.
227+
sys_recv_notification(self.interrupt);
228+
}
229+
}
230+
183231
fn write_impl(
184232
&self,
185233
command: Command,
@@ -238,24 +286,10 @@ impl Qspi {
238286
// off the front.
239287
let mut data = data;
240288
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());
289+
// Check for any errors
290+
let fl = self.get_fifo_level()?;
256291

257292
// How much space is in the FIFO?
258-
let fl = usize::from(sr.flevel().bits());
259293
let ffree = FIFO_SIZE - fl;
260294
if ffree >= FIFO_THRESH.min(data.len()) {
261295
// Calculate the write size. Note that this may be bigger than
@@ -293,18 +327,11 @@ impl Qspi {
293327
}
294328

295329
// 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-
});
330+
self.wait_for_transfer_complete();
331+
332+
// Clean up by disabling our interrupt sources.
333+
self.disable_all_interrupts();
334+
308335
Ok(())
309336
}
310337

@@ -375,22 +402,10 @@ impl Qspi {
375402
// perform transfers.
376403
let mut out = out;
377404
while !out.is_empty() {
378-
let sr = self.reg.sr.read();
405+
// Get the FIFO level if no errors have occurred.
406+
let fl = self.get_fifo_level()?;
379407

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());
392408
// Is there enough to read that we want to bother with it?
393-
let fl = usize::from(sr.flevel().bits());
394409
if fl < FIFO_THRESH.min(out.len()) {
395410
// Nope! Let's wait for more bytes.
396411

@@ -438,27 +453,11 @@ impl Qspi {
438453
// necessarily imply the BUSY flag is clear, but since commands are
439454
// issued into a FIFO, we can issue the next command even while BUSY is
440455
// 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-
}
456+
self.wait_for_transfer_complete();
450457

451458
// 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-
});
459+
self.disable_all_interrupts();
460+
462461
Ok(())
463462
}
464463

0 commit comments

Comments
 (0)