How to use SPI from an interrupt?

jollytopper
Posts: 30
Joined: Mon Sep 17, 2018 6:39 am

How to use SPI from an interrupt?

Postby jollytopper » Tue Nov 27, 2018 9:43 am

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?

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: How to use SPI from an interrupt?

Postby PeterR » Tue Nov 27, 2018 10:47 am

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.
& I also believe that IDF CAN should be fixed.

jollytopper
Posts: 30
Joined: Mon Sep 17, 2018 6:39 am

Re: How to use SPI from an interrupt?

Postby jollytopper » Tue Nov 27, 2018 11:12 am

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?

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: How to use SPI from an interrupt?

Postby PeterR » Tue Nov 27, 2018 12:08 pm

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.
& I also believe that IDF CAN should be fixed.

Who is online

Users browsing this forum: Google [Bot], tomatosoup and 129 guests