cancel
Showing results for 
Search instead for 
Did you mean: 

SPI slave interrupt is slow in STM32F767

YoungKim
Associate III

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
1 ACCEPTED SOLUTION

Accepted Solutions
FBL
ST Employee

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 Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

5 REPLIES 5
KnarfB
Principal III

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

FBL
ST Employee

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 Accept as Solution on the reply which solved your issue or answered your question.

YoungKim
Associate III

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

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
Associate III

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.