I am working on an application where two ATMega324P processors will exchange data over SPI bus by connecting the SPI lines directly together. But after reading the data sheet and doing some tests it doesn't seem easy to implement a fast and reliable data link. A special problem is when the ATMega SPI slave is doing some other task than receiving from the master, the master will not know about the delay and the slave will lose bytes that has been sent.
To overcome this problem I used a separate IO pin as an acknowledge from the slave to the master (5 lines total), and instead of polling the SPIF ("byte sent") in the master, it has to poll the IO pin ("slave received byte") before it can continue.
The transfer is two bytes at once, and the ack pin from the slave toggle state at each byte recieve.
Code for master:
spi16: ; Exchange var1, var2 over SPI cbi PORTB, 4 ; Slave select out SPDR0, var1 ; Send byte spi161: sbic PIND, 7 ; Wait for slave rjmp spi161 in var1, SPDR0 ; Read byte out SPDR0, var2 ; Send second byte spi162: sbis PIND, 7 ; Wait for slave rjmp spi162 in var2, SPDR0 ; Read byte sbi PORTB, 4 ; Deselect slave ret
Code for slave:
spi16: ; Exchange var1 and var2 with SPI master. out SPDR0, var1 sbi PORTD, 7 ; Set SPI master ack pin spi161: in sys, SPSR0 ; New char received from SPI? sbrs sys, SPIF0 rjmp spi161 ; No, wait for it in var1, SPDR0 ; Yes, get character out SPDR0, var2 cbi PORTD,7 ; Clear SPI master ack pin spi162: in sys, SPSR0 ; New char received from SPI? sbrs sys, SPIF0 rjmp spi162 ; No, wait for it in var2, SPDR0 ; Yes, get character ret
Theoretically when the MCU's are running at 18.4MHz and SPI clock speed is set to mclk/4, the transfer speed could be up to 575 kb/s, and when testing the code above I measured approx 300 kb/s. Important is, I haven't yet verified that the data was transferred without errors :)
After analyzing the code (execution order) I came to that all instructions for master and slave will add up (no overlap/paralell processing at all) and contribute to overhead in addition to the hardware shifting of the data. So these about 30 instructions would be 2uS wasting of time, and the hardware shifting of data are about 3.5uS, sum is 5.5uS for 16bit SPI transfer -> 364 kb/s. Measured value was 300 kb/s, so the polling/wait loops do not repeat many cycles.
(when the hardware is running (shifting out data), these two routines are polling/waiting all the time, so at least 8*4 instructions of code can be executed during this time, probably at both the master and the slave side)
1. Is it actually necessary to use feedback from slave to master to make AVR-AVR SPI link reliable?
2. Is it necessary to use the SS pin when there are only one slave, I believe the slave resets anyway when one char has ben transferred?
3. Any ideas on how to optimize the above routines to save some cycles, other code examples?