cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F769 SPI missing data

Jonathan Roberts
Associate II
Posted on May 04, 2017 at 12:41

Hi,

I am occasionally loosing a byte on SPI reads from an external ADC and would appreciate any suggestions about how to investigate further.

Summary: I have a FreeRTOS based application running on the STM32F769I Eval board. Periodically the application reads data from an external ADC (AD7606) connected via SPI. Data reads from the ADC are using DMA. Very occasionally (~one cluster in every 250000 transfers) I lose a byte in the middle of a number of successive transfers. The missing data is visibleon the bus an external SPI Analyser. The SPI Error interrupt never triggers.

Details:

  • The application is developed using the OpenSTM32 tools and CubeMX 4.19
  • The AD7606 is sampled at 1000Hz, driven by a hardware timer.
  • SPI & DMA Configuration

    • STM32 is the master
    • AD7606 is connected via SPI1
    • SPI Clock is 7.5MHz
    • Each SPI transfer is 16 bytes long.
    • The DMA transfer is from the SPI FIFO to external SDRAM.
    • SPI Configuration is:

      hspi1.Instance = SPI1;

      hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    • The DMA & GPIO Configuration is: /**SPI1 GPIO Configuration PB4 ------> SPI1_MISO PB3 ------> SPI1_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* Peripheral DMA init*/ hdma_spi1_rx.Instance = DMA2_Stream0; hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3; hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_spi1_rx.Init.Mode = DMA_NORMAL; hdma_spi1_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH; hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(spiHandle,hdmarx,hdma_spi1_rx);

  • The missing data is always an entire byte for example:

    On Bus: 0x24 0x06 0x24 0x0F

    0x24

    0x23

    0x24 0x12 0x24 0x14 0x23 0xFA 0x24 0x06 0x24 0x10Received: 0x24 0x06 0x24 0x0F

    0x23

    0x24 0x12 0x24 0x14 0x23 0xFA 0x24 0x06 0x24 0x10 0x24
  • As mentioned in the summary, despite the HAL layer enabling SPI error interrupts, an error is never triggered.

Thanks in advance for any suggestions.

Jonathan

#dma #spi #stm32f7 #freertos

Note: this post was migrated and contained many threaded conversations, some content may be missing.
11 REPLIES 11
Jonathan Roberts
Associate II
Posted on May 09, 2017 at 21:30

I have continued to investigate this and have modified theSTM32F769I-DiscoverySPI_FullDuplex_ComDMA example to run on the

STM32F769I Eval board and read data from my external ADC. I am using the same SPI and DMA configuration as my full application it appears to be 100% reliable.

This suggests to me that the problem is some sort of interaction between components in my full application. The application isn't terribly complicated at the moment and is only using the following peripherals:

  • Full speed USB port

  • TIM6

  • SPI1 & DMA

  • GPIO

  • SDRAM

Whilst the ADC is running there isn't anyTX/RX activity on the USB port.

I have used Seggers SystemView application to visualise the activity of the system and I haven't been able to spot anything different in the system behaviour during the conversion that fails vs the ones which are fine.

I am wondering is something similar to this

https://community.st.com/thread/39114-reading-rtc-registers-stops-dma-transfer-on-stm32l051

is happening (I realise it is a very different part).

Any suggestions as to the cause would be appreciated.

Thanks!

Posted on May 10, 2017 at 00:32

Is 16-bit mode more robust?

At 16 bytes per transfer, would Internal SRAM make more sense? Even if you move the data to SDRAM later via the cache/write-buffers.

Monitoring via the debugger is likely more invasive than you think, and more likely to cause bus conflicts and stalls. Avoid.

Getting this kind of byte loss with DMA is disturbing, perhaps you can convince an ST FAE to review this behaviour with you. If it were my problem I'd probably get an FPGA to spoof the ADC with an LFSR generating a known/predictable sequence so the STM32 side software could detect and trap the failure.

I don't think the RTC issue is the same, there you have a massive disparity in peripheral speeds and the stalling of bus resources for very significant amounts of time. ie like the accidents you'd have with a Zamboni on the motorway/freeway.

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

> Monitoring via the debugger is likely more invasive than you think, and more likely to cause bus conflicts and stalls. Avoid.

More importantly, reading the SPI [data] register by the debuging gadget causes [Rx] flag loss.

I'd also ask whether the DMA is circular, or the SPI is stopped/started (maybe it's in the given code, I don't speak the 'libraries' gobbledygook), and whether the data loss occurs on the 16-byte chunk boundaries.

JW

Posted on May 10, 2017 at 15:25

Interesting comments and suggestions.

Firstly I am not monitoring the SPI registers with the debugger so we can rule out that.

My test system is feeding known voltages into the 8 ADC inputs and I have traps set in the application to trigger when the captured inputs go outside of some tight bounds around the expected values.

I have today tried changing the DMA RX buffer from SDRAM to internal memory (aligned on a 4 byte boundary). I also tried changing from 8 bit mode to 16 bit mode. After these changes it does appear to be more robust but eventually I had a similar problem occur, but this time I 'lost' 4 bytes.

Posted on May 10, 2017 at 17:04

I'd also ask whether the DMA is circular, or the SPI is stopped/started (maybe it's in the given code, I don't speak the 'libraries' gobbledygook), and whether the data loss occurs on the 16-byte chunk boundaries.

Posted on May 10, 2017 at 17:16

Also,

If it were my problem I'd probably get an FPGA to spoof the ADC with an LFSR generating a known/predictable sequence so the STM32 side software could detect and trap the failure.

is a great point. You might have missing more data than you think.

JW

Posted on May 10, 2017 at 18:49

Hi,

Sorry I missed this question earlier. The DMA isn't circular and the SPI is started and stopped by the HAL layer around each transaction. The I don't believe that the failure always occurs on a 16 byte boundary, but will need to re run the system to check.

It is a good idea about using a controllable SPI Slave to generate a known pattern. I will try and set that up tomorrow..

Tamas Novak
Associate III
Posted on May 11, 2017 at 09:48

I don't know if this fits your problem, but I have had similar kind of problem: STM32F0 as SPI slave 'lost' bytes (I mean random 0x00 bytes injected into the data stream). After a while I spotted a comment in the HAL file 'stm32f0xx_hal_spi.c'

Using the HAL it is not possible to reach all supported SPI frequency with the differents SPI Modes,

the following table resume the max SPI frequency reached with data size 8bits/16bits:

+-----------------------------------------------------------------------------------------+

| | | 2Lines Fullduplex | 2Lines RxOnly | 1Line |

| Process | Tranfert mode |--------------------|--------------------|--------------------|

| | | Master | Slave | Master | Slave | Master | Slave |

|=========================================================================================|

| T | Polling | Fcpu/32 | Fcpu/32 | NA | NA | NA | NA |

| X |----------------|----------|---------|----------|---------|----------|---------|

| / | Interrupt | Fcpu/32 | Fcpu/32 | NA | NA | NA | NA |

| R |----------------|----------|---------|----------|---------|----------|---------|

| X | DMA | Fcpu/32 | Fcpu/16 | NA | NA | NA | NA |

|=========|================|==========|=========|==========|=========|==========|=========|

| | Polling | Fcpu/32 | Fcpu/16 | Fcpu/16 | Fcpu/16 | Fcpu/16 | Fcpu/16 |

| |----------------|----------|---------|----------|---------|----------|---------|

| R | Interrupt | Fcpu/16 | Fcpu/16 | Fcpu/16 | Fcpu/16 | Fcpu/16 | Fcpu/16 |

| X |----------------|----------|---------|----------|---------|----------|---------|

| | DMA | Fcpu/4 | Fcpu/8 | Fcpu/4 | Fcpu/4 | Fcpu/8 | Fcpu/16 |

|=========|================|==========|=========|==========|=========|==========|=========|

| | Polling | Fcpu/16 | Fcpu/16 | NA | NA | Fcpu/16 | Fcpu/16 |

| |----------------|----------|---------|----------|---------|----------|---------|

| T | Interrupt | Fcpu/32 | Fcpu/16 | NA | NA | Fcpu/16 | Fcpu/16 |

| X |----------------|----------|---------|----------|---------|----------|---------|

| | DMA | Fcpu/2 | Fcpu/16 | NA | NA | Fcpu/8 | Fcpu/16 |

+-----------------------------------------------------------------------------------------+

@note The max SPI frequency depend on SPI data size (4bits, 5bits,..., 8bits,...15bits, 16bits),

SPI mode(2 Lines fullduplex, 2 lines RxOnly, 1 line TX/RX) and Process mode (Polling, IT, DMA).

Being max SPI clock = 1/32* FCPU  is shocking: a 48MHz MCU (fully armored with DMA, cache system etc) can do only 1.5Mbps transfer?

Posted on May 15, 2017 at 14:31

Any progress on this?