int stm32_i2c_configure_timing(struct device *dev, u32_t clock) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); I2C_TypeDef *i2c = cfg->i2c; u32_t i2c_hold_time_min, i2c_setup_time_min; u32_t i2c_h_min_time, i2c_l_min_time; u32_t presc = 1; u32_t timing = 0; switch (I2C_SPEED_GET(data->dev_config)) { case I2C_SPEED_STANDARD: i2c_h_min_time = 4000; i2c_l_min_time = 4700; i2c_hold_time_min = 500; i2c_setup_time_min = 1250; break; case I2C_SPEED_FAST: i2c_h_min_time = 600; i2c_l_min_time = 1300; i2c_hold_time_min = 375; i2c_setup_time_min = 500; break; default: return -EINVAL; } /* Calculate period until prescaler matches */ do { u32_t t_presc = clock / presc; u32_t ns_presc = NSEC_PER_SEC / t_presc; u32_t sclh = i2c_h_min_time / ns_presc; u32_t scll = i2c_l_min_time / ns_presc; u32_t sdadel = i2c_hold_time_min / ns_presc; u32_t scldel = i2c_setup_time_min / ns_presc; if ((sclh - 1) > 255 || (scll - 1) > 255) { ++presc; continue; } if (sdadel > 15 || (scldel - 1) > 15) { ++presc; continue; } timing = __LL_I2C_CONVERT_TIMINGS(presc - 1, scldel - 1, sdadel, sclh - 1, scll - 1); break; } while (presc < 16); if (presc >= 16) { SYS_LOG_DBG("I2C:failed to find prescaler value"); return -EINVAL; } LL_I2C_SetTiming(i2c, timing); return 0; }
/** * @brief Initialize the I2C registers according to the specified parameters in I2C_InitStruct. * @param I2Cx I2C Instance. * @param I2C_InitStruct pointer to a @ref LL_I2C_InitTypeDef structure. * @retval An ErrorStatus enumeration value: * - SUCCESS: I2C registers are initialized * - ERROR: Not applicable */ uint32_t LL_I2C_Init(I2C_TypeDef *I2Cx, LL_I2C_InitTypeDef *I2C_InitStruct) { /* Check the I2C Instance I2Cx */ assert_param(IS_I2C_ALL_INSTANCE(I2Cx)); /* Check the I2C parameters from I2C_InitStruct */ assert_param(IS_LL_I2C_PERIPHERAL_MODE(I2C_InitStruct->PeripheralMode)); assert_param(IS_LL_I2C_ANALOG_FILTER(I2C_InitStruct->AnalogFilter)); assert_param(IS_LL_I2C_DIGITAL_FILTER(I2C_InitStruct->DigitalFilter)); assert_param(IS_LL_I2C_OWN_ADDRESS1(I2C_InitStruct->OwnAddress1)); assert_param(IS_LL_I2C_TYPE_ACKNOWLEDGE(I2C_InitStruct->TypeAcknowledge)); assert_param(IS_LL_I2C_OWN_ADDRSIZE(I2C_InitStruct->OwnAddrSize)); /* Disable the selected I2Cx Peripheral */ LL_I2C_Disable(I2Cx); /*---------------------------- I2Cx CR1 Configuration ------------------------ * Configure the analog and digital noise filters with parameters : * - AnalogFilter: I2C_CR1_ANFOFF bit * - DigitalFilter: I2C_CR1_DNF[3:0] bits */ LL_I2C_ConfigFilters(I2Cx, I2C_InitStruct->AnalogFilter, I2C_InitStruct->DigitalFilter); /*---------------------------- I2Cx TIMINGR Configuration -------------------- * Configure the SDA setup, hold time and the SCL high, low period with parameter : * - Timing: I2C_TIMINGR_PRESC[3:0], I2C_TIMINGR_SCLDEL[3:0], I2C_TIMINGR_SDADEL[3:0], * I2C_TIMINGR_SCLH[7:0] and I2C_TIMINGR_SCLL[7:0] bits */ LL_I2C_SetTiming(I2Cx, I2C_InitStruct->Timing); /* Enable the selected I2Cx Peripheral */ LL_I2C_Enable(I2Cx); /*---------------------------- I2Cx OAR1 Configuration ----------------------- * Disable, Configure and Enable I2Cx device own address 1 with parameters : * - OwnAddress1: I2C_OAR1_OA1[9:0] bits * - OwnAddrSize: I2C_OAR1_OA1MODE bit */ LL_I2C_DisableOwnAddress1(I2Cx); LL_I2C_SetOwnAddress1(I2Cx, I2C_InitStruct->OwnAddress1, I2C_InitStruct->OwnAddrSize); LL_I2C_EnableOwnAddress1(I2Cx); /*---------------------------- I2Cx MODE Configuration ----------------------- * Configure I2Cx peripheral mode with parameter : * - PeripheralMode: I2C_CR1_SMBDEN and I2C_CR1_SMBHEN bits */ LL_I2C_SetMode(I2Cx, I2C_InitStruct->PeripheralMode); /*---------------------------- I2Cx CR2 Configuration ------------------------ * Configure the ACKnowledge or Non ACKnowledge condition * after the address receive match code or next received byte with parameter : * - TypeAcknowledge: I2C_CR2_NACK bit */ LL_I2C_AcknowledgeNextData(I2Cx, I2C_InitStruct->TypeAcknowledge); return SUCCESS; }