in hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c_v1.c [620:913]
HAL_StatusTypeDef HAL_I2C_Master_Receive_Custom(I2C_HandleTypeDef *hi2c,
uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout,
uint8_t LastOp)
{
uint32_t tickstart = 0x00U;
/* Init tickstart for timeout management*/
tickstart = HAL_GetTick();
if(hi2c->State == HAL_I2C_STATE_READY)
{
if (hi2c->Mode != HAL_I2C_MODE_MASTER_SEL)
{
/* Wait until BUSY flag is reset */
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK)
{
return HAL_BUSY;
}
}
/* Process Locked */
__HAL_LOCK(hi2c);
/* Check if the I2C is already enabled */
if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE)
{
/* Enable I2C peripheral */
__HAL_I2C_ENABLE(hi2c);
}
/* Disable Pos */
hi2c->Instance->CR1 &= ~I2C_CR1_POS;
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 = I2C_NO_OPTION_FRAME;
hi2c->XferSize = hi2c->XferCount;
/* Send Slave Address */
if(I2C_MasterRequestRead(hi2c, DevAddress, Timeout, tickstart) != HAL_OK)
{
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
{
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_ERROR;
}
else
{
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_TIMEOUT;
}
}
if(hi2c->XferSize == 0U)
{
/* Clear ADDR flag */
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);
if (LastOp)
{
/* Generate Stop */
hi2c->Instance->CR1 |= I2C_CR1_STOP;
}
}
else if(hi2c->XferSize == 1U)
{
/* Disable Acknowledge */
hi2c->Instance->CR1 &= ~I2C_CR1_ACK;
#if MYNEWT_VAL(MCU_STM32F1)
/* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
software sequence must complete before the current byte end of transfer */
__disable_irq();
#endif
/* Clear ADDR flag */
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);
if (LastOp)
{
/* Generate Stop */
hi2c->Instance->CR1 |= I2C_CR1_STOP;
}
#if MYNEWT_VAL(MCU_STM32F1)
/* Re-enable IRQs */
__enable_irq();
#endif
}
else if(hi2c->XferSize == 2U)
{
#if MYNEWT_VAL(MCU_STM32F1)
/* Enable Pos */
hi2c->Instance->CR1 |= I2C_CR1_POS;
/* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
software sequence must complete before the current byte end of transfer */
__disable_irq();
/* Clear ADDR flag */
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);
/* Disable Acknowledge */
hi2c->Instance->CR1 &= ~I2C_CR1_ACK;
/* Re-enable IRQs */
__enable_irq();
#else
/* Disable Acknowledge */
hi2c->Instance->CR1 &= ~I2C_CR1_ACK;
/* Enable Pos */
hi2c->Instance->CR1 |= I2C_CR1_POS;
/* Clear ADDR flag */
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);
#endif
}
else
{
/* Enable Acknowledge */
hi2c->Instance->CR1 |= I2C_CR1_ACK;
/* Clear ADDR flag */
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);
}
while(hi2c->XferSize > 0U)
{
if(hi2c->XferSize <= 3U)
{
/* One byte */
if(hi2c->XferSize == 1U)
{
/* Wait until RXNE flag is set */
if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
{
if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT)
{
return HAL_TIMEOUT;
}
else
{
return HAL_ERROR;
}
}
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
}
/* Two bytes */
else if(hi2c->XferSize == 2U)
{
/* Wait until BTF flag is set */
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK)
{
return HAL_TIMEOUT;
}
#if MYNEWT_VAL(MCU_STM32F1)
/* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
software sequence must complete before the current byte end of transfer */
__disable_irq();
#endif
if (LastOp)
{
/* Generate Stop */
hi2c->Instance->CR1 |= I2C_CR1_STOP;
}
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
#if MYNEWT_VAL(MCU_STM32F1)
/* Re-enable IRQs */
__enable_irq();
#endif
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
}
/* 3 Last bytes */
else
{
/* Wait until BTF flag is set */
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK)
{
return HAL_TIMEOUT;
}
/* Disable Acknowledge */
hi2c->Instance->CR1 &= ~I2C_CR1_ACK;
#if MYNEWT_VAL(MCU_STM32F1)
/* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
software sequence must complete before the current byte end of transfer */
__disable_irq();
#endif
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
/* Wait until BTF flag is set */
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK)
{
#if MYNEWT_VAL(MCU_STM32F1)
/* Re-enable IRQs */
__enable_irq();
#endif
return HAL_TIMEOUT;
}
if (LastOp)
{
/* Generate Stop */
hi2c->Instance->CR1 |= I2C_CR1_STOP;
}
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
#if MYNEWT_VAL(MCU_STM32F1)
/* Re-enable IRQs */
__enable_irq();
#endif
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
}
}
else
{
/* Wait until RXNE flag is set */
if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
{
if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT)
{
return HAL_TIMEOUT;
}
else
{
return HAL_ERROR;
}
}
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET)
{
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
}
}
}
hi2c->State = HAL_I2C_STATE_READY;
if (LastOp) {
hi2c->Mode = HAL_I2C_MODE_NONE;
} else {
hi2c->Mode = HAL_I2C_MODE_MASTER_SEL;
}
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}