cancel
Showing results for 
Search instead for 
Did you mean: 

How to handle SPI DMA (50Mbits/s) and While() loop?

SFeje
Associate II

Hello!

I use SPI DMA (NSS always down) communication between 2pcs H743ZI.

Everything work fine, till I don't change SPI speed to higher frequency (6MBits/s)

It seems like, the DMA interrupts don't let enough time for While() to run.

EXAMPLE:

...
uint8_t pnSPI2Values_rx[8] = {100, 0, 0, 0, 0, 0, 0, 0}; 
uint8_t pnSPI2Values_tx[8] = {100, 1, 2, 3, 4, 5, 6, 7}; 
 
int main(void)
{
  ...
  if(HAL_SPI_TransmitReceive_DMA(&hspi2,   (uint8_t*)pnSPI2Values_tx, (uint8_t 
  *)pnSPI2Values_rx, 8) != HAL_OK)
  {
  	 Error_Handler();
  }
   ...
  while (1)
  {
     function();
  } 
}

With prescaler 256 = 1.562 Mbits/s I can do my While() funcion too.

The function() do a lot of things, and also handle SPI RX values and change the TX array values.

For example from:

- function() STEP1 to STEP10 the time is 7.8ms - prescaler 256 = 1.562 Mbits/s

- function() STEP1 to STEP10 the time is 12.5ms - prescaler 128 = 3.125 Mbits/s

- function() STEP1 to STEP10 the time is NEVER - prescaler 64 = 6.25 Mbits/s

The communication is still stable with good values, only I can't change any TX values under runtime, because it happens in While() and I think its by the DMA interrupts.

In the end I want to run SPI with 50MBits/s and the whole program with 400MHz core clock.

I use STM32CubeIDE

Here are some pictrues:

0690X00000AABxVQAX.png0690X00000AABxLQAX.png0690X00000AABxGQAX.png

The main thing is that I do some measurement with ADC DMA on processor 1 (slave), and sending it with SPI DMA to processor 2 (master), then it changing PWM duty cycle. And this change happening in While() loop.

-What is the best solution?

-Does it help if I disable the half interrupt in SPI? (I don't know how to do it, but its possible)

-Disable both interrupts? Does it will occur sync problem with the data flow?

-Using SPI with timer?

Thanks for any help!

Szilveszter

3 REPLIES 3

The HAL abstraction is pretty heavy, but would have thought it would still function.

Not sure how the DMA vs while() loop interacts for a single firing.

Toggle a GPIO in the IRQHandler and see if it is saturating there. Perhaps signal on entry/exit so you can see if you're eating too much time in those routines.

Watch for things in your call-back functions which take excessive time, or BLOCK.

For high rates you might want to hand-craft the code with an eye to cycles, interactions, and DMA HT/TC appropriateness.

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

no NSS means no synchronisation in case of bus glitches occuring.

I would build ADC in a cyclic DMA buffer and use the half/full transfer interrupt to use another DMA channel to push a block of data by SPI.

The SPI throughput (MHz) must be fast enough to flush faster than the ADC fills half buffer.

Toggle NSS to tell this is a new block of data.

SPI Slave should run a cirular mode with same buffer and get interrupt in half/full transfer received, or use EXTI on NSS rise edge to save the incoming block.

SFeje
Associate II

Thanks! I would try these.