in CMake-armcc/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c [4038:4206]
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
uint32_t XferOptions)
{
HAL_StatusTypeDef dmaxferstatus;
/* Check the parameters */
assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
{
if ((pData == NULL) || (Size == 0U))
{
hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
return HAL_ERROR;
}
/* Disable Interrupts, to prevent preemption during treatment in case of multicall */
I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT);
/* Process Locked */
__HAL_LOCK(hi2c);
/* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
/* and then toggle the HAL slave TX state to RX state */
if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
{
/* Disable associated Interrupts */
I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
{
/* Abort DMA Xfer if any */
if (hi2c->hdmatx != NULL)
{
hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
/* Set the I2C DMA Abort callback :
will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
/* Abort DMA TX */
if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
{
/* Call Directly XferAbortCallback function in case of error */
hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
}
}
}
}
else if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
{
if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
{
hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
/* Abort DMA Xfer if any */
if (hi2c->hdmarx != NULL)
{
/* Set the I2C DMA Abort callback :
will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
/* Abort DMA RX */
if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
{
/* Call Directly XferAbortCallback function in case of error */
hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
}
}
}
}
else
{
/* Nothing to do */
}
hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN;
hi2c->Mode = HAL_I2C_MODE_SLAVE;
hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
/* Enable Address Acknowledge */
hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
/* Prepare transfer parameters */
hi2c->pBuffPtr = pData;
hi2c->XferCount = Size;
hi2c->XferSize = hi2c->XferCount;
hi2c->XferOptions = XferOptions;
hi2c->XferISR = I2C_Slave_ISR_DMA;
if (hi2c->hdmarx != NULL)
{
/* Set the I2C DMA transfer complete callback */
hi2c->hdmarx->XferCpltCallback = I2C_DMASlaveReceiveCplt;
/* Set the DMA error callback */
hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
/* Set the unused DMA callbacks to NULL */
hi2c->hdmarx->XferHalfCpltCallback = NULL;
hi2c->hdmarx->XferAbortCallback = NULL;
/* Enable the DMA channel */
dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize);
}
else
{
/* Update I2C state */
hi2c->State = HAL_I2C_STATE_LISTEN;
hi2c->Mode = HAL_I2C_MODE_NONE;
/* Update I2C error code */
hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_ERROR;
}
if (dmaxferstatus == HAL_OK)
{
/* Update XferCount value */
hi2c->XferCount -= hi2c->XferSize;
/* Reset XferSize */
hi2c->XferSize = 0;
}
else
{
/* Update I2C state */
hi2c->State = HAL_I2C_STATE_LISTEN;
hi2c->Mode = HAL_I2C_MODE_NONE;
/* Update I2C error code */
hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_ERROR;
}
if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT)
{
/* Clear ADDR flag after prepare the transfer parameters */
/* This action will generate an acknowledge to the Master */
__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
}
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
/* Note : The I2C interrupts must be enabled after unlocking current process
to avoid the risk of I2C interrupt handle execution before current
process unlock */
/* REnable ADDR interrupt */
I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
/* Enable DMA Request */
hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}