2010-09-16 11:57:37     SPI read fails in PIO mode

Document created by Aaronwu Employee on Aug 23, 2013
Version 1Show Document
  • View in full screen mode

2010-09-16 11:57:37     SPI read fails in PIO mode

Scott Wagner (UNITED STATES)

Message: 93507   

 

Hello,

 

I am using the BF548 SPI controller 2, starting out my development using PIO access for ease of debugging before I go on to a more sophisticated interface.  I am communicating full duplex, Mode 3, 500 kHz with my peripheral.  I find that reads of the spi bus do not seem to work properly.

 

In particular, the spi_u8_reader() function of ./drivers/spi/spi_bfin5xx.c looks like:

 

static void bfin_spi_u8_reader(struct master_data *drv_data)

{

u16 tx_val = drv_data->cur_chip->idle_tx_val;

 

/* discard old RX data and clear RXS */

bfin_spi_dummy_read(drv_data);

while (drv_data->rx < drv_data->rx_end) {

write_TDBR(drv_data, tx_val);

while (!(read_STAT(drv_data) & BIT_STAT_RXS))

cpu_relax();

udelay(4);

*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);

}

}

 

Note the evil udelay(4) highlighted in the code, which I inserted.  Without this delay, the data in my read buffer is not what I see coming back from my device on the SPI bus; it is either 0 or the value of the last transmitted bit (if I'm in full duplex mode and thus using the bfin_spi_u8_duplex() function.)  If I insert the udelay(4), I get the correct data back.  If I insert udelay(2), that does not seem to be sufficient and I get the same result as no udelay().  Strangely enough, if I put the udelay(4) after the read_RDBR(), that works too.

 

Does anyone have any idea what's happening here?  I can't imagine that this is a new problem, and I don't think my usage deviates in any meaningful way from plain vanilla spi communication.

 

Thanks for any insight ...

 

-Scott Wagner

QuoteReplyEditDelete

 

 

2010-09-16 13:33:54     Re: SPI read fails in PIO mode

Scott Wagner (UNITED STATES)

Message: 93513   

 

I note that this behavior does not happen in the interrupt-driven PIO case using bfin_spi_pio_irq_handler() - possibly because there is a lot of stuff that happens between the check of BIT_STAT_RXS and the read of RDBR.  In the polled PIO case above, the processor simply spins on reads of these two registers.

 

Hmmm ... does everyone else in the world use interrupt-driven PIO or DMA?  Or perhaps this has something to do with the relatively slow baud rate I'm using (500 kHz?)

 

-Scott

QuoteReplyEditDelete

 

 

2010-09-16 15:07:03     Re: SPI read fails in PIO mode

Scott Wagner (UNITED STATES)

Message: 93515   

 

OK - my last post was in error.  The spi transfer worked in PIO interrupt mode only because I had debug turned on, and the printk of e.g. "read: write_TDBR" is time-consuming enough to introduce the delay.  Without debug, and with no delay, I see the same behavior as in polled PIO (ref. original message), and if I introduce a udelay(3) after

 

/* wait until transfer finished. */

while (!(read_STAT(drv_data) & BIT_STAT_RXS))

cpu_relax();

udelay(3);

in bfin_spi_pio_irq_handler(), then I have error-free transfers.  (Of course, now I have introduced a nasty spin in interrupt context!)  So, whatever is going on, it is not strictly tied to PIO polled mode.

 

Still stumped ...

-Scott

QuoteReplyEditDelete

 

 

2010-09-16 15:18:50     Re: SPI read fails in PIO mode

Mike Frysinger (UNITED STATES)

Message: 93516   

 

you could try changing it to:

 

while ((read_STAT(drv_data) & (BIT_STAT_TXS|BIT_STAT_SPIF|BIT_STAT_RXS)) != (BIT_STAT_SPIF|BIT_STAT_RXS))

QuoteReplyEditDelete

 

 

2010-09-17 12:29:34     Re: SPI read fails in PIO mode

Scott Wagner (UNITED STATES)

Message: 93558   

 

Hi Mike et. al.

 

Thanks, Mike, for the reply.  I tried your suggested code; reads now succeed without the udelay().  However, there are some remaining questions before I'm satisfied with this:

 

1) Why is this necessary?  Especially in the data interrupt case, I would expect that I would not get a data interrupt until the data is really ready.  Would you please explain?

 

2) Since the while loop occurs in interrupt context, the effect is that we're spinning while atomic, waiting for a hardware event.  This is really somewhat dangerous, in my opinion - we're vulnerable to the processor getting hung in the IRQ for a long time (microseconds), or maybe forever in a pathological case.  So, I guess before committing this we should consider something a bit safer - do you agree?

 

3) Sort of on the same subject as (2), is the time we will spin in the while loop at all deterministic?  Can you tell me how long it will be after the irq is asserted before the condition BIT_STAT_TXS == 0; BIT_STAT_SPIF == 1; BIT_STAT_RXS == 1?

 

4) Why is this not what is in the distribution spi_bfin5xx.c already?  Why has nobody else noticed this?  Is this a change we should commit for the public release?

 

Thanks

 

Scott

QuoteReplyEditDelete

 

 

2010-09-17 12:42:26     Re: SPI read fails in PIO mode

Scott Wagner (UNITED STATES)

Message: 93560   

 

Whoa!  Stop the presses!  Mike's suggestion did not work!  (I still had debug code in my driver which was effectively causing a udelay()).

 

So, we're still back where we started - and to my four questions above, I add "What's going on??"

 

Thanks for any assistance or insight!

 

-Scott

QuoteReplyEditDelete

 

 

2010-09-17 13:47:46     Re: SPI read fails in PIO mode

Mike Frysinger (UNITED STATES)

Message: 93564   

 

are you using PIO as in you've enabled the status interrupt in the pio_interrupt platform resources ?  if not, then there is no interrupt.  the duplex() function is run in a workqueue, it is not run in interrupt context.

QuoteReplyEditDelete

 

 

2010-09-20 10:57:09     Re: SPI read fails in PIO mode

Scott Wagner (UNITED STATES)

Message: 93634   

 

Hi Mike,

 

The behavior I describe occurs both in pio / polled mode (where the spi_u<x>_duplex() and spi_u<x>_reader() functions are used) and in the pio / intrerrupt mode (where the irq handler is used.)  I'm sorry - in my earlier post I was unclear about the fact that I have switched to pio / interrupt mode, using bfin_spi_pio_irq_handler().

 

I have not tried (and cannot use) DMA mode because my slave device in communicating full-duplex.

 

I guess it makes sense that I see the same behavior in the ISR as in the polled / PIO case - both are running approximately the same code, and the behavior of each is about the same from the point of view of the Blackfin SPI controller hardware.

 

Regards,

 

Scott

QuoteReplyEditDelete

 

 

2010-09-20 20:00:11     Re: SPI read fails in PIO mode

Mike Frysinger (UNITED STATES)

Message: 93639   

 

have you tried slowing things down ?  or does the slave client require that exact speed ?

 

QuoteReplyEditDelete

 

 

2010-09-21 10:30:14     Re: SPI read fails in PIO mode

Scott Wagner (UNITED STATES)

Message: 93702   

 

I have tried speeds from 500 kHz to 4 MHz.  Because my spi prototype wiring is a 20 cm tangle of wires tacked between boards, I'm not comfortable going faster than that.  Behavior is pretty much the same in all cases, although I haven't tried correlating minimum required udelay() with speed.

QuoteReplyEditDelete

 

 

2010-09-21 16:04:00     Re: SPI read fails in PIO mode

Mike Frysinger (UNITED STATES)

Message: 93711   

 

500 kHz - 4 MHz is not slower

Attachments

    Outcomes