in Drivers/STM32U5xx_HAL/Src/stm32u5xx_hal_spi.c [2300:2585]
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData,
uint16_t Size)
{
HAL_SPI_StateTypeDef tmp_state;
HAL_StatusTypeDef errorcode;
uint32_t tmp_mode;
/* Check Direction parameter */
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
/* Lock the process */
__HAL_LOCK(hspi);
/* Init temporary variables */
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->pTxBuffPtr = (uint8_t *)pTxData;
hspi->TxXferSize = Size;
hspi->TxXferCount = Size;
hspi->pRxBuffPtr = (uint8_t *)pRxData;
hspi->RxXferSize = Size;
hspi->RxXferCount = Size;
/* Init field not used in handle to zero */
hspi->RxISR = NULL;
hspi->TxISR = NULL;
/* Reset the Tx/Rx DMA bits */
CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);
/* Packing mode management is enabled by the DMA settings */
if (((hspi->Init.DataSize > SPI_DATASIZE_16BIT) && (hspi->hdmarx->Init.DestDataWidth != DMA_DEST_DATAWIDTH_WORD) && \
(IS_SPI_FULL_INSTANCE(hspi->Instance))) || \
((hspi->Init.DataSize > SPI_DATASIZE_8BIT) && (hspi->hdmarx->Init.DestDataWidth == DMA_DEST_DATAWIDTH_BYTE)))
{
/* Restriction the DMA data received is not allowed in this mode */
errorcode = HAL_ERROR;
/* Unlock the process */
__HAL_UNLOCK(hspi);
return errorcode;
}
/* Adjust XferCount according to DMA alignment / Data size */
if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
{
if (hspi->hdmatx->Init.SrcDataWidth == DMA_SRC_DATAWIDTH_HALFWORD)
{
hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 1UL) >> 1UL;
}
if (hspi->hdmatx->Init.SrcDataWidth == DMA_SRC_DATAWIDTH_WORD)
{
hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 3UL) >> 2UL;
}
if (hspi->hdmarx->Init.DestDataWidth == DMA_DEST_DATAWIDTH_HALFWORD)
{
hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 1UL) >> 1UL;
}
if (hspi->hdmarx->Init.DestDataWidth == DMA_DEST_DATAWIDTH_WORD)
{
hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 3UL) >> 2UL;
}
}
else if (hspi->Init.DataSize <= SPI_DATASIZE_16BIT)
{
if (hspi->hdmatx->Init.SrcDataWidth == DMA_SRC_DATAWIDTH_WORD)
{
hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 1UL) >> 1UL;
}
if (hspi->hdmarx->Init.DestDataWidth == DMA_DEST_DATAWIDTH_WORD)
{
hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 1UL) >> 1UL;
}
}
else
{
/* Adjustment done */
}
/* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */
if (hspi->State == HAL_SPI_STATE_BUSY_RX)
{
/* Set the SPI Rx DMA Half transfer complete callback */
hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
}
else
{
/* Set the SPI Tx/Rx DMA Half transfer complete callback */
hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt;
}
/* Set the DMA error callback */
hspi->hdmarx->XferErrorCallback = SPI_DMAError;
/* Set the DMA AbortCallback */
hspi->hdmarx->XferAbortCallback = NULL;
if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
{
hspi->RxXferCount = Size;
}
else if (hspi->Init.DataSize <= SPI_DATASIZE_16BIT)
{
hspi->RxXferCount = Size * 2U;
}
else
{
hspi->RxXferCount = Size * 4U;
}
/* Enable the Rx DMA Stream/Channel */
if ((hspi->hdmarx->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
{
if (hspi->hdmarx->LinkedListQueue != NULL)
{
/* Set DMA data size */
hspi->hdmarx->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = hspi->RxXferCount;
/* Set DMA source address */
hspi->hdmarx->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)&hspi->Instance->RXDR;
/* Set DMA destination address */
hspi->hdmarx->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = (uint32_t)hspi->pRxBuffPtr;
errorcode = HAL_DMAEx_List_Start_IT(hspi->hdmarx);
}
else
{
/* Update SPI error code */
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
/* Unlock the process */
__HAL_UNLOCK(hspi);
hspi->State = HAL_SPI_STATE_READY;
errorcode = HAL_ERROR;
return errorcode;
}
}
else
{
errorcode = HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->RXDR, (uint32_t)hspi->pRxBuffPtr,
hspi->RxXferCount);
}
/* Check status */
if (errorcode != HAL_OK)
{
/* Update SPI error code */
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
/* Unlock the process */
__HAL_UNLOCK(hspi);
hspi->State = HAL_SPI_STATE_READY;
errorcode = HAL_ERROR;
return errorcode;
}
/* Enable Rx DMA Request */
SET_BIT(hspi->Instance->CFG1, SPI_CFG1_RXDMAEN);
/* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing
is performed in DMA reception complete callback */
hspi->hdmatx->XferHalfCpltCallback = NULL;
hspi->hdmatx->XferCpltCallback = NULL;
hspi->hdmatx->XferErrorCallback = NULL;
hspi->hdmatx->XferAbortCallback = NULL;
if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
{
hspi->TxXferCount = Size;
}
else if (hspi->Init.DataSize <= SPI_DATASIZE_16BIT)
{
hspi->TxXferCount = Size * 2U;
}
else
{
hspi->TxXferCount = Size * 4U;
}
/* Enable the Tx DMA Stream/Channel */
if ((hspi->hdmatx->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
{
if (hspi->hdmatx->LinkedListQueue != NULL)
{
/* Set DMA data size */
hspi->hdmatx->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = hspi->TxXferCount;
/* Set DMA source address */
hspi->hdmatx->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)hspi->pTxBuffPtr;
/* Set DMA destination address */
hspi->hdmatx->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = (uint32_t)&hspi->Instance->TXDR;
errorcode = HAL_DMAEx_List_Start_IT(hspi->hdmatx);
}
else
{
/* Update SPI error code */
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
/* Unlock the process */
__HAL_UNLOCK(hspi);
hspi->State = HAL_SPI_STATE_READY;
errorcode = HAL_ERROR;
return errorcode;
}
}
else
{
errorcode = HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->TXDR,
hspi->TxXferCount);
}
/* Check status */
if (errorcode != HAL_OK)
{
/* Update SPI error code */
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
/* Unlock the process */
__HAL_UNLOCK(hspi);
hspi->State = HAL_SPI_STATE_READY;
errorcode = HAL_ERROR;
return errorcode;
}
if ((hspi->hdmarx->Mode == DMA_LINKEDLIST_CIRCULAR) && (hspi->hdmatx->Mode == DMA_LINKEDLIST_CIRCULAR))
{
MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, 0UL);
}
else
{
MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
}
/* Enable Tx DMA Request */
SET_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN);
/* Enable the SPI Error Interrupt Bit */
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_OVR | SPI_IT_UDR | SPI_IT_FRE | SPI_IT_MODF));
/* Enable SPI peripheral */
__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);
}
/* Unlock the process */
__HAL_UNLOCK(hspi);
return errorcode;
}