cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4xx Using DMA Transfer Complete Callback with SPI

elmood
Associate III
Posted on February 10, 2016 at 22:18

I just posted this message but it seems to have gotten lost by the forum system. :(

Anyway, I'm using SPI with DMA to talk to a SPI flash chip. I'm using the TXRX complete callback handler to detect when a transfer is finished and change internal states so the application can be notified when stuff is done.

But in some cases I use the TXRX complete callback to start new transfers. For instance on my particular chip the write enable requires a 1 byte transfer followed by the actual data to write. So I start the first transfer, and when it's done and the callback gets called I try to start the next transfer. But the SPI module never transmits anything the second time, nor does it ever complete.

Is there some kind of weird limitation of doing what I'm doing? I'd prefer not to have a task within my SPI flash module, and would rather rely on the callbacks to drive everything for simplicity and maximum throughput.

Any help would be greatly appreciated!
8 REPLIES 8
mark239955_stm1
Associate II
Posted on February 10, 2016 at 23:24

The TXRX complete callback is probably being executed by the DMA interrupt handler, so the CPU is still in the Handler state when it fires.

You shouldn't need a separate task to manage repeated accesses to the SPI driver, just some RTOS elements like semaphores and a loop construct.  For example, you could wrap the HAL SPI driver with an RTOS layer so that you take a binary semaphore just before you start a transaction, and release the semaphore in the RXTX complete callback.

re.wolff9
Senior
Posted on February 11, 2016 at 01:03

Consider the possibility that the interrupt happens BEFORE the whole SPI sequence is finished. That would mean that if you start doing the next transfer things may interfere. 

mark239955_stm1
Associate II
Posted on February 11, 2016 at 01:33

Only if ST haven't made a complete hash of their SPI HAL driver.

I'll acknowledge that implication != fact, but given a callback named ''TXRX Complete'', the implication is that it's firing from either the SPI Rx interrupt or the SPI Rx DMA interrupt.

elmood
Associate III
Posted on February 11, 2016 at 03:05

I don't really want an RTOS... I just want to start the next transfer once the previous one is complete without requiring any timers or polling of this module. Starting a transfer when the other one is complete seems like a good way to schedule that as tightly as possible, but clearly there is something I'm doing wrong.

As for the SPI completing, I confirmed that the SPI clock has stopped toggling well in advance (3us or so) of the completion callback being called.

I traced the callback all the way into the NVIC stuff but the DMA / SPI callbacks seem to happen right at the end of the other housekeeping tasks so at least these are not clearing something that I'm setting by trying to make another transfer. However I didn't dig into the actual NVIC code yet to see if there is anything else there.

An example of how to properly do this would be great. I'd like this module to be timed off its own completion instead of needing outside prodding.

mark239955_stm1
Associate II
Posted on February 11, 2016 at 11:45

If you want to avoid using an RTOS, then one technique that would work is to set a ''busy'' flag just before you fire off the SPI transaction, and clear the ''busy'' flag in the ''complete'' callback.  Then you can poll the state of the ''busy'' flag in a loop somewhere and when it polls as clear you can fire off your next SPI transaction.

elmood
Associate III
Posted on February 12, 2016 at 17:43

Okay, so what you're saying is that it's impossible to start a new transfer in the transfer complete callback? I would like to understand the reason for this because it seems rather lame that I would have to wait until a polling routine comes around to make best use of the bus bandwidth like this.

TDK
Guru
Posted on February 13, 2016 at 02:37

It's definitely possible to do this.  I do it now with UART DMA transfers, but the concept would be the same for SPI.  Likely there is something you're not setting up correctly in your code, but as you didn't post it, that's just a guess.

If DMAX_StreamY_IRQHandler isn't being triggered the second time, you haven't set something up correctly.  Possibly you haven't cleared the bit, which HAL_DMA_IRQHandler does for you if you use it.

If you feel a post has answered your question, please click "Accept as Solution".
TDK
Guru
Posted on February 13, 2016 at 02:37

duplicate message oh god why is this forum software so bad

If you feel a post has answered your question, please click "Accept as Solution".