in Drivers/STM32U5xx_HAL/Src/stm32u5xx_hal_spi.c [1253:1533]
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
uint32_t Timeout)
{
HAL_SPI_StateTypeDef tmp_state;
HAL_StatusTypeDef errorcode = HAL_OK;
#if defined (__GNUC__)
__IO uint16_t *ptxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->TXDR));
__IO uint16_t *prxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->RXDR));
#endif /* __GNUC__ */
uint32_t tickstart;
uint32_t tmp_mode;
uint16_t initial_TxXferCount;
uint16_t initial_RxXferCount;
/* Check Direction parameter */
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
/* Lock the process */
__HAL_LOCK(hspi);
/* Init tickstart for timeout management*/
tickstart = HAL_GetTick();
initial_TxXferCount = Size;
initial_RxXferCount = Size;
tmp_state = hspi->State;
tmp_mode = hspi->Init.Mode;
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;
__HAL_UNLOCK(hspi);
return errorcode;
}
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0UL))
{
errorcode = HAL_ERROR;
__HAL_UNLOCK(hspi);
return errorcode;
}
/* 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;
/* Set the number of data at current transfer */
MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
__HAL_SPI_ENABLE(hspi);
if (((hspi->Instance->AUTOCR & SPI_AUTOCR_TRIGEN) == 0U) && (hspi->Init.Mode == SPI_MODE_MASTER))
{
/* Master transfer start */
SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
}
/* Transmit and Receive data in 32 Bit mode */
if ((hspi->Init.DataSize > SPI_DATASIZE_16BIT) && (IS_SPI_FULL_INSTANCE(hspi->Instance)))
{
while ((initial_TxXferCount > 0UL) || (initial_RxXferCount > 0UL))
{
/* Check TXP flag */
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP)) && (initial_TxXferCount > 0UL))
{
*((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint32_t);
hspi->TxXferCount --;
initial_TxXferCount = hspi->TxXferCount;
}
/* Check RXWNE/EOT flag */
if (((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_EOT)) != 0UL) && (initial_RxXferCount > 0UL))
{
*((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint32_t);
hspi->RxXferCount --;
initial_RxXferCount = hspi->RxXferCount;
}
/* Timeout management */
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
{
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
/* Unlock the process */
__HAL_UNLOCK(hspi);
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
hspi->State = HAL_SPI_STATE_READY;
return HAL_TIMEOUT;
}
}
}
/* Transmit and Receive data in 16 Bit mode */
else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
{
while ((initial_TxXferCount > 0UL) || (initial_RxXferCount > 0UL))
{
/* Check TXP flag */
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP) && (initial_TxXferCount > 0UL))
{
if ((initial_TxXferCount > 1UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
{
*((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint32_t);
hspi->TxXferCount -= (uint16_t)2UL;
initial_TxXferCount = hspi->TxXferCount;
}
else
{
#if defined (__GNUC__)
*ptxdr_16bits = *((uint16_t *)hspi->pTxBuffPtr);
#else
*((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
#endif /* __GNUC__ */
hspi->pTxBuffPtr += sizeof(uint16_t);
hspi->TxXferCount--;
initial_TxXferCount = hspi->TxXferCount;
}
}
/* Check RXWNE/FRLVL flag */
if (((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_FRLVL)) != 0UL) && (initial_RxXferCount > 0UL))
{
if ((hspi->Instance->SR & SPI_FLAG_RXWNE) != 0UL)
{
*((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint32_t);
hspi->RxXferCount -= (uint16_t)2UL;
initial_RxXferCount = hspi->RxXferCount;
}
else
{
#if defined (__GNUC__)
*((uint16_t *)hspi->pRxBuffPtr) = *prxdr_16bits;
#else
*((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
#endif /* __GNUC__ */
hspi->pRxBuffPtr += sizeof(uint16_t);
hspi->RxXferCount--;
initial_RxXferCount = hspi->RxXferCount;
}
}
/* Timeout management */
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
{
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
/* Unlock the process */
__HAL_UNLOCK(hspi);
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
hspi->State = HAL_SPI_STATE_READY;
return HAL_TIMEOUT;
}
}
}
/* Transmit and Receive data in 8 Bit mode */
else
{
while ((initial_TxXferCount > 0UL) || (initial_RxXferCount > 0UL))
{
/* check TXP flag */
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP)) && (initial_TxXferCount > 0UL))
{
if ((initial_TxXferCount > 3UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_03DATA))
{
*((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint32_t);
hspi->TxXferCount -= (uint16_t)4UL;
initial_TxXferCount = hspi->TxXferCount;
}
else if ((initial_TxXferCount > 1UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
{
#if defined (__GNUC__)
*ptxdr_16bits = *((uint16_t *)hspi->pTxBuffPtr);
#else
*((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
#endif /* __GNUC__ */
hspi->pTxBuffPtr += sizeof(uint16_t);
hspi->TxXferCount -= (uint16_t)2UL;
initial_TxXferCount = hspi->TxXferCount;
}
else
{
*((__IO uint8_t *)&hspi->Instance->TXDR) = *((uint8_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint8_t);
hspi->TxXferCount--;
initial_TxXferCount = hspi->TxXferCount;
}
}
/* Wait until RXWNE/FRLVL flag is reset */
if (((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_FRLVL)) != 0UL) && (initial_RxXferCount > 0UL))
{
if ((hspi->Instance->SR & SPI_FLAG_RXWNE) != 0UL)
{
*((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint32_t);
hspi->RxXferCount -= (uint16_t)4UL;
initial_RxXferCount = hspi->RxXferCount;
}
else if ((hspi->Instance->SR & SPI_FLAG_FRLVL) > SPI_RX_FIFO_1PACKET)
{
#if defined (__GNUC__)
*((uint16_t *)hspi->pRxBuffPtr) = *prxdr_16bits;
#else
*((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
#endif /* __GNUC__ */
hspi->pRxBuffPtr += sizeof(uint16_t);
hspi->RxXferCount -= (uint16_t)2UL;
initial_RxXferCount = hspi->RxXferCount;
}
else
{
*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint8_t);
hspi->RxXferCount--;
initial_RxXferCount = hspi->RxXferCount;
}
}
/* Timeout management */
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
{
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
/* Unlock the process */
__HAL_UNLOCK(hspi);
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
hspi->State = HAL_SPI_STATE_READY;
return HAL_TIMEOUT;
}
}
}
/* Wait for Tx/Rx (and CRC) data to be sent/received */
if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_EOT, RESET, tickstart, Timeout) != HAL_OK)
{
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
}
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
/* Unlock the process */
__HAL_UNLOCK(hspi);
hspi->State = HAL_SPI_STATE_READY;
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
{
return HAL_ERROR;
}
return errorcode;
}