Skip to main content
YoungKim
Associate II
February 20, 2023
Solved

SPI slave interrupt is slow in STM32F767

  • February 20, 2023
  • 5 replies
  • 5767 views

I am working on SPI slave at NUCLEO-F767ZI.

I am using the interrupt and LL library. This is the RX handler:

void SPI1_Rx_Callback(void) {
 if (LL_SPI_GetRxFIFOLevel(SPI1) > LL_SPI_RX_FIFO_HALF_FULL)
 {
 // this is only for break point
 spi1_rx = LL_SPI_ReceiveData16(SPI1);
 return;
 }
 
 spi1_rx = LL_SPI_ReceiveData16(SPI1);
 spi1_tx = spi1_rx;
 LL_SPI_TransmitData16(SPI1, spi1_tx);
}

It just echos. The master sends 70 bytes data with no delay or gap until the end of the transmission. I put a break point in the line of 5 in the above code. When the master sends the data in 1MHz, it never go into the break point. But if I increase it to 2MHz, it stops in the break point. I think 2MHz is not that fast speed in SPI bus. How can I fix this?

  • sysclk: 96MHz
  • Here is SPI1 setting:0693W00000aHByoQAG.png
This topic has been closed for replies.
Best answer by FBL

Hello @YoungKim​ 

DMA can help to get faster data transfer rates. You can configure the DMA controller to transfer data between the SPI peripheral and a memory buffer.

Also, you may use DMA interrupts to trigger a callback function when a transfer is complete and set up the DMA to transfer data at a fixed number of bytes, which can be set to the maximum length of data that the master will send in each burst.

5 replies

KnarfB
Super User
February 20, 2023

Its easy to get interrupt latencies >1µs especially if you work with the HAL callback mechanism and not the bare IRQ handlers. A typical approach could read from RX FIFO in a while loop to drain the FIFO as quickly as possible. Another approach would be using DMA which seems preferrable here because the master sends short bursts (of predictable max. length?) of data.

hth

KnarfB

FBLBest answer
ST Technical Moderator
February 20, 2023

Hello @YoungKim​ 

DMA can help to get faster data transfer rates. You can configure the DMA controller to transfer data between the SPI peripheral and a memory buffer.

Also, you may use DMA interrupts to trigger a callback function when a transfer is complete and set up the DMA to transfer data at a fixed number of bytes, which can be set to the maximum length of data that the master will send in each burst.

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
YoungKim
YoungKimAuthor
Associate II
February 20, 2023

The SPI slave application should respond as soon as possible whenever it receives 16 bits register. therefore the DMA solution may not be suitable. Is my understanding correct?

And I can't use while loop solution because I am running multiple tasks by using FreeRTOS.

I want to use bare IRQ handler. I will try and get back here with the result. Thanks @KnarfB​  and @F.Belaid​ 

S.Ma
Principal
February 20, 2023

If the chosen STM32 has it, use DMA TX and RX channels in cyclic buffer mode.

This way, you mostly need to deal with NSS going up EXTI detection to digest the data transfer.

Some SPI with 32 bit HW FIFO aren't fully application optimized, thei TX FIFO being full by DMA in slave mode, when NSS goes up, and the only way to flush the FIFO is to RCC/SYS reset/reconfigure the SPI. These workarounds are necessary to get something decently working in the real world instead of the cycle count optimisation world.

YoungKim
YoungKimAuthor
Associate II
February 21, 2023

I found this from the RM0410 reference manual:

It is preferable for the slave to use DMA, especially when data frames are shorter and

bus rate is high.