SPI reception timeouts due to SPI_FLAG_RXP bit on STM32U575
Hi, i have a project here using an STM32U575RIT6Q with an external device i have connected throught the SPI interface.
The microcontroller is at 160MHz using HSE with PLL. The SPI interface is at 40MHz with SPI mode 0, nss software and 8 bits per word.
The problem surges when i call the function HAL_SPI_Receive. The reception of a long frame breaks up after some received bytes and then timeouts. Due to this timeout i cannot be able to receive the whole frame.
I have made some test on the NUCLEO-U575ZI-Q using the 3 SPI peripherals to check if my SPI interface has any limitation. The result is the same.
Here is the configuration for the SPI interfaces:
/**
* @brief SPI1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
SPI_AutonomousModeConfTypeDef HAL_SPI_AutonomousMode_Cfg_Struct = {0};
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
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_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 0x7;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
hspi1.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
hspi1.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerState = SPI_AUTO_MODE_DISABLE;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerSelection = SPI_GRP1_GPDMA_CH0_TCF_TRG;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerPolarity = SPI_TRIG_POLARITY_RISING;
if (HAL_SPIEx_SetConfigAutonomousMode(&hspi1, &HAL_SPI_AutonomousMode_Cfg_Struct) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
/**
* @brief SPI2 Initialization Function
* @PAram None
* @retval None
*/
static void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
SPI_AutonomousModeConfTypeDef HAL_SPI_AutonomousMode_Cfg_Struct = {0};
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
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_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 0x7;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
hspi2.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
hspi2.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerState = SPI_AUTO_MODE_DISABLE;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerSelection = SPI_GRP1_GPDMA_CH0_TCF_TRG;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerPolarity = SPI_TRIG_POLARITY_RISING;
if (HAL_SPIEx_SetConfigAutonomousMode(&hspi2, &HAL_SPI_AutonomousMode_Cfg_Struct) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_Init 2 */
}
/**
* @brief SPI3 Initialization Function
* @PAram None
* @retval None
*/
static void MX_SPI3_Init(void)
{
/* USER CODE BEGIN SPI3_Init 0 */
/* USER CODE END SPI3_Init 0 */
SPI_AutonomousModeConfTypeDef HAL_SPI_AutonomousMode_Cfg_Struct = {0};
/* USER CODE BEGIN SPI3_Init 1 */
/* USER CODE END SPI3_Init 1 */
/* SPI3 parameter configuration*/
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 0x7;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi3.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi3.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi3.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi3.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi3.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi3.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi3.Init.IOSwap = SPI_IO_SWAP_DISABLE;
hspi3.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
hspi3.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
}
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerState = SPI_AUTO_MODE_DISABLE;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerSelection = SPI_GRP2_LPDMA_CH0_TCF_TRG;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerPolarity = SPI_TRIG_POLARITY_RISING;
if (HAL_SPIEx_SetConfigAutonomousMode(&hspi3, &HAL_SPI_AutonomousMode_Cfg_Struct) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI3_Init 2 */
/* USER CODE END SPI3_Init 2 */
}Here is the test i have developed:
while(1)
{
HAL_StatusTypeDef state;
uint16_t lenSpi = 35;
uint8_t dataArray1[4000];
memset(dataArray1, 0xFF, sizeof(dataArray1));
state = HAL_SPI_Receive(&hspi1, &dataArray1[1000], lenSpi, 1000);
printf("Receive1 %u %u %02X.\n", lenSpi, state, dataArray1[1000]);
state = HAL_SPI_Receive(&hspi2, &dataArray1[2000], lenSpi, 1000);
printf("Receive2 %u %u %02X.\n", lenSpi, state, dataArray1[2000]);
state = HAL_SPI_Receive(&hspi3, &dataArray1[3000], lenSpi, 1000);
printf("Receive3 %u %u %02X.\n", lenSpi, state, dataArray1[3000]);
}I added this additional print inside the HAL_SPI_Receive function :
/* Receive data in 8 Bit mode */
else
{
/* Transfer loop */
while (hspi->RxXferCount > 0UL)
{
/* Check the RXP flag */
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXP))
{
*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint8_t);
hspi->RxXferCount--;
}
else
{
/* Timeout management */
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
{
printf("Missing Data to Receive %u from %u.\n", hspi->RxXferCount, Size);
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
hspi->State = HAL_SPI_STATE_READY;
/* Unlock the process */
__HAL_UNLOCK(hspi);
return HAL_TIMEOUT;
}
}
}
}The results are the following ones at 40MHz:
Missing Data to Receive 6 from 35.
Receive1 35 3.
Missing Data to Receive 6 from 35.
Receive2 35 3.
Missing Data to Receive 22 from 35.
Receive3 35 3.
Missing Data to Receive 6 from 35.
Receive1 35 3.
Missing Data to Receive 6 from 35.
Receive2 35 3.
Missing Data to Receive 22 from 35.
Receive3 35 3.
Missing Data to Receive 6 from 35.
Receive1 35 3.
Missing Data to Receive 6 from 35.
Receive2 35 3.
Missing Data to Receive 22 from 35.
Receive3 35 3.
In this output is shown the lenght of the data that was not received, the total requested data length, and the return value by the HAL_SPI_Receive function. This return value is always 3 that means HAL_TIMEOUT.
I have made this same test with decreasing the SPI frequency to 20MHz and this is the result:
Missing Data to Receive 20 from 1000.
Receive1 1000 3.
Missing Data to Receive 20 from 1000.
Receive2 1000 3.
Missing Data to Receive 843 from 1000.
Receive3 1000 3.
Missing Data to Receive 20 from 1000.
Receive1 1000 3.
Missing Data to Receive 20 from 1000.
Receive2 1000 3.
Missing Data to Receive 843 from 1000.
Receive3 1000 3.
It seems there is a dependancy on the SPI frequency and the triggering of this issue. While less the frequecy, more the data i can receive before the timeout due to the bit SPI_FLAG_RXP not being after some received bytes.
Maybe there is some configuration i am missing? i have made this same test on a STM32L452RET6 and it doesnt occur.
Thanks all.
