SPI slave unwanted loopback

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have an Arduino that I'm trying to do some SPI slave communications with. My SPI code gives me loopbacks that I simply cannot explain. I think there's something about the SPI bus that I do not understand.

SPI Configure

  //Configure SPI bus
  SPCR = (1<<CPHA);

  // turn on SPI in slave mode
  SPCR |= (1<<SPE);

  // now turn on interrupts
  SPCR |= _BV(SPIE);

SPI Interrupt

    UDR0=SPDR;
    SPDR=0xAA;

So all the routine does is send what it receives onward to the serial port, and then responds to every MOSI byte with a MISO 0xAA byte.

However, only the first byte of every SPI MISO packet shows up as 0xAA. The others are simply loopback copies of the input MOS. Why?

Is this somehow related to the fact that my CS pin is not going to zero after every single byte? That seems a little ridiculous.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It makes sense if the spi slave device has the miso and mosi tied together. (Like on some microchip a/ds for example). Same result if slave disconnected?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The ATMega328p on the Arduino is the slave. The master is an STM32 chip. The code above should be all that is necessary to configure the ATMega and then have it run in interrupt mode.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Is this somehow related to the fact that my CS pin is not going to zero after every single byte? That seems a little ridiculous.
What do you mean by this? Are you de-selecting the AVR in the middle of the transaction?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No,, that's the point, although admittedly I should have made that clearer. I'm not deselecting the chip between individual bytes, only between packets.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have no experience with SPI on the AVR but the atmega324P datasheet says to write the MISO data before reading the MOSI from SPDR.

Quote:
The Slave may continue to place new data to be sent into SPDR before reading
the incoming data. The last incoming byte will be kept in the Buffer Register for later use. The system is single buffered in the transmit direction and double buffered in the receive direction.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

atomicdog wrote:
I have no experience with SPI on the AVR but the atmega324P datasheet says to write the MISO data before reading the MOSI from SPDR.]

That's a somewhat moot point here, or at least it should be. In a series of bytes what comes after number one comes before number two...

In any case, the other way around doesn't work either.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know how the avr works in master mode, but slave mode is different. When the arm sends a byte, I assume you assert ss, and store the byte the data and clock start shaking. The slave sees ss edge, and must wait for the MASTER to clock in the data. I guess a flag goes hi when the byte is ready? The byte that was in the SPDR goes out while the new byte is coming in. If the master wants a resp from the slave, he probably sends a dummy byte to clk the resp back to the master.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A slave has to load SPDR before any transaction takes place so I think you should at least add

SPDR=0xAA;

to the config code because at present the first byte you send will be garbage.

Then at the end of every packet you have to "seed" SPDR with the first byte of the next packet. If you don't know that in advance then the master should treat the first byte as garbage.

I don't think that explains your problem, but it is an issue with the code.

______
Rob

Scattered showers my arse -- Noah, 2348BC.
Rob Gray, old fart, nature photographer, embedded hardware/software designer, and serial motorhome builder, www.robgray.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As I said, it makes no effective difference where the code is loaded, neither in practice nor in theory.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Using AVRs as SPI slave was a nightmare. :!:

The slave has no transmit buffer and thus it must place new data inside one half SPI clock.

Assuming the AVR runs at 8MHz, the SPI interrupt was 50 cycle short and no other interrupts used, then the fastest SPI clock of the master must be below:
8MHz / 50 / 2 = 80kHz.
Otherwise data was lost.

But if the slave runs other interrupts also, it must be many times slower (sum of time of all interrupts below one half SPI clock).

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The slave has no transmit buffer and thus it must place new data inside one half SPI clock.

I've got it working by preloading SPDR so it's ready to go, therefore the first byte works. You then get an interrupt when it's gone and I had the master insert a small delay here.

Once in the ISR I poll SPSR waiting for SPIF to go high then load the next byte.

Polling is much faster than interrupting but even then the master has to add a very small delay.

Of course this blocks the main code but for small frames it works well.

______
Rob

Scattered showers my arse -- Noah, 2348BC.
Rob Gray, old fart, nature photographer, embedded hardware/software designer, and serial motorhome builder, www.robgray.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I had the master insert a small delay here

That's the key thing with the half baked AVR8 SPI slave implementation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kubark42 wrote:
SPI Interrupt

    UDR0=SPDR;
    SPDR=0xAA;

So all the routine does is send what it receives onward to the serial port, and then responds to every MOSI byte with a MISO 0xAA byte.

However, only the first byte of every SPI MISO packet shows up as 0xAA. The others are simply loopback copies of the input MOS. Why?

Perhaps the ISR is somehow not being executed.
Also, I'm not sure what affect collisions have.

Edit: How much output are you getting from the serial port?

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles