diff options
| author | Cristian Maglie <c.maglie@bug.st> | 2014-10-20 19:46:08 +0200 | 
|---|---|---|
| committer | Cristian Maglie <c.maglie@bug.st> | 2014-11-25 15:49:17 +0100 | 
| commit | d4edece7e6698e7687dd8dec1831f9756c8b0017 (patch) | |
| tree | b4866effbeb5895f00ab6e620c58d9c5d27263c0 | |
| parent | 7ee84bdb1eb39dde646ed1859d9fe7d37d4584bf (diff) | |
[avr] Improved SPI speed on 16bit transfer.
From https://github.com/arduino/Arduino/pull/2376#issuecomment-59671152
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.
| -rw-r--r-- | libraries/SPI/SPI.h | 10 | 
1 files changed, 10 insertions, 0 deletions
diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index b54e2df..24ebc12 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -184,6 +184,12 @@ public:    // Write to the SPI bus (MOSI pin) and also receive (MISO pin)    inline static uint8_t transfer(uint8_t data) {      SPDR = data; +    /* +     * The following NOP introduces a small delay that can prevent the wait +     * loop form iterating when running at the maximum speed. This gives +     * about 10% more speed, even if it seems counter-intuitive. At lower +     * speeds it is unnoticed. +     */      asm volatile("nop");      while (!(SPSR & _BV(SPIF))) ; // wait      return SPDR; @@ -193,16 +199,20 @@ public:      in.val = data;      if (!(SPCR & _BV(DORD))) {        SPDR = in.msb; +      asm volatile("nop"); // See transfer(uint8_t) function        while (!(SPSR & _BV(SPIF))) ;        out.msb = SPDR;        SPDR = in.lsb; +      asm volatile("nop");        while (!(SPSR & _BV(SPIF))) ;        out.lsb = SPDR;      } else {        SPDR = in.lsb; +      asm volatile("nop");        while (!(SPSR & _BV(SPIF))) ;        out.lsb = SPDR;        SPDR = in.msb; +      asm volatile("nop");        while (!(SPSR & _BV(SPIF))) ;        out.msb = SPDR;      }  | 
