cancel
Showing results for 
Search instead for 
Did you mean: 

stm32L4S5, spi pause between 8-bit frames

heisenbug
Associate III

Hi all,

i am performing some 400bytes blocks transferts by SPI, at 16Mhz.

I have NSS off, so no CS up/down between frames.

From some testing, whatever system clock i set, or whatever spi clock i set, there is a fixed 4us time between 2 consecutive frames. This pause is of course very visible and heavy at 20Mhz spi clock, by scope something like:

__||||||||_____________||||||||______________|||||||_____

Transfer is done by LL_SPI_TransmitData8

If any help to reduce this delay between frames, would be very good, or at least to know i cannot reduce it in any way will be helpful too.

thanks a lot

 

 

25 REPLIES 25

Shouldn't your simple test include checking the status register (0x40003808 ?) and only sending new data when the TXE (Transmit Buffer Empty) bit is set?

heisenbug
Associate III

Hi greg,

thanks,

test changed as

		while (l--) {
			if (*(volatile uint8_t *)(0x40003808) & (1 << 1))
				*(volatile uint8_t *)(0x4000380c) = *p++;
		}

no improvements, always this 4us gap, that looks recurrent in the google search issues:

heisenbug_0-1707917629969.png

This seems really a limitation of the stm32 hw controller.

As you see, i am working on a specific spi protocol variant that requires CS to stay asserted over the full transfer. Anyway, to talk to this slave chip i still have available standard SPI option, so can try DMA in standard SPI mode.

Thanks all for now, but every helpful comment still welcome.

Right !

I check (on my cpu) "fifo not full" ...

+

to get optimum speed : need compile with optimizer -O2 .

 

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

Which STM32?

Disable interrupts before that snippet of code. Disable all DMAs (simply disable their clocks in RCC). Try to transmit a *constant* in an *infinite loop* (i.e avoid reading any variables from memory), plus what @gregstm wrote above.

Read out and check/post SPI registers content.

JW

Just : 120M core now, and the bus speeds (APB1 +2) ?

+

Show the SPI setting (in Cube) , just from screen shot .

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

This code snipped still writes one byte at a time and we have no reference for what the l variable is. Perhaps the calling code writes single bytes. Removing as much of your code logic as possible in order to show the problem in a simple example is beneficial during debugging. Try writing multiple bytes at a time.

Try writing an entire word and see if the output is different.

*(volatile uint32_t *)(0x4000380c) = 0x12345678;

 

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

Interesting. I am pretty sure that it should work much faster even without DMA (but using DMA is the best way).
a) Check yours compiler optimization level
b) Check you core clock (it is possible that SPI runs at 120MHz but core can be "underclocked" to slower speed)
c) Does "p" pointing to internal RAM or to some external ?
d) use 32bit access to SPI (write four bytes in one instruction/transaction)

Warning: you should not only check flags, but also react to their values. Simply write new data only if there is free space in buffer.

heisenbug
Associate III

Thanks all for the great help.

@waclawek.jan disabling interrupts brought me from 4us gap to 1.8us, Thanks a lot for this. SPI DMA is actually disabled.

@TDK writing a 32bit constant does not help, i still am near 1.8us gap.

 @Michal Dudka  i am actually forced to stay in Zephyr with default compilation options, that is -Os. (have to check if i can optimize differently with some board-related setting). I set 80->120Mhz clock, no improvement, maybe a bit worst,  gap is moved from 1.8us to 2.0us (test with removed p pointer, tested writing the 32bit constant). 

 

Continuing in investigations, thanks


@heisenbug wrote:

disabling interrupts brought me from 4us gap to 1.8us, Thanks a lot for this. SPI DMA is actually disabled



That looks like a good clue. "Empty" interrupt routine can take about 1 or 2 us. I guess so you have enabled some SPI related interrupt (even when you don't use it) which fires every time you load new data to SPI ... may by from RX etc. Check that.

I meant, disable *all* DMA. And I also had other suggestions there, re-read my previous post and follow *all* of them.

Or, better - start a new project, with nothing else, but setting up clocks, SPI pins and SPI itself, and try transmitting there.

You don't execute from QSPI, do you?

JW