cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 SPI management

Posted on March 10, 2016 at 21:14

Hi all,

what's the best way to manage a full-duplex SPI slave interface, running on STM32F4 + RTOS?

I tried 3 different strategies, but none of them seem suitable for high performance.

What I have:

- 5 pins SPI: miso mosi clk cs irq

- 2x DMA: Tx (normal?) and Rx (circular?)

- 2x Buffers: Tx and Rx

- Interrupts on SPI (TXE, RXNE, ...), DMA (TC, HT, ...)

- 2x Tasks: ParseRxBuffer, ParseTxBuffer

- queues, semaphores, etc...

q1: chip select in HW or in SW? (I think in HW)

q2: even if working in HW, should interrupt be used for CS line? (I think so)

q3: can I use HW CS and interrupt on that line? (I hope so)

I think DMA on RX should be always running, while DMA on TX should be enabled only when needed

q4: which event should be used to wake RxBufferParserTask? Since there is no ''idle interrupt'' on SPI peripheral. (I think: interrupt on CS line). I tried RXNE interrupt, but leads to stop&start DMA on RX. Not so good. I heard also about timers on clock line...

I expect, during TX, sending dummy data (0xFF) while nothing needs to be sent (SPI Master put CS low). I expect also sending TX buffer if something needs to be sent (IRQ line put low).

q5: can I change ''on the fly'' TX DMA buffer content, if a transmission is needed while CS line is already low?

Thanks for knowledge sharing 🙂

jerry

ps: both frames (Master to Slave, and slave to Master) start with an header containing frame length...
2 REPLIES 2
TDK
Guru
Posted on March 11, 2016 at 05:23

I do something very similar.

q1: Use the hardware (NSS) pin, it makes everything easier.

q2: You'll have to decide how you need the slave to respond.  It's not going to be fast enough to respond immediately.  If the slave can process when the CS pin goes high, then do your processing there and ready the data in the TX buffer.

q3: I don't think so--at least not on the same pin.  In order to use the NSS hardware pin, it'll have to be in AF mode.  In order to use an interrupt, it needs to be in interrupt mode.  Easy solution: just tie two pins together and use the second one to trigger EXTI interrupts and leave the first as the NSS pin.

q4: Yes, rising edge on the CS is a good option, if it works for your application.  Other options include the DMA HalfTxComplete and TxComplete events.

q5: Mostly yes.  As long as you change it before it gets loaded into the SPI peripheral.  Note that when you start the DMA RX/TX SPI routine, the first byte gets loaded immediately.

In any case, that should all yield a decent SPI handling routine.  Note that DMA is going to be more efficient for longer transfers.  The overhead is constant regardless of how much you're sending.

Since it seems you will not always be using the TX, I would only enable it when needed, as you suggest.  Whereas RX should presumably always be enabled.  And a circular buffer to handle it seems correct.  You can use the DMA's NDTR register to figure out how many bytes have been transferred and handle them as they come in.  You'll need a way of tracking which bytes have been processed and which have not.  I use a pointer to the next byte to process.

Good luck!

If you feel a post has answered your question, please click "Accept as Solution".
Posted on March 11, 2016 at 11:31

Hi Tim,

cannot use another pin (together with CS). So, interrupt ''on CS'' cannot be used to wake RxBufferParserTask.

Interrupt on RXNE, or switch to SW CS?

Thanks

j