int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); int timeout; int count; int value; if (length == 0) return 0; /* update CR2 register */ i2c->CR2 = (i2c->CR2 & (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP))) | (uint32_t)(((uint32_t)address & I2C_CR2_SADD) | (((uint32_t)length << 16) & I2C_CR2_NBYTES) | (uint32_t)I2C_SOFTEND_MODE | (uint32_t)I2C_GENERATE_START_READ); // Read all bytes for (count = 0; count < length; count++) { value = i2c_byte_read(obj, 0); data[count] = (char)value; } // Wait transfer complete timeout = LONG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_TC) == RESET) { timeout--; if (timeout == 0) { return 0; } } __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_TC); // If not repeated start, send stop. if (stop) { i2c_stop(obj); /* Wait until STOPF flag is set */ timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_STOPF) == RESET) { timeout--; if (timeout == 0) { return 0; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_STOPF); } return length; }
inline int i2c_start(i2c_t *obj) { I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); int timeout; I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); // Clear Acknowledge failure flag __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_AF); // Wait the STOP condition has been previously correctly sent timeout = FLAG_TIMEOUT; while ((i2c->CR2 & I2C_CR2_STOP) == I2C_CR2_STOP){ if ((timeout--) == 0) { return 1; } } // Generate the START condition i2c->CR2 |= I2C_CR2_START; // Wait the START condition has been correctly sent timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BUSY) == RESET) { if ((timeout--) == 0) { return 1; } } return 0; }
inline int i2c_start(i2c_t *obj) { I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); int timeout; I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); // Clear Acknowledge failure flag __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_AF); // Wait the STOP condition has been previously correctly sent // This timeout can be avoid in some specific cases by simply clearing the STOP bit timeout = FLAG_TIMEOUT; while ((i2c->CR1 & I2C_CR1_STOP) == I2C_CR1_STOP) { if ((timeout--) == 0) { return 1; } } // Generate the START condition i2c->CR1 |= I2C_CR1_START; // Wait the START condition has been correctly sent timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_SB) == RESET) { if ((timeout--) == 0) { return 1; } } return 0; }
// this function is based on STM code STATIC int send_addr_byte(I2C_HandleTypeDef *hi2c, uint8_t addr_byte, uint32_t Timeout, uint32_t Tickstart) { /* Generate Start */ hi2c->Instance->CR1 |= I2C_CR1_START; /* Wait until SB flag is set */ if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart)) { return -MP_ETIMEDOUT; } /* Send slave address */ hi2c->Instance->DR = addr_byte; /* Wait until ADDR flag is set */ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) == RESET) { if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) { // nack received for addr, release the bus cleanly hi2c->Instance->CR1 |= I2C_CR1_STOP; __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); return -MP_ENODEV; } /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { if ((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout)) { return -MP_ETIMEDOUT; } } } return 0; }
int i2c_slave_write(i2c_t *obj, const char *data, int length) { uint32_t Timeout; int size = 0; I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); while (length > 0) { /* Wait until TXE flag is set */ Timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_TXE) == RESET) { Timeout--; if (Timeout == 0) { return -1; } } /* Write data to DR */ I2cHandle.Instance->DR = (*data++); length--; size++; if ((__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BTF) == SET) && (length != 0)) { /* Write data to DR */ I2cHandle.Instance->DR = (*data++); length--; size++; } } /* Wait until AF flag is set */ Timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_AF) == RESET) { Timeout--; if (Timeout == 0) { return -1; } } /* Clear AF flag */ __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_AF); /* Wait until BUSY flag is reset */ Timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BUSY) == SET) { Timeout--; if (Timeout == 0) { return -1; } } I2cHandle.State = HAL_I2C_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(&I2cHandle); return size; }
// this function is based on STM code STATIC bool I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) { if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) { /* Clear NACKF Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); return true; } return false; }
/** * @brief This function handles Acknowledge failed detection during an I2C Communication. * @param hi2c: Pointer to a I2C_HandleTypeDef structure that contains * the configuration information for the specified I2C. * @param Timeout: Timeout duration * @param Tickstart: Tick start value * @retval HAL status */ static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) { /* Wait until STOP Flag is reset */ /* AutoEnd should be initiate after AF */ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) { /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0)||((HAL_GetTick() - Tickstart) > Timeout)) { hi2c->State= HAL_I2C_STATE_READY; hi2c->Mode = HAL_I2C_MODE_NONE; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_TIMEOUT; } } } /* Clear NACKF Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); /* Flush TX register */ I2C_Flush_TXDR(hi2c); /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); hi2c->ErrorCode = HAL_I2C_ERROR_AF; hi2c->State= HAL_I2C_STATE_READY; hi2c->Mode = HAL_I2C_MODE_NONE; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_ERROR; } return HAL_OK; }
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); int timeout; int count; // Update CR2 register i2c->CR2 = (i2c->CR2 & (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP))) | (uint32_t)(((uint32_t)address & I2C_CR2_SADD) | (((uint32_t)length << 16) & I2C_CR2_NBYTES) | (uint32_t)I2C_SOFTEND_MODE | (uint32_t)I2C_GENERATE_START_WRITE); for (count = 0; count < length; count++) { i2c_byte_write(obj, data[count]); } // Wait transfer complete timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_TC) == RESET) { timeout--; if (timeout == 0) { return -1; } } __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_TC); // If not repeated start, send stop if (stop) { i2c_stop(obj); // Wait until STOPF flag is set timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_STOPF) == RESET) { timeout--; if (timeout == 0) { return -1; } } // Clear STOP Flag __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_STOPF); } return count; }
/** * @brief I2C Tx data register flush process. * @param hi2c: I2C handle. * @retval None */ static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c) { /* If a pending TXIS flag is set */ /* Write a dummy data in TXDR to clear it */ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET) { hi2c->Instance->TXDR = 0x00; } /* Flush TX register if not empty */ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) { __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE); } }
int i2c_slave_receive(i2c_t *obj) { int retValue = NoData; if (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BUSY) == 1) { if (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_ADDR) == 1) { if (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_TRA) == 1) retValue = ReadAddressed; else retValue = WriteAddressed; __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_ADDR); } } return (retValue); }
int i2c_slave_receive(i2c_t *obj) { I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); int retValue = NoData; if (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BUSY) == 1) { if (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_ADDR) == 1) { if (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_DIR) == 1) retValue = ReadAddressed; else retValue = WriteAddressed; __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_ADDR); } } return (retValue); }
// this function is based on STM code STATIC int I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) { /* Check if a STOPF is detected */ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) { /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); return -MP_EBUSY; } /* Check for the Timeout */ if ((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) { return -MP_ETIMEDOUT; } } return 0; }
/** * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag. * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains * the configuration information for the specified I2C. * @param Timeout Timeout duration * @param Tickstart Tick start value * @retval HAL status */ static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart, uint8_t prev_mode) { while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) { /* Check if a NACK is detected */ if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK) { return HAL_NACK; } /* * FIXME: need to re-check if what is supposed to be a RESTART is not also * triggering a STOP along... */ /* Check if a STOPF is detected */ if (prev_mode != HAL_I2C_MODE_MASTER_SEL && __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) { /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); hi2c->ErrorCode = HAL_I2C_ERROR_NONE; hi2c->State = HAL_I2C_STATE_READY; hi2c->Mode = HAL_I2C_MODE_NONE; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_ERROR; } /* Check for the Timeout */ if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) { hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; hi2c->State = HAL_I2C_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_TIMEOUT; } } return HAL_OK; }
inline int i2c_start(i2c_t *obj) { I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); int timeout; I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); // Clear Acknowledge failure flag __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_AF); // Generate the START condition and remove an eventual pending STOP bit i2c->CR1 = ((i2c->CR1 & ~I2C_CR1_STOP) | I2C_CR1_START); // Wait the START condition has been correctly sent timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_SB) == RESET) { if ((timeout--) == 0) { return 1; } } return 0; }
void i2c_er_irq_handler(mp_uint_t i2c_id) { I2C_HandleTypeDef *hi2c; switch (i2c_id) { #if defined(MICROPY_HW_I2C1_SCL) case 1: hi2c = &I2CHandle1; break; #endif #if defined(MICROPY_HW_I2C2_SCL) case 2: hi2c = &I2CHandle2; break; #endif #if defined(MICROPY_HW_I2C3_SCL) case 3: hi2c = &I2CHandle3; break; #endif #if defined(MICROPY_HW_I2C4_SCL) case 4: hi2c = &I2CHandle4; break; #endif default: return; } #if defined(MCU_SERIES_F4) uint32_t sr1 = hi2c->Instance->SR1; // I2C Bus error if (sr1 & I2C_FLAG_BERR) { hi2c->ErrorCode |= HAL_I2C_ERROR_BERR; __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR); } // I2C Arbitration Loss error if (sr1 & I2C_FLAG_ARLO) { hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO; __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO); } // I2C Acknowledge failure if (sr1 & I2C_FLAG_AF) { hi2c->ErrorCode |= HAL_I2C_ERROR_AF; SET_BIT(hi2c->Instance->CR1,I2C_CR1_STOP); __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); } // I2C Over-Run/Under-Run if (sr1 & I2C_FLAG_OVR) { hi2c->ErrorCode |= HAL_I2C_ERROR_OVR; __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR); } #else // if not an F4 MCU, use the HAL's IRQ handler HAL_I2C_ER_IRQHandler(hi2c); #endif }
unsigned long TWI_MasterWriteRead(new_twi* TwiStruct, unsigned int TransmitBytes, unsigned int ReceiveBytes) { uint32_t tickstart = 0; I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)TwiStruct->udata; /* Init tickstart for timeout management*/ tickstart = HAL_GetTick(); if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) { I2C_SoftwareResetCmd(hi2c); return HAL_TIMEOUT; } hi2c->State = HAL_I2C_STATE_BUSY_TX; hi2c->Mode = HAL_I2C_MODE_MASTER; hi2c->ErrorCode = HAL_I2C_ERROR_NONE; /* Prepare transfer parameters */ hi2c->pBuffPtr = TwiStruct->TxBuff; hi2c->XferCount = TransmitBytes; hi2c->XferISR = NULL; /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); } else { if(ReceiveBytes != 0) { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE); } } do { tickstart = HAL_GetTick(); /* Wait until TXIS flag is set */ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Read data from RXDR */ hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); hi2c->XferCount--; hi2c->XferSize--; if((hi2c->XferSize == 0) && (hi2c->XferCount != 0)) { /* Wait until TCR flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else { if(ReceiveBytes != 0) { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_NO_STARTSTOP); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } } }while(hi2c->XferCount > 0); if(ReceiveBytes == 0) { /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is reset */ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); hi2c->State = HAL_I2C_STATE_READY; hi2c->Mode = HAL_I2C_MODE_NONE; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_OK; } tickstart = HAL_GetTick(); /* Wait until TCR flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } hi2c->State = HAL_I2C_STATE_BUSY_RX; hi2c->Mode = HAL_I2C_MODE_MASTER; hi2c->ErrorCode = HAL_I2C_ERROR_NONE; /* Prepare transfer parameters */ hi2c->pBuffPtr = TwiStruct->RxBuff; hi2c->XferCount = ReceiveBytes; hi2c->XferISR = NULL; /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr | 1, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr | 1, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); } do { tickstart = HAL_GetTick(); /* Wait until RXNE flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } /* Read data from RXDR */ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; hi2c->XferSize--; hi2c->XferCount--; if((hi2c->XferSize == 0) && (hi2c->XferCount != 0)) { /* Wait until TCR flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr | 1, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr | 1, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } }while(hi2c->XferCount > 0); /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is reset */ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); hi2c->State = HAL_I2C_STATE_READY; hi2c->Mode = HAL_I2C_MODE_NONE; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_OK; }
/** * @brief Receives in master mode an amount of data in blocking mode. * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains * the configuration information for the specified I2C. * @param DevAddress Target device address The device 7 bits address value * in datasheet must be shifted to the left before calling the interface * @param pData Pointer to data buffer * @param Size Amount of data to be sent * @param Timeout Timeout duration * @param LastOp If set sends STOP, otherwise no STOP * @retval HAL status */ 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 = 0U; uint8_t prev_mode = 0; HAL_StatusTypeDef rc; if (hi2c->State == HAL_I2C_STATE_READY) { /* Process Locked */ __HAL_LOCK(hi2c); /* Init tickstart for timeout management */ tickstart = HAL_GetTick(); prev_mode = hi2c->Mode; if (prev_mode != HAL_I2C_MODE_MASTER_SEL) { if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) { return HAL_TIMEOUT; } } 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->XferISR = NULL; /* Send Slave Address */ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ if (hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); } else if (!LastOp) { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_READ); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); } while (hi2c->XferCount > 0U) { /* Wait until RXNE flag is set */ rc = I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart, prev_mode); if (rc != HAL_OK && rc != HAL_NACK) { if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Read data from RXDR */ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; hi2c->XferSize--; hi2c->XferCount--; if (rc == HAL_NACK) { break; } if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) { /* Wait until TCR flag is set */ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } if (hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else if (!LastOp) { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_NO_STARTSTOP); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } } if (LastOp) { /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is set */ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); } else { /* No autoend/reload was requested, make sure transmission of last byte * has finished... */ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, SET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } } /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); 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; } }