Richard Serge

Double-buffered SPI: Detecting last byte shifted

Discussion created by Richard Serge on Oct 21, 2010
Latest reply on Feb 12, 2014 by Jose ..

I've had this question/problem before and I've always been able to work around it, but I'm never happy with my solution. I'm still not.

 

I've got a GB60, doing an SPI transfer to an SD card at 8.67MHz. I've also got a high priority interrupt pounding me at 22KHz. What I'm trying to do is to exit from the SPI routine as quickly as possible once the last byte is shifted out, but detecting when this last byte is gone is what's bugging me. (Yes, I can delay X number of cycles to insure the transfer is over with but surely there is a more efficient solution.) The SPTEF bit tells me when the Tx buffer can accept another byte, and the SPRF bit tells me when a byte is shifted in and/or when the current byte in the shifter has been shifted out. But I can't tell when that last byte is in the process of being shifted out. (Can I?) Here's the code that does the transfer:

 

SPITXB MOV X+,SPID  ;(5) SEND DATA. BRCLR SPTEF,SPIS,* ;(5) WAIT FOR TX BUFFER EMPTY. DBNZA SPITXB  ;(4) LOOP FOR ACCA BYTES (IF A WAS 0 THEN SENDS 256). TST SPID  ;CLR SPRF (WAS SET WHEN SPTEF WAS SET). BRCLR SPRF,SPIS,* ;WAITS FOR TX OF LAST BYTE. RTS

 

 

This works until an interrupt comes along (say just prior to the TST instruction) that steals enough cycles so that the last byte is already gone and the next-to-last line hangs since SPRF has already been set, and cleared. I *could* set & clear the interrupt mask in the loop but doing so would reduce the maximum transfer rate that I have now, and I need all the speed I can get at this point in my code. Also, I'd like something that doesn't block interrupts so I can still use the code later on when I have something with a much slower SPI clock.

 

Suggestions would be welcomed.

Outcomes