Is SPI.transfer(buffer, size) a blocking function


Does anyone know if SPI.transfer(buffer, size) is a blocking function? I am looking to transfer an array of data out using SPI, but while the data is being transferred I want to be preparing the next array. If SPI.transfer(buffer, size) is blocking then I can't use it :(

I guess I'll be looking at transferring one array byte at a time and using interrupts to transfer subsequent bytes.

I'm new to this (coming back after a very long time away from embedded programming) so would appreciate any comments or alternative ideas.


Why didn't you look at the source code?

  inline static void transfer(void *buf, size_t count) {
    if (count == 0) return;
    uint8_t *p = (uint8_t *)buf;
    SPDR = *p;
    while (--count > 0) {
      uint8_t out = *(p + 1);
      while (!(SPSR & _BV(SPIF))) ;
      uint8_t in = SPDR;
      SPDR = out;
      *p++ = in;
    while (!(SPSR & _BV(SPIF))) ;
    *p = SPDR;

Yes, the function is blocking. But, really, how long does it take to send the data?

That depends on your SPI clock prescaler settings... On many Arduinos (ATmega ones) the SPI hardware only stores/holds a single byte at a time. You can use SPI interrupts to manage the flow of bytes to/from a buffer, but if you are running SPI at high speed (8MHz for instance), this cannot work as the interrupts are slower than the SPI hardware!

Processors with an actual FIFO in their SPI hardware can do better, I think the Due has this, but might be mis-remembering.

How much data are you sending? A transfer takes 17 clocks, just over 1uS if you set the SPI clock divisor to 2 and don’t use interrupts to signal when it is done:

SPDR = array[x+0]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
SPDR = array[x+1]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;

SPDR = array[x+2]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;

SPDR = array[x+3]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;

SPDR = array[x+4]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;

That is totally blocking, but takes just 5.3uS.
You could mix that up, use 1 instance of SPDR = array[x+0];
and while 17 (or more) clocks go by be doing the other array preparation.

for (x=0; x<100; x=x+1){
SPDR = array[x]; // send a byte
array1[x] = (whatever the prep is that take several clock cycles); 
} // the for:loop counting/comparing takes a few clocks as well

Watch it on a protocol analyzer and see if the SCK line has a little break between bursts of 8 clocks at 8 MHz, that’ll be your array1 processing and the for loop doing and occasionally the millis/micros counter doing their thing.