Skip to main content
RMlad
Associate
April 1, 2019
Question

SPI reliability problem when transferring large amount of data

  • April 1, 2019
  • 3 replies
  • 985 views

I'm building SPI slave based on STM32F750V8T6 MCU and I'm having problem loosing sync between master and slave. When I run test that is sending sync bytes, slave receive data from master, sync again and slave is returning data after some time master ends up receiving sync bytes not the message that has been sent.

I have tried lowering speed, adding delays between syncs.

Master SPI config:

 hspi1.Instance = SPI1;
 hspi1.Init.Mode = SPI_MODE_MASTER;
 hspi1.Init.Direction = SPI_DIRECTION_2LINES;
 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_4;
 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_ENABLE;
 if (HAL_SPI_Init(&hspi1) != HAL_OK)
 {
 Error_Handler();
 }

slave SPI init

 hspi1.Instance = SPI1;
 hspi1.Init.Mode = SPI_MODE_SLAVE;
 hspi1.Init.Direction = SPI_DIRECTION_2LINES;
 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.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;
 if (HAL_SPI_Init(&hspi1) != HAL_OK)
 {
 Error_Handler();
 }

master sync

uint8_t txackbytes = SPI_MASTER_SYNBYTE;
 rxackbytes = 0x00;
 do
 {
 SPI_TASK(HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)&txackbytes, (uint8_t *)&rxackbytes, 1, HAL_MAX_DELAY))
 }while(rxackbytes != SPI_SLAVE_SYNBYTE);

slave sync

 uint8_t txackbyte = SPI_SLAVE_SYNBYTE;
 uint8_t rxackbyte = 0x00;
 do
 {
 SPI_TASK(HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)&txackbyte, (uint8_t *)&rxackbyte, 1, HAL_MAX_DELAY))
 } while (rxackbyte != SPI_MASTER_SYNBYTE);

master while(1)

HAL_GPIO_WritePin(SPI_SS_GPIO_Port,SPI_SS_Pin,GPIO_PIN_RESET);
 
 Master_Synchro();
 SPI_TASK(HAL_SPI_Transmit(&hspi1, (uint8_t*)&porukaSize, 2, 50));
 
 Master_Synchro();
 SPI_TASK(HAL_SPI_Transmit(&hspi1, poruka, porukaSize, 50));
 
 Master_Synchro();
 SPI_TASK(HAL_SPI_Receive(&hspi1, aRxBuffer, porukaSize, 50));
 
 HAL_GPIO_WritePin(SPI_SS_GPIO_Port,SPI_SS_Pin,GPIO_PIN_SET);
 
 if(strcmp(poruka, aRxBuffer) != 0)
 flag = 0;
 
 if (flag){
 broj_uspeha++;
 }
 memset(aRxBuffer, 0, sizeof(aRxBuffer));

slave while(1)

if(!HAL_GPIO_ReadPin(SPI_SS_GPIO_Port,SPI_SS_Pin)){
 
 Slave_Synchro();
 SPI_TASK(HAL_SPI_Receive(&hspi1, (uint8_t*)&aRxBufferSize, 2, 50));
 
 Slave_Synchro();
 SPI_TASK(HAL_SPI_Receive(&hspi1, aRxBuffer, aRxBufferSize, 50));
 
 memcpy(aTxBuffer, aRxBuffer, sizeof(aRxBuffer));
 
 Slave_Synchro();
 SPI_TASK(HAL_SPI_Transmit(&hspi1, aTxBuffer, aRxBufferSize, 50));
 
 memset(aRxBuffer, 0, sizeof(aRxBuffer));
 memset(aTxBuffer, 0, sizeof(aTxBuffer));
 }

This topic has been closed for replies.

3 replies

S.Ma
Principal
April 2, 2019

Seems you don't use NSS SPI signal between chips?

I2C bus is an NSS embedded in the clock data stream with START (falling edge) and STOP (rising edge) to synchronise data and make sure bytes are not misplaced.

For the slave SPI, do use DMA with cyclical buffer in RAM.

When NSS toggles, get EXTI interrupt to notify that the transmission is completed or about to start, and prepare your DMA pointers for it.

RMlad
RMladAuthor
Associate
April 2, 2019

We are using SPI_NSS_SOFT for slave select, with DMA we are having even bigger problem. When using DMA the first sync-send-receive is failure.

S.Ma
Principal
April 2, 2019

Implement EXTI interrupt on NSS GPIO both rise and fall edge at least for the slave function.

Use it to initialize the DMA (at fall edge if length known at last minute, at rise edge otherwise).