Skip to content

Commit d4edece

Browse files
committed
[avr] Improved SPI speed on 16bit transfer.
From arduino/Arduino#2376 (comment) Quoting Andrew Kroll: [..this commit..] introduces a small delay that can prevent the wait loop form iterating when running at the maximum speed. This gives you a little more speed, even if it seems counter-intuitive. At lower speeds, it is unnoticed. Watch the output on an oscilloscope when running full SPI speed, and you should see closer back-to-back writes. Quoting Paul Stoffregen: I did quite a bit of experimenting with the NOP addition. The one that's in my copy gives about a 10% speedup on AVR.
1 parent 7ee84bd commit d4edece

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

libraries/SPI/SPI.h

+10
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ class SPIClass {
184184
// Write to the SPI bus (MOSI pin) and also receive (MISO pin)
185185
inline static uint8_t transfer(uint8_t data) {
186186
SPDR = data;
187+
/*
188+
* The following NOP introduces a small delay that can prevent the wait
189+
* loop form iterating when running at the maximum speed. This gives
190+
* about 10% more speed, even if it seems counter-intuitive. At lower
191+
* speeds it is unnoticed.
192+
*/
187193
asm volatile("nop");
188194
while (!(SPSR & _BV(SPIF))) ; // wait
189195
return SPDR;
@@ -193,16 +199,20 @@ class SPIClass {
193199
in.val = data;
194200
if (!(SPCR & _BV(DORD))) {
195201
SPDR = in.msb;
202+
asm volatile("nop"); // See transfer(uint8_t) function
196203
while (!(SPSR & _BV(SPIF))) ;
197204
out.msb = SPDR;
198205
SPDR = in.lsb;
206+
asm volatile("nop");
199207
while (!(SPSR & _BV(SPIF))) ;
200208
out.lsb = SPDR;
201209
} else {
202210
SPDR = in.lsb;
211+
asm volatile("nop");
203212
while (!(SPSR & _BV(SPIF))) ;
204213
out.lsb = SPDR;
205214
SPDR = in.msb;
215+
asm volatile("nop");
206216
while (!(SPSR & _BV(SPIF))) ;
207217
out.msb = SPDR;
208218
}

0 commit comments

Comments
 (0)