SPI bus access control between threads

I have a photon which uses SPI bus to connect to a TFT screen and to an SD card. In addition, there is a SPI FRAM which holds an event queue. Each peripheral has a unique CS pin. The event queue is accessed using the PublishQueueAsyncRK library which publishes from a separate thread from the application. I have noticed that during periods where I might queue a number of events from the application thread and immediately after that I might read from SD and write to TFT, that I might see either corruption of the event data, or corruption of images drawn from SD to screen or primitives drawn directly to the TFT. Aside from using delay() in the application thread immediately after the queuing of an event are there any simple ways to avoid clashes between threads competing to use the SPI bus?
I am thinking checking for all CS pins high - but this would not be atomic? PublishQueueAsync is already using a mutex.
@rickkas7 @ScruffR

You absolutely must use SPI transactions (SPI.beginTransction and SPI.endTransaction). You need to put them around any group of operations that can’t be interrupted by another SPI transaction on the same bus. The SpiFlashRK library uses them, so one of the other libraries probably doesn’t.

@rickkas7 Thanks for the quick reply. I have used SPI.beginTransaction and SPI.endTransaction - I have gone through all the source (libraries) looking for “SPI.” and nothing except for SdFat - which I had not gone through. I hadn’t understood that beginTransaction exclusively claimed the SPI bus since it is separate from the CS pin reset and set.

Should have re-read this:

In addition to reconfiguring the SPI peripheral, beginTransaction() also acquires the SPI peripheral lock, blocking other threads from using the selected SPI peripheral until endTransaction() is called. See Synchronizing Access to Shared System Resources section for additional information on shared resource locks.

It is required that you use beginTransaction() and endTransaction() if:

  • You have more than one SPI device and they have different settings (speed, bit order, or mode)
  • You have more than one thread or use SPI from a Software Timer

I haven’t checked recently, but in the past there was an issue that the define that SdFat checked to see if SPI transactions were available was not set on Particle. I’d definitely look there first. It may be fixed (it’s been a while, and I might have misremembered) but it’s as good of a place to start as any.

1 Like