cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 SPI DMA FIFO not writing into or corrupting memory

Noyb
Associate II
Posted on March 10, 2016 at 14:44

Hi, I just wanted to connect a STM32 to a GPS using a SPI with DMA. Here is my setting :

la : LOGICPORT LA1034

board : NUCLEO-L476RG

mcu : STM32L476RGT6

gps : EVA-7M

cube : 4.13.0

lib : HAL 1.3.0

clock : 80 MHz

spi : SPI3, master, full duplex, 2 wires, prescaler 256 (312 kHz), no NSS

dma : DMA2_Rq3_Ch1 as Rx, DMA2_Rq3_Ch2 as Tx, BYTE

The scenario is as follow :

> STM32 send a 6 bytes UBX polling request frame using HAL_SPI_Transmit_DMA

> The logic analyzer 'see' the frame being sent

> After a while, I try to read the 6 first bytes from the answered UBX frame

Here are the results of my analysis :

1- Trying to receive 6 bytes using HAL_SPI_Receive_DMA into memory @ 'bufUbx' (multiple of 8)

expected frame : B5 62 0A 04 | 64 00

expected @ bufUbx : B5 62 0A 04 | 64 00 .. .. | .. .. .. .. | .. .. .. ..

??

: unreceived byte(s)

received frame :

FF

B5 62 0

A

|

0

4

64

received @ bufUbx :

FF FF FF FF

| B5 62 0

E 3

4 |

??

..

.. .. | .. .. .. ..

The logic analyzer 'see' 6 bytes incoming from the GPS, yet it starts with an unexpected dummy byte set at FF.

The STM32 starts writing 4 bytes after 'bufUbx', padding the first 32 bits with the received dummy byte. The last bytes are merged into one, corrupting memory.

As the frame starts with a dummy byte, the UBX size is not complete. So I tried receiving 1 more byte as read ahead.

2- Trying to receive 6 + 1 bytes using HAL_SPI_Receive_DMA into memory @ 'bufUbx' (multiple of 8)

expected frame : B5 62 0A 04 | 64 00 31

expected @ bufUbx : B5 62 0A 04 | 64 00 31 .. | .. .. .. .. | .. .. .. ..

??

: unreceived byte(s)

received frame :

FF

B5 62 0A |

0

4 64 00

received @ bufUbx :

FF FF FF FF

| B5 62 0A

3

4 |

?? ??

..

.. | .. .. .. ..

The logic analyzer shows that the UBX size 64 00 is now received, the frame still starting with a dummy byte.

The STM32 still doesn't write the last received bytes into memory, corrupting it instead. So I try to receive even more bytes to see where it leads.

3- Trying to receive 6 + 1 + 4 bytes using HAL_SPI_Receive_DMA into memory @ 'bufUbx' (multiple of 8)

expected frame : B5 62 0A 04 | 64 00 31 2E | 30 30 31

expected @ bufUbx : B5 62 0A 04 | 64 00 31 2E | 30 30 31 .. | .. .. .. ..

??

: unreceived byte(s)

received frame :

FF

B5 62 0A | 04 64 00 31 |

2E 30 30

received @ bufUbx :

FF FF FF FF

| B5 62 0A 04 | 64 00 31

??

|

?? ??

.. ..

The logic analyzer shows the expected number of bytes requested, yet starting again with the dummy byte.

The STM32 still writes at the wrong location into memory, but instead to corrupt the last bytes, it just skip them.

If the 32 FIFO is to take into consideration, let's try to received a multiple of 4 bytes to check if the whole FIFO is dumped in one operation into memory.

4- Trying to receive 12 bytes using HAL_SPI_Receive_DMA into memory @ 'bufUbx' (multiple of 8)

expected frame : B5 62 0A 04 | 64 00 31 2E | 30 30 20 28

expected @ bufUbx : B5 62 0A 04 | 64 00 31 2E | 30 30 20 28 | .. .. .. ..

??

: unreceived byte(s)

received frame :

FF

B5 62 0A | 04 64 00 31 | 2E

30 30 20

received @ bufUbx :

FF FF FF FF

| B5 62 0A 04 | 64 00 31 2E |

?? ?? ??

..

Nothing has changed, the received UBX frame still starts with a dummy byte.

The STM32 just writes 1 byte more into memory, skipping the remaining 3 bytes.

As a matter of fact, I used STM32cubeMX to create my initialization code and I'm using the brand new HAL library to perform some basic data transfer.

I don't see what's so complicated to perform, I could provide you with my initialization and callback routines.

#stm32-spi-dma-fifo-flush
6 REPLIES 6
Posted on March 10, 2016 at 16:59

Well with SPI the leading dummy byte on the receive is likely due to the fact you have to clock something into the device for it to respond, and you'd have to keep pumping some data out to generate clocks, as the responses will be longer than the requests.

Sorry not used uBlox devices in SPI mode, and have about zero interest in HAL/Cube. You could perhaps try using polling, or IRQ modes, to remove DMA from the equation.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Noyb
Associate II
Posted on March 10, 2016 at 17:23

> clock something to get rid of dummy byte

How to be sure I have to clock something ? How will it be interpreted by the GPS module ? I can always try to output multiple FF as these will be discarded.

> responses will be longer than the requests

Sure they are, that the point. but I cannot perform real ''full-duplex'' because there are no double transmission happening at the same time. The STM32 issue a polling request, the GPS answers back a little while later (it needs to perform its own internal parsing and computation first)

> uBlox in SPI

Too bad, but with my ''hack'' (extra bytes) my prototype works somewhat, hence proving it is indeed possible

> HAL/Cube

Well, I have pretty much enough high level stuff to do instead to waste my time on low level handling when a library is supposed to do the trick for me. Yet I heard here and there that HAL is almost completely bogus and several people encourage to step back to StdPeriph_Lib instead.

> try using polling, or IRQ modes, to remove DMA

Well, DMA would leaves the RTOS enough time to perform some other operations during the transfers. Perhaps IRQ would help but I cannot imagine you to pack everything nicely without running into a race condition. I'm not into coding a finite state machine or a micro scheduler just to synchronize things.

I'm basically just asking for the serial communication to work without having to call for the whole US army to get to the rescue.

Posted on March 10, 2016 at 17:39

How to be sure I have to clock something ?

The SPI bus is symmetrical, only transmission generates clocks, simply reading SPI->DR does not generate clocks, and thus data must be pumped across the interface for data to be retrieved.

I'm basically just asking for the serial communication to work without having to call for the whole US army to get to the rescue.

There are just volunteer fire fighters here. My uBlox protocol experience is with UART/USB

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 10, 2016 at 17:54

0690X000006037xQAA.jpg

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Noyb
Associate II
Posted on March 11, 2016 at 11:19

Thanks for the insight.

Here attached a very simple STMCubeMX example just with basic SPI polling with no DMA that shows the problem. So it is NOT DMA related.

> Test14_NUCLEO_L476RG_SPI_EVA7_ACC.zip

________________

Attachments :

Test14_NUCLEO_L476RG_SPI_EVA7_ACC.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0tx&d=%2Fa%2F0X0000000bfj%2F3f1VzbhD4gGe0U1G3lw9fQ32l93LFaq3cXkk9aTDtSk&asPdf=false
Noyb
Associate II
Posted on March 11, 2016 at 15:26

OK, looks like after HAL_Init(); and MX_SPI3_Init(); I have to perform a first HAL_SPI_TransmitReceive(&hspi3 of 4 bytes set to 0xFF in order to initialize the FIFOs and the TxRx register, setting MOSI and MISO high.

After that everything now looks working well. Polling or DMA. Obviously just an initialization issue that MX should have added automatically to completely set up the SPI.