32F417 SPI running at half the speed it should
Hello,
I am using a chopped-down function from the Cube HAL code to talk to a serial FLASH. The original function has a mass of options which were checked at runtime - the usual thing for HAL code...
It's all working fine. SPI2, 21MHz (the fastest I can go with PCLK1=PCLK2=42MHz).
But testing the speed, I am seeing 600us time taken to read 512 bytes. The SPI speed limit should be about 200us. The actual time, obtained by waggling a pin, is 600us. Can anyone see anything obviously wrong with this code? As I say, it works perfectly.
// Used only for SPI2. Mode is always SPI_MODE_MASTER and 2LINE.
//__attribute__((optimize("O0")))
HAL_StatusTypeDef B_HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
{
uint16_t initial_TxXferCount;
uint32_t tmp_mode;
HAL_SPI_StateTypeDef tmp_state;
/* Variable used to alternate Rx and Tx during transfer */
uint32_t txallowed = 1U;
HAL_StatusTypeDef errorcode = HAL_OK;
/* Init temporary variables */
tmp_state = hspi->State;
tmp_mode = hspi->Init.Mode;
initial_TxXferCount = Size;
if (!((tmp_state == HAL_SPI_STATE_READY) || \
((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX))))
{
errorcode = HAL_BUSY;
goto error;
}
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
{
errorcode = HAL_ERROR;
goto error;
}
/* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
if (hspi->State != HAL_SPI_STATE_BUSY_RX)
{
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
}
/* Set the transaction information */
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
hspi->pRxBuffPtr = (uint8_t *)pRxData;
hspi->RxXferCount = Size;
hspi->RxXferSize = Size;
hspi->pTxBuffPtr = (uint8_t *)pTxData;
hspi->TxXferCount = Size;
hspi->TxXferSize = Size;
/*Init field not used in handle to zero */
hspi->RxISR = NULL;
hspi->TxISR = NULL;
/* Check if the SPI is already enabled */
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
{
__HAL_SPI_ENABLE(hspi);
}
/* Transmit and Receive data in 8 Bit mode */
// The need for this initial byte is unknown
if (initial_TxXferCount == 0x01U)
{
*((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr);
hspi->pTxBuffPtr++;
hspi->TxXferCount--;
}
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
{
/* Check TXE flag */
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
{
*(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr);
hspi->pTxBuffPtr++;
hspi->TxXferCount--;
/* Next Data is a reception (Rx). Tx not allowed */
txallowed = 0U;
}
/* Wait until RXNE flag is reset */
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
{
(*(uint8_t *)hspi->pRxBuffPtr) = hspi->Instance->DR;
hspi->pRxBuffPtr++;
hspi->RxXferCount--;
/* Next Data is a Transmission (Tx). Tx is allowed */
txallowed = 1U;
}
}
// Clear overrun flag in 2 Lines communication mode because received is not read
// For 45DBxx the Init.Direction is always SPI_DIRECTION_2LINES and is set up in b_main.c
//if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
//{
__HAL_SPI_CLEAR_OVRFLAG(hspi);
//}
error :
hspi->State = HAL_SPI_STATE_READY;
return errorcode;
}