@@ -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