cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA with variable lenght and timeout?

MReus.2
Associate II

Hi, my project is an ethernet server made with the STM32F411RET6. It receives and transmits data over SPI as a slave in 16bit mode, chip select disabled. At the moment i poll with HAL_SPI_Receive() and HAL_SPI_Transmit(). After transmit the master is triggered via gpio. My loop time is about 110us. For transmiting, there is a buffer in the ethernet part. So i cand send word after word. The problem is with receiving. I get sometimes 4 words in a row, sometimes only 1 word or something in between. No matter how many words arrive they should be sent fast, ideally once per loop at least. With HAL_SPI_Receive_DMA() and a buffer that fits 4 words, a 1 word package can be delayed. I would like to avoid interrupts. Is there a way to use the DMA but then poll and flush the buffer once a loop? I've seen HAL_SPIEx_FlushRxFifo() but i am not sure if this does what i need. Seems like it reads DR Register. I am new to Stm32 and CubeIDE and would like to understand whats going on instead of trying without knowing what i do. Any help is appreciated.

Thanks

Martin

3 REPLIES 3

I don't undestand what do you want to achieve, try to draw a diagram.

Cube/HAL is open-source, so you can take a look what do those functions do. Or simply ditch Cube and write your program normally.

JW

MReus.2
Associate II

Thanks for your answer. Please excuse my confused question, i guess it reflects how confused i was by all the options.

I am basically looking for a way to buffer the packages coming from the spi master. But i cannot alwayswait till the dma buffer is full. There might be times where only one packace arrives which still should be sent in a rwasona le amount of time. My thought was to check the dma buffer once per loop. I am not sure how to do this. After searching a little bit more i think of something like this.

HAl_SPI_Reiceive_DMA(&hspi2, buffer);

// do some stuff in the mIn loop

// if dma buffer is not full when new loop starts, check if something has arrived and send it

HAL_DMA_Abort(hspi2_rx);

if (buffer != empty) {send stuff();}

// start dma again

HAl_SPI_Reiceive_DMA(&hspi2, buffer);

I hope this explains a little bit better what i try to do. At the end i want to avoid that the master has to wait to send packages. With polling and my current loop time the slave can only handle one package every 110us.

Thanks for your help

gbm
Lead III

There is no such thing as SPI timeout. The master device decides on the amount of data and transfer speed - you get the exact number of frames you want to read in the period decided on by SPI clock frequency. There is no point in checking how many frames were received before the transfer is complete.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice