Page 1 of 1

How to use SPI from an interrupt?

Posted: Tue Nov 27, 2018 9:43 am
by jollytopper
Currently, program crashes if I try to do a spi_device_transmit.

I'm thinking about setting up a task with a very high priority and have the IRQ handlers send objects to a queue, which in turn wakes up the high priority task to do the processing. Are there any alternatives?

Re: How to use SPI from an interrupt?

Posted: Tue Nov 27, 2018 10:47 am
by PeterR
spi_device_transmit() queues a request, enables the SPI interrupt which should then run and start the SPI exchange.
spi_device_transmit() calls FreeRTOS routine which should not be called from an ISR.
Regardless spi_device_transmit() then waits for the transaction to complete as indicated by a item being placed on a queue.

(1) You should not wait on a queue from within an ISR, (2) clearly you should only call ISR safe routines from an ISR and (even if you survive all that), (3) the SPI driver may not even start sending depending on which interrupt you are making the request from and that interrupt's priority.

There are always alternatives. What do you want to achieve? Faster, simpler?
If you don't mind losing performance then poll for your event rather than use an interrupt.
You could dedicate a core to just sit there and check for interrupt on a GPIO. That approach could even be faster!
If you need performance and to share cores then the tasking approach recommended is simplest.
You can go faster (reduce the number of context switches) but you need to gain an appreciation of RT issues first and so try the tasking approach.

RT can hard but you will hit it sooner or latter (sooner in IDF and multicore!) & there are plenty of guides.

Re: How to use SPI from an interrupt?

Posted: Tue Nov 27, 2018 11:12 am
by jollytopper
Thanks for the response. My concern about my original point is that I'm worried while the high priority task is processing the IRQ, the other core may be running a task that disrupts this tasks function by maybe using some shared resource or something.

What I really would like to do is for have this task be the only thing that runs until it is finished. I don't want to have to add mutexes all over the place and try to manage the resource manually. Is there a simple way to suspend all other tasks but still allow SPI to function?

Re: How to use SPI from an interrupt?

Posted: Tue Nov 27, 2018 12:08 pm
by PeterR
Difficult to comment without knowing what these shared resource are - however if you are talking about shared application data then:

Your SPI task 1) fires up on ISR semaphore/event/queue, 2) reads application data, 3) launches SPI with copy of data, 4) waits for SPI completion, 5) Stores results somewhere
(3 & 4 are in the SPI transmit call).

Remember that if your ISR task is high priority then you may have jumped in front of someone else who may be using your shared resources.
So 2) and 5) may interrupt someone else who is performing an read/write.
Small chance maybe but give it a day or so & boom.

You must therefore guard shared data and/or use queues to exchange that data.
EDIT: Disabling the other tasks at 1) or 5) does not help because they may already be half way into the data. Hence the other tasks also have to play by the rules.