/** * @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; }
/** * @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) { LL_RCC_ClocksTypeDef rcc_clocks; /* 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_CLOCK_SPEED(I2C_InitStruct->ClockSpeed)); assert_param(IS_LL_I2C_DUTY_CYCLE(I2C_InitStruct->DutyCycle)); 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); /* Retrieve Clock frequencies */ LL_RCC_GetSystemClocksFreq(&rcc_clocks); /*---------------------------- I2Cx SCL Clock Speed Configuration ------------ * Configure the SCL speed : * - ClockSpeed: I2C_CR2_FREQ[5:0], I2C_TRISE_TRISE[5:0], I2C_CCR_FS, * and I2C_CCR_CCR[11:0] bits * - DutyCycle: I2C_CCR_DUTY[7:0] bits */ LL_I2C_ConfigSpeed(I2Cx, rcc_clocks.PCLK1_Frequency, I2C_InitStruct->ClockSpeed, I2C_InitStruct->DutyCycle); /*---------------------------- I2Cx OAR1 Configuration ----------------------- * Disable, Configure and Enable I2Cx device own address 1 with parameters : * - OwnAddress1: I2C_OAR1_ADD[9:8], I2C_OAR1_ADD[7:1] and I2C_OAR1_ADD0 bits * - OwnAddrSize: I2C_OAR1_ADDMODE bit */ LL_I2C_SetOwnAddress1(I2Cx, I2C_InitStruct->OwnAddress1, I2C_InitStruct->OwnAddrSize); /*---------------------------- I2Cx MODE Configuration ----------------------- * Configure I2Cx peripheral mode with parameter : * - PeripheralMode: I2C_CR1_SMBUS, I2C_CR1_SMBTYPE and I2C_CR1_ENARP bits */ LL_I2C_SetMode(I2Cx, I2C_InitStruct->PeripheralMode); /* Enable the selected I2Cx Peripheral */ LL_I2C_Enable(I2Cx); /*---------------------------- 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; }
/* Attach and start I2C as slave */ int i2c_stm32_slave_register(struct device *dev, struct i2c_slave_config *config) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); I2C_TypeDef *i2c = cfg->i2c; u32_t bitrate_cfg; int ret; if (!config) { return -EINVAL; } if (data->slave_attached) { return -EBUSY; } if (data->master_active) { return -EBUSY; } bitrate_cfg = _i2c_map_dt_bitrate(cfg->bitrate); ret = i2c_stm32_runtime_configure(dev, bitrate_cfg); if (ret < 0) { SYS_LOG_ERR("i2c: failure initializing"); return ret; } data->slave_cfg = config; LL_I2C_Enable(i2c); LL_I2C_SetOwnAddress1(i2c, config->address << 1, LL_I2C_OWNADDRESS1_7BIT); LL_I2C_EnableOwnAddress1(i2c); data->slave_attached = true; SYS_LOG_DBG("i2c: slave registered"); LL_I2C_EnableIT_ADDR(i2c); return 0; }
static inline void msg_init(struct device *dev, struct i2c_msg *msg, u8_t *next_msg_flags, u16_t slave, uint32_t transfer) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); I2C_TypeDef *i2c = cfg->i2c; if (LL_I2C_IsEnabledReloadMode(i2c)) { LL_I2C_SetTransferSize(i2c, msg->len); } else { if (I2C_ADDR_10_BITS & data->dev_config) { LL_I2C_SetMasterAddressingMode(i2c, LL_I2C_ADDRESSING_MODE_10BIT); LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave); } else { LL_I2C_SetMasterAddressingMode(i2c, LL_I2C_ADDRESSING_MODE_7BIT); LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave << 1); } if (!(msg->flags & I2C_MSG_STOP) && next_msg_flags && !(*next_msg_flags & I2C_MSG_RESTART)) { LL_I2C_EnableReloadMode(i2c); } else { LL_I2C_DisableReloadMode(i2c); } LL_I2C_DisableAutoEndMode(i2c); LL_I2C_SetTransferRequest(i2c, transfer); LL_I2C_SetTransferSize(i2c, msg->len); #if defined(CONFIG_I2C_SLAVE) data->master_active = true; #endif LL_I2C_Enable(i2c); LL_I2C_GenerateStartCondition(i2c); } }
static int i2c_stm32_transfer(struct device *dev, struct i2c_msg *msg, u8_t num_msgs, u16_t slave) { struct i2c_stm32_data *data = DEV_DATA(dev); #if defined(CONFIG_I2C_STM32_V1) const struct i2c_stm32_config *cfg = DEV_CFG(dev); I2C_TypeDef *i2c = cfg->i2c; #endif struct i2c_msg *current, *next; int ret = 0; /* Check for validity of all messages, to prevent having to abort * in the middle of a transfer */ current = msg; /* * Set I2C_MSG_RESTART flag on first message in order to send start * condition */ current->flags |= I2C_MSG_RESTART; for (u8_t i = 1; i <= num_msgs; i++) { /* Maximum length of a single message is 255 Bytes */ if (current->len > 255) { ret = -EINVAL; break; } if (i < num_msgs) { next = current + 1; /* * Restart condition between messages * of different directions is required */ if (OPERATION(current) != OPERATION(next)) { if (!(next->flags & I2C_MSG_RESTART)) { ret = -EINVAL; break; } } /* Stop condition is only allowed on last message */ if (current->flags & I2C_MSG_STOP) { ret = -EINVAL; break; } } else { /* Stop condition is required for the last message */ current->flags |= I2C_MSG_STOP; } current++; } if (ret) { return ret; } /* Send out messages */ k_sem_take(&data->bus_mutex, K_FOREVER); #if defined(CONFIG_I2C_STM32_V1) LL_I2C_Enable(i2c); #endif current = msg; while (num_msgs > 0) { u8_t *next_msg_flags = NULL; if (num_msgs > 1) { next = current + 1; next_msg_flags = &(next->flags); } if ((current->flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { ret = stm32_i2c_msg_write(dev, current, next_msg_flags, slave); } else { ret = stm32_i2c_msg_read(dev, current, next_msg_flags, slave); } if (ret < 0) { break; } current++; num_msgs--; } #if defined(CONFIG_I2C_STM32_V1) LL_I2C_Disable(i2c); #endif k_sem_give(&data->bus_mutex); return ret; }