Skip to main content
sergey239955
Associate II
January 30, 2020
Question

STM32L4 - DMA with SPI in slave mode doubles the first byte loaded into DMA

  • January 30, 2020
  • 26 replies
  • 5662 views

We are migrating from STM32F103 to STM32L4. The code architecture is the same, as the product basically is the same. We just upgrade the micro.

We have an SPI that is configured in slave mode, and a device that supplies clock to the SPI. DMA is used to feed the SPI with data. What we do is we first init SPI, then we init and load DMA with data, then we enable DMA request and a few milliseconds later we enable the clock source. Everything is very basic and works absolutely fine on STM32F103.

We found that the STM32L4 with practically the same code (save for specifics of peripheral configuration) doubles the very first byte loaded into DMA. Say, if you load a string of 5 bytes 0x1, 0x2, 0x3,0x4 and 0x5, the SPI will output 0x1, 0x1, 0x2, 3, 4, and 5. Whatever the first byte is, it will be doubled (we suspect by SPI) because the DMA count is correct. Meaning that the DMA will stop after 5 bytes, while the SPI will output 6 bytes.

Anyone saw anything similar to it? We are positive that it is not our bug. It is almost impossible to do even if we wanted to. And the same code works fine in STM32F103.

This topic has been closed for replies.

26 replies

sergey239955
Associate II
February 3, 2020

I read the DMA and SPI registers after I initialize them for the transfer. Here are the values, but I see nothing there that doesn't match the configuration in the code that I provided, and nothing suspicious

SPI CR1 0x000002C0
SPI CR2 0x00000702
SPI SR 0x00001800
DMA CCR 0x00003091
DMA CNDTR 0x00000020
DMA CPAR 0x40003C0C
DMA CMAR 0x2001D1C0

Any ideas?

As I said, the strangest thing is the behavior changes with the frequency of the external clock for the slave SPI.

waclawek.jan
Super User
February 3, 2020

What was the value loaded into NDTR? It's obviously not 16 as in the example you gave above. And SPI TxFIFO is already full (as expected).

What is the state of SCK at this moment, does it match CPOL? Are there any transitions of SCK since the SPI was enabled? Is the idle state of SCK depending on the data rate you are mentioning?

Could you try to have the internal NSS at 1 while enabling SPI, and then perform a 1-to-0 transition on the internal NSS (using SPIx_CR1.SSI) after you've enabled the SPI, and having ensured SCK matches CPOL?

JW

sergey239955
Associate II
February 3, 2020

No, of course not 16. In this register capture the NDTR was set to 0x20, I believe.

Since I suspect that DMA has nothing to do with the SPI behavior, I tested SPI without DMA.

Since the SPI has 32 bit FIFO, I loaded 4 bytes. Later the clock starts. I would expect all 4 bytes output correctly. But I, in fact, get 5 bytes, the first being sent twice.

Here is the code:

 LL_SPI_StructInit(&SPI_Init_ToFromRadio);
// change non-defaults to what we need 
 SPI_Init_ToFromRadio.NSS = LL_SPI_NSS_SOFT;
 SPI_Init_ToFromRadio.BitOrder = LL_SPI_LSB_FIRST;
 
 LL_SPI_DeInit(SPI3);
 LL_SPI_Init(SPI3, &SPI_Init_ToFromRadio);
 LL_SPI_Enable(SPI3);
 
 LL_SPI_TransmitData8(SPI3, 0x33);
 LL_SPI_TransmitData8(SPI3, 0x55);
 LL_SPI_TransmitData8(SPI3, 0);
 LL_SPI_TransmitData8(SPI3, 0xff);

The SPI is doing it, not DMA

Here is the logic analyzer trace of what happens on the SPI data out line, and the clock

0690X00000By2BeQAJ.jpg

It was captured using the code above. You can clearly see that the first 0x33 comes out doubled, followed by 0x55, 0x0 and 0xff.

Since I do not stop the clock after that (being the test code), the SPI continues outputting 0x33, I guess it is the SPI behavior when in underflow condition.

What is important is that the SPI peripheral is deInit and re-init every time when I call this code. IMHO it points to a racing condition in the SPI IP becase different clock rates behave differently with the same code.

What do you think?

sergey239955
Associate II
February 3, 2020

to answer your question:

No, the idle state doesn't depend on the clock.

I can quickly change the rate and capture the trace again to confirm that there are no glitches of any sort.

waclawek.jan
Super User
February 3, 2020

> I guess it is the SPI behavior when in underflow condition.

Yes, I've been explicitly assured here by ST that this is the case, can't find the thread at the moment.

> No, the idle state doesn't depend on the clock.

But obviously it's not 0 while you set CPOL to 0.

Note this line in RM:

The SCK signal must be settled at an idle state level corresponding to the selected polarity before the SPI slave is enabled.''

JW

sergey239955
Associate II
February 3, 2020

Well, it appears I was wrong, because I made an assumption (wrongly) that the idle state of the clock doesn't depend on the rate. It does.

Below is the correct behavior of SPI at a different rate.

Looks like the transceiver is acting differently at different rates, and the SPI responds differently.

0690X00000By2rBQAR.jpg

waclawek.jan
Super User
February 3, 2020

Okay, so problem solved?

JW

sergey239955
Associate II
February 4, 2020

Hi JW,

it doesn't seem that SPI takes the configuration which sets the high level of idle clock

SPI_InitStrToFromRadio.ClockPolarity = LL_USART_POLARITY_HIGH;

There is no data on the SPI output. The moment I configure it for the (default) SPI_InitStrToFromRadio.ClockPolarity = LL_USART_POLARITY_LOW,

I see the data (albeit with that double first byte issue). Did you hear anything from ST about this issue?

sergey239955
Associate II
February 4, 2020

Sorry, never mind. Accidentally used the USART define instead of SPI

sergey239955
Associate II
February 3, 2020

Thank you JW for asking all right questions, and other guys for spending your time helping out.

I am sure the idle clock polarity is what causes SPI to behave this way. I kinda feel stupid for assuming too much. Too much emphasis was made on the fact that it is migration from a working project. Too much time spent looking at the code and not probing the lines.

Cheers!

sergey239955
Associate II
February 3, 2020

Yes, it is solved. Thanks!

MRosc.1
Associate II
March 29, 2022

I am having a similar issue.

Do you remember what the problem was?

sergey239955
Associate II
March 29, 2022
There was a problem with the idle state of the SPI clock. It didn’t correspond to the SPI settings. Waclawek.jan pointed it out.