cancel
Showing results for 
Search instead for 
Did you mean: 

How to use SPI + DMA with software CS?

jb
Associate II

Hi All,

I am trying to use SPI+DMA in stm32f401 nucleo 64.

SPI + DMA is working successfully on both transmit and receive data. I configured spi + dma in software cs since I have multiple slaves, but that means I have to pull the gpio up and down for every transmission.

I am not sure if I did/understood it correct, this way, gpio would not pull up and down by itself while the processer is running other code, so I will have to call spi + dma with gpio inside a while loop. It feels to me that does not make any difference than using polling.

Is there a way to get pass this ? or am i doing this correctly?

Thanks in advance!

5 REPLIES 5
TDK
Guru

> Is there a way to get pass this ? or am i doing this correctly?

A better solution would be to implement the transfer complete routine to pull up CS. That way you don't need to worry about it and your CPU can do other things. The transfer complete function is called before the state is set to ready. Your main loop can just poll the status to see when it's ready for another transfer.

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

If you are SPI master and have SPI and DMA active, you need only from main loop to trigger the transaction(s).

If you want the SPI to run in the background with RTOS or bare metal implementation, I can suggest my past implementation as Interrupt based state machine. Say you have 3 slaves with sequentially 3 transactions queued and you want 10usec delay between each of them:

  • disable the interrupt and kick the state machine by forcing NSS1 low and start SPI+DMA transfer. Setup DMA_RX transfer complete interrupt
  • When the DMA_RX interrupt kicks in, rise NSS1 and set a timer to trigger an interrupt 10usec later
  • With timer interrupt, flip NSS2 low and kick the SPI + DMA transfer, set the DMA_RX transfer complete interrupt
  • When the DMA_RX kicks in, rise NSS2 and set timer for 10usec kick back
  • rinse and repeat....

This is a very simplified scheme, you can have a queue of transfers to reenable this smart SPI and you can disable it when the queue is empty.

All these transactions will run with brief interrupt routines while the main loop does something else.

This scheme can work with multiple SPIs running in the background, where multiple HW SPI gets full use of them instead of time multiplexing them...

S.Ma
Principal

Note: Such implementation can't be found in HAL examples.

What hardware are you talking too that expects CS to bang up/down for *every* byte?

ST's implementation really doesn't function helpfully for you.

I don't think DMA is going to help you here.

If you really have to deal with this hardware you might consider generating a pattern buffer you can DMA to GPIO pins.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
prain
Senior III

Warning: don't use DMA transfer complete interrupt​, to change slave selection. Use SPI transfer complete interrupt instead.

​Also be aware of assertion/de-assertion times before and after transfer. some slaves need a few time after assertion of CS pin to receive your data and after your transfer completes. check slave datasheet for required timing.