cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F429ZIT6 SPI Receive Issue

Scarlet
Associate III

Hi everyone,

I'm currently using the Nucleo F429ZI development board to test SPI Receive, and I've encountered the following two issues:

  1. I use the HAL_SPI_Receive() function, when I config the SPI frequency to a slower rate, I've observed that the CS signal HIGH too early, causing subsequent received data to be incorrectly received.

    SPI Freq Config:

 

hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;

 

 

Code:

 

/* CS Enable */
GPIOA->ODR &= ~(1<<4);

HAL_SPI_Receive(&hspi1, data_ptr, 1, 1);

/* CS Disable */
GPIOA->ODR |= 0x0010;

 

 

 (yellow is CS, blue is SPI SCK)

Scarlet_3-1713491847589.jpeg

 

 

  • When I config the SPI frequency to a faster rate, the HAL_SPI_Receive() function times out. I've found similar issues and solutions [1].However, due to my requirement for high speed, I can't afford to slowly determine the timeout function. Therefore, I'm currently not using the HAL function and directly controlling the SPI registers to avoid the HAL_SPI_Receive() timeout issue. However, I still encounter issue 1 with the CS signal HIGH too early.

Referring to the RM0090 Manual programming SPI Receive.

Scarlet_1-1713491584077.jpeg

Scarlet_2-1713491599258.jpeg

Code:

 

/* CS Enable */
GPIOA->ODR &= ~(1<<4);

/* Enable SPI, SPE = 1 */
SPI1->CR1 |= 0x0040;

/* Check RXNE flag */
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)){
	*data_ptr = (uint16_t)hspi->Instance->DR;
	*data_ptr += sizeof(uint16_t);
}
SPI1->CR1 &= 0xFFBF;

/* CS Disable */
GPIOA->ODR |= 0x0010;

 

 

According to Figure 257 in RM0090, RXNE should only be raised after the SPI_DR register has received data completely.
I infer that the RXNE bit is to 1 when the SPI_DR register has data, causing the program to execute the CS set HIGH after checking RXNE, which evidently differs from the actual behavior.

 

[1] SPI receive times out due to SPI_FLAG_RXNE not reseting in SPI_EndRxTransaction.

4 REPLIES 4
Bob S
Principal

> When I config the SPI frequency to a faster rate, the HAL_SPI_Receive() function times out.

That does not make sense.  A SLOWER clock could cause it to time out, not a faster clock rate.  Larger clock divider would cause timeout as that means slower clock.  But really, when using polled functions you should almost always give a large value for the "timeout" param.  Exceptions to this rule exist, but not your situation.

It looks like you have the SPI port configured for 16-bit transfers, is that correct?  If so, then the only reason I can see for the "early return" that you show above is that the clock rate is slow enough that it takes more than 1ms to complete the 16-bit transfer.  So, again, make you timeout much larger (even HAL_MAX_DELAY).

And if the return code from ..._Receive() had been checked from the outset it might have been helpful.

I know your meaning.

In theory, if the SPI frequency is too slow, we need to provide a sufficiently large value for the "timeout". However, in practice, what is observed is that when the SPI frequency is configured to be too fast, it results in the SPI function waiting until timeout due to Timeout.

Quoting [1] by waclawek.jan:

"If the baud rate is low and/or compiler optimizations are enabled, the test will happen before that extraneous frame is received, and the RXNE flag set afterwards will cause problems when starting to receive the next frame. In the other case - as happened here - the extra frame is received completely and RXNE is set at the time of the test, then the code waits until timeout (potentially forever if set so), as there's, of course, nothing which would clear RXNE in that waiting loop."

[1] SPI receive times out due to SPI_FLAG_RXNE not reseting in SPI_EndRxTransaction.

OK, I'll checked the function again.