cancel
Showing results for 
Search instead for 
Did you mean: 

SPI slave - different behavior without debugger

DSass
Associate II

Hi,

I am using STM32L051R8T6 and i have implemented an SPI slave using the HAL libraries.

I am using DMA. the master is an FPGA. SPI clock is ~2Mhz.

The FPGA initiate 2 read commands for each read from the MCU - 1 for it to prepare the data and 1 to read it. all of the commands are fixed length of 7 Bytes.

When using a debugger it is working but when i reset the board and load without a debugger i get different results - the bytes seems shifted. attached are the 2 scenarios from the signal tap of the FPGA.

We tried increasing the delay between the 2 messages and it didn't

this is how my SPI is configured:

 /* SPI2 parameter configuration*/

 hspi2.Instance = SPI2;

 hspi2.Init.Mode = SPI_MODE_SLAVE;

 hspi2.Init.Direction = SPI_DIRECTION_2LINES;

 hspi2.Init.DataSize = SPI_DATASIZE_8BIT;

 hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;

 hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

 hspi2.Init.NSS = SPI_NSS_HARD_INPUT;

 hspi2.Init.FirstBit = SPI_FIRSTBIT_LSB;

 hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

 hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

 hspi2.Init.CRCPolynomial = 7;

 if (HAL_SPI_Init(&hspi2) != HAL_OK)

 {

  Error_Handler();

 }

  /* SPI2 DMA Init */

  /* SPI2_RX Init */

  hdma_spi2_rx.Instance = DMA1_Channel4;

  hdma_spi2_rx.Init.Request = DMA_REQUEST_2;

  hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

  hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;

  hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;

  hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

  hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

  hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;

  hdma_spi2_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;

  if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK)

  {

   Error_Handler();

  }

  __HAL_LINKDMA(hspi,hdmarx,hdma_spi2_rx);

  /* SPI2_TX Init */

  hdma_spi2_tx.Instance = DMA1_Channel5;

  hdma_spi2_tx.Init.Request = DMA_REQUEST_2;

  hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

  hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;

  hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;

  hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

  hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

  hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;

  hdma_spi2_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;

  if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)

  {

   Error_Handler();

  }

  __HAL_LINKDMA(hspi,hdmatx,hdma_spi2_tx);

  /* SPI2 interrupt Init */

  HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);

  HAL_NVIC_EnableIRQ(SPI2_IRQn);

0693W000003BgFlQAK.png0693W000003BgFvQAK.png

6 REPLIES 6
TDK
Guru

The MISO line is definitely different between the two plots, but that doesn't really explain much, unless you are sending the exact same data on every transaction. You need to ensure your SPI slave is set up prior to the CS line going low. Add a GPIO output somewhere that you can see on the logic analyzer to prove this is the case.

Probably a bug in the code, but it's unlikely to be in the SPI initialization.

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

Usually the main difference is that without debugger the FPGA and the MCU don't start the same way. How to you handle the case that the MCU init SPI while FPGA is transacting on the SPI bus? Do you reinit and sync with NSS edge?

What's the time between the assertion (falling edge) of NSS and the first clock of the SPI frame? The SPI module in Slave mode has a spec for that, I believe - see the Data Sheet.

DSass
Associate II

i am using HAL_SPI_TransmitReceive_DMA . i have a fixed size structure for the rx&tx dma and i call this function again after handling the message, waiting for the next command. I start handling the message after receiving a full 7 byte messages (below) so in the first read command from the FPGA i don't have anything in the tx buffer but when i receive the next message i have the full answer in the buffer.

this is the HAL_SPI_TxRxCpltCallback:

  if (calculateLRC((unsigned char *)&(m.pkt), 6) == m.lrc)

   com_spi_hndlr(SPI_PROC);

  HAL_SPI_TransmitReceive_DMA(SPI_PROC, (uint8_t *)payload_tx,(uint8_t *)&m, 7);

   

DSass
Associate II

the messages from the FPGA start in response to a message the FPGA get from an external source, so I wait and make sure the MCU is finished initializing. after handling a message i re-init the SPI.

DSass
Associate II

Thanks, i will check it.