in CMake-armcc/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c [3505:3654]
HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
uint16_t Size, uint32_t XferOptions)
{
uint32_t xfermode;
uint32_t xferrequest = I2C_GENERATE_START_READ;
HAL_StatusTypeDef dmaxferstatus;
/* Check the parameters */
assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
if (hi2c->State == HAL_I2C_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hi2c);
hi2c->State = HAL_I2C_STATE_BUSY_RX;
hi2c->Mode = HAL_I2C_MODE_MASTER;
hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
/* Prepare transfer parameters */
hi2c->pBuffPtr = pData;
hi2c->XferCount = Size;
hi2c->XferOptions = XferOptions;
hi2c->XferISR = I2C_Master_ISR_DMA;
/* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
if (hi2c->XferCount > MAX_NBYTE_SIZE)
{
hi2c->XferSize = MAX_NBYTE_SIZE;
xfermode = I2C_RELOAD_MODE;
}
else
{
hi2c->XferSize = hi2c->XferCount;
xfermode = hi2c->XferOptions;
}
/* If transfer direction not change and there is no request to start another frame, do not generate Restart Condition */
/* Mean Previous state is same as current state */
if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) && (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
{
xferrequest = I2C_NO_STARTSTOP;
}
else
{
/* Convert OTHER_xxx XferOptions if any */
I2C_ConvertOtherXferOptions(hi2c);
/* Update xfermode accordingly if no reload is necessary */
if (hi2c->XferCount <= MAX_NBYTE_SIZE)
{
xfermode = hi2c->XferOptions;
}
}
if (hi2c->XferSize > 0U)
{
if (hi2c->hdmarx != NULL)
{
/* Set the I2C DMA transfer complete callback */
hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt;
/* 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_READY;
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)
{
/* Send Slave Address and set NBYTES to read */
I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
/* Update XferCount value */
hi2c->XferCount -= hi2c->XferSize;
/* 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 */
/* Enable ERR and NACK interrupts */
I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
/* Enable DMA Request */
hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
}
else
{
/* Update I2C state */
hi2c->State = HAL_I2C_STATE_READY;
hi2c->Mode = HAL_I2C_MODE_NONE;
/* Update I2C error code */
hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_ERROR;
}
}
else
{
/* Update Transfer ISR function pointer */
hi2c->XferISR = I2C_Master_ISR_IT;
/* Send Slave Address */
/* Set NBYTES to read and generate START condition */
I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
/* 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 */
/* Enable ERR, TC, STOP, NACK, TXI interrupt */
/* possible to enable all of these */
/* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}