diff options
-rw-r--r-- | os/hal/include/i2c.h | 11 | ||||
-rw-r--r-- | os/hal/platforms/STM32/i2c_lld.c | 14 |
2 files changed, 21 insertions, 4 deletions
diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 2d07ae8f2..c2f717432 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -79,8 +79,15 @@ typedef enum { /**
* @brief I2C notification callback type.
- * @details This function must be used to send start or stop events to I2C bus,
- * and change states of I2CDriver.
+ * @details This callback invoked when byte transfer finish event generated,
+ * No matter sending or reading. This function designed
+ * for sending (re)start or stop events to I2C bus.
+ * Use "restart" boolean flag
+ * in I2CSlaveConfig structure for this needs.
+ * Each slave can (must?) have its own callback function.
+ *
+ * If callback function is set to NULL - driver generate stop
+ * condition on the bus after the transfer finish.
*
* @param[in] i2cp pointer to the @p I2CDriver object triggering the
* callback
diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 154a735fa..cb75b6da2 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -195,8 +195,16 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ chSysLockFromIsr(); i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt - i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); chSysUnlockFromIsr(); + /* now driver is ready to generate (re)start/stop condition. + * Callback function is good place to do that.*/ + i2cp->id_state = I2C_READY; + + if (i2cp->id_slave_config->id_callback != NULL) + i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); + else /* If no callback function set - generate stop */ + i2c_lld_master_stop(i2cp); + return; } else{ // debugging trap @@ -455,7 +463,9 @@ void i2c_lld_master_start(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_START; while (i2cp->id_i2c->CR1 & I2C_CR1_START); - i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; // enable interrupts + /* enable interrupts from I2C hardware. They will disable in driver state + machine after the tranafer finish.*/ + i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; } void i2c_lld_master_stop(I2CDriver *i2cp){ |