mirror of https://github.com/ARMmbed/mbed-os.git
I2C bugfix 'i2c_stop()' timeout
- Remove waiting for 'BTF' flag in 'i2c_stop()': When 'i2c_stop()' is called from 'i2c_read()' or 'i2c_write()' flag 'BTF' has already been cleared (indirectly) by the calling functions and therefore 'i2c_stop()' would mistakenly always run into a timeout. - Delay clock enabling until pins are configured: Enabling the I2C bus clock before configuring its pins might in rare cases lead to HW faults on the bus. - Move initialization of 'handle->Instance' to function 'i2c_reset()': As 'i2c_reset()' uses '__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BUSY)' field 'handle->Instance' must have been initialized before doing so. Therefore, this operation has been anticipated by moving it from function 'i2c_frequency()' to function 'i2c_reset()'.pull/3032/head
parent
e965c34e66
commit
857786e303
|
@ -68,7 +68,6 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
|
||||||
// Enable I2C1 clock and pinout if not done
|
// Enable I2C1 clock and pinout if not done
|
||||||
if ((obj_s->i2c == I2C_1) && !i2c1_inited) {
|
if ((obj_s->i2c == I2C_1) && !i2c1_inited) {
|
||||||
i2c1_inited = 1;
|
i2c1_inited = 1;
|
||||||
__I2C1_CLK_ENABLE();
|
|
||||||
// Configure I2C pins
|
// Configure I2C pins
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
pinmap_pinout(scl, PinMap_I2C_SCL);
|
||||||
|
@ -78,11 +77,11 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
|
||||||
obj_s->event_i2cIRQ = I2C1_EV_IRQn;
|
obj_s->event_i2cIRQ = I2C1_EV_IRQn;
|
||||||
obj_s->error_i2cIRQ = I2C1_ER_IRQn;
|
obj_s->error_i2cIRQ = I2C1_ER_IRQn;
|
||||||
#endif
|
#endif
|
||||||
|
__I2C1_CLK_ENABLE();
|
||||||
}
|
}
|
||||||
// Enable I2C2 clock and pinout if not done
|
// Enable I2C2 clock and pinout if not done
|
||||||
if ((obj_s->i2c == I2C_2) && !i2c2_inited) {
|
if ((obj_s->i2c == I2C_2) && !i2c2_inited) {
|
||||||
i2c2_inited = 1;
|
i2c2_inited = 1;
|
||||||
__I2C2_CLK_ENABLE();
|
|
||||||
// Configure I2C pins
|
// Configure I2C pins
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
pinmap_pinout(scl, PinMap_I2C_SCL);
|
||||||
|
@ -92,12 +91,12 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
|
||||||
obj_s->event_i2cIRQ = I2C2_EV_IRQn;
|
obj_s->event_i2cIRQ = I2C2_EV_IRQn;
|
||||||
obj_s->error_i2cIRQ = I2C2_ER_IRQn;
|
obj_s->error_i2cIRQ = I2C2_ER_IRQn;
|
||||||
#endif
|
#endif
|
||||||
|
__I2C2_CLK_ENABLE();
|
||||||
}
|
}
|
||||||
#if defined I2C3_BASE
|
#if defined I2C3_BASE
|
||||||
// Enable I2C3 clock and pinout if not done
|
// Enable I2C3 clock and pinout if not done
|
||||||
if ((obj_s->i2c == I2C_3) && !i2c3_inited) {
|
if ((obj_s->i2c == I2C_3) && !i2c3_inited) {
|
||||||
i2c3_inited = 1;
|
i2c3_inited = 1;
|
||||||
__I2C3_CLK_ENABLE();
|
|
||||||
// Configure I2C pins
|
// Configure I2C pins
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
pinmap_pinout(scl, PinMap_I2C_SCL);
|
||||||
|
@ -107,6 +106,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
|
||||||
obj_s->event_i2cIRQ = I2C3_EV_IRQn;
|
obj_s->event_i2cIRQ = I2C3_EV_IRQn;
|
||||||
obj_s->error_i2cIRQ = I2C3_ER_IRQn;
|
obj_s->error_i2cIRQ = I2C3_ER_IRQn;
|
||||||
#endif
|
#endif
|
||||||
|
__I2C3_CLK_ENABLE();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -114,7 +114,6 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
|
||||||
// Enable I2C3 clock and pinout if not done
|
// Enable I2C3 clock and pinout if not done
|
||||||
if ((obj_s->i2c == FMPI2C_1) && !fmpi2c1_inited) {
|
if ((obj_s->i2c == FMPI2C_1) && !fmpi2c1_inited) {
|
||||||
fmpi2c1_inited = 1;
|
fmpi2c1_inited = 1;
|
||||||
__HAL_RCC_FMPI2C1_CLK_ENABLE();
|
|
||||||
// Configure I2C pins
|
// Configure I2C pins
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
pinmap_pinout(scl, PinMap_I2C_SCL);
|
||||||
|
@ -124,6 +123,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
|
||||||
obj_s->event_i2cIRQ = FMPI2C1_EV_IRQn;
|
obj_s->event_i2cIRQ = FMPI2C1_EV_IRQn;
|
||||||
obj_s->error_i2cIRQ = FMPI2C1_ER_IRQn;
|
obj_s->error_i2cIRQ = FMPI2C1_ER_IRQn;
|
||||||
#endif
|
#endif
|
||||||
|
__HAL_RCC_FMPI2C1_CLK_ENABLE();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -151,8 +151,6 @@ void i2c_frequency(i2c_t *obj, int hz)
|
||||||
struct i2c_s *obj_s = I2C_S(obj);
|
struct i2c_s *obj_s = I2C_S(obj);
|
||||||
I2C_HandleTypeDef *handle = &(obj_s->handle);
|
I2C_HandleTypeDef *handle = &(obj_s->handle);
|
||||||
|
|
||||||
handle->Instance = (I2C_TypeDef *)(obj_s->i2c);
|
|
||||||
|
|
||||||
MBED_ASSERT((hz > 0) && (hz <= 400000));
|
MBED_ASSERT((hz > 0) && (hz <= 400000));
|
||||||
|
|
||||||
// wait before init
|
// wait before init
|
||||||
|
@ -212,20 +210,8 @@ inline int i2c_start(i2c_t *obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int i2c_stop(i2c_t *obj) {
|
inline int i2c_stop(i2c_t *obj) {
|
||||||
|
|
||||||
int timeout;
|
|
||||||
struct i2c_s *obj_s = I2C_S(obj);
|
struct i2c_s *obj_s = I2C_S(obj);
|
||||||
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
|
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
|
||||||
I2C_HandleTypeDef *handle = &(obj_s->handle);
|
|
||||||
|
|
||||||
//Wait Byte transfer finished before sending stop
|
|
||||||
timeout = FLAG_TIMEOUT;
|
|
||||||
while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BTF) == RESET) {
|
|
||||||
timeout--;
|
|
||||||
if (timeout == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the STOP condition
|
// Generate the STOP condition
|
||||||
i2c->CR1 |= I2C_CR1_STOP;
|
i2c->CR1 |= I2C_CR1_STOP;
|
||||||
|
@ -361,7 +347,7 @@ int i2c_byte_write(i2c_t *obj, int data) {
|
||||||
|
|
||||||
handle->Instance->DR = (uint8_t)data;
|
handle->Instance->DR = (uint8_t)data;
|
||||||
|
|
||||||
// Wait until the byte (might be the adress) is transmitted
|
// Wait until the byte (might be the address) is transmitted
|
||||||
timeout = FLAG_TIMEOUT;
|
timeout = FLAG_TIMEOUT;
|
||||||
while ((__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXE) == RESET) &&
|
while ((__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXE) == RESET) &&
|
||||||
(__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BTF) == RESET) &&
|
(__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BTF) == RESET) &&
|
||||||
|
@ -385,6 +371,8 @@ void i2c_reset(i2c_t *obj) {
|
||||||
struct i2c_s *obj_s = I2C_S(obj);
|
struct i2c_s *obj_s = I2C_S(obj);
|
||||||
I2C_HandleTypeDef *handle = &(obj_s->handle);
|
I2C_HandleTypeDef *handle = &(obj_s->handle);
|
||||||
|
|
||||||
|
handle->Instance = (I2C_TypeDef *)(obj_s->i2c);
|
||||||
|
|
||||||
// wait before reset
|
// wait before reset
|
||||||
timeout = LONG_TIMEOUT;
|
timeout = LONG_TIMEOUT;
|
||||||
while ((__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BUSY)) && (timeout-- != 0));
|
while ((__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BUSY)) && (timeout-- != 0));
|
||||||
|
@ -570,7 +558,6 @@ int i2c_slave_write(i2c_t *obj, const char *data, int length) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Clear AF flag */
|
/* Clear AF flag */
|
||||||
__HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_AF);
|
__HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_AF);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue