Problem with SPI transactions on Arduino Due

I’m having problems with SPI transactions on Arudino DUE. Here are some facts about my project:

  1. ADC interrupts on pins 20 and 21
  • Uses SPI to read measured value
  • Starts a new measure cycle which will evenutally trigger another ADC interrupt
  • ADC is configured so that ~600 values per second are read.
  • Called SPI.usingInterrupt during setup
  1. FAN speed measurement interrupt on pin 13
  • Calls micros() and digitalRead()
  • DO NOT uses SPI
  1. Main loop
  • Reads twice the same block of 128 bytes from the EEPROM and compares it and if it’s different reports the error
  • Detects ADC timeout error, a condition when no ADC value is measured for the configured period of time (60ms).
  • Other tasks

I’m using SPI transactions in both ADC interrupt handler and main loop.

I’m getting regulary both EEPROM read verify and ADC timeout errors. ADC timeout can happen if ADC interrupt is not handled which means that no new ADC measure cycle is triggered.

Also note this:

  1. If I call SPI.usingInterrupt for port 13 (which doesn’t use SPI) I do get mentioned errors but very rarelly!?

  2. If I turn off ADC module there are no errors on EEPROM regardless if I called SPI.usingInterrupt for port 13 or not.

Do you have any idea what could be the reason for this?

Sure; the SPI library doesn't contain any interlocking that would prevent different SPI devices from interfering with each other. If your main code is reading the EEPROM (an external SPI eeprom?) and has gotten one byte into sending a three byte command, and you service an ADC interrupt that changes the SPI target, there is no way that the EEPROM code will recover. You probably need to disable the ADC interrupt during the "atomic" parts of the EEPROM access...

the SPI library doesn't contain any interlocking that would prevent different SPI devices from interfering with each other.

But I'm using SPI transactions. All my SPI code is executed within transaction:

SPI.beginTransaction(spiSettings);

...

SPI.endTransaction();

Also, I didn't forget to call SPI_usingInterrupt(intNum) for ADC interrupt. So, it should mask ADC interrupt during SPI transaction.

In the meantime I re-implemented SPI transactions - it is not as optional as official SPI library code because it masks all the interrupts not just one that actually use SPI.

I replaced SPI.beginTransaction(...) with:

noInterrupts();
SPI.setClockDivider(...);
SPI.setBitOrder(...);
SPI.setDataMode(...);

and SPI.endTransaction() with:

interrupts();

And it looks like it worked. I left it running over the night and I didn't get one single error while before I was getting the errors all the time.