Skip to content

Commit 57f4df6

Browse files
committed
STM32: I2C: reset state machine
this I2C IP is meant for automatic STOP, based on programmed number of bytes to be sent or receivede, not a user triggered STOP. So the state machiine needs to be reset in case we use this I2C mbed unitary API (start / byte_write / byte_read / stop).
1 parent 450701f commit 57f4df6

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

targets/TARGET_STM/i2c_api.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,23 @@ void i2c_hw_reset(i2c_t *obj) {
238238
#endif
239239
}
240240

241+
void i2c_sw_reset(i2c_t *obj)
242+
{
243+
struct i2c_s *obj_s = I2C_S(obj);
244+
I2C_HandleTypeDef *handle = &(obj_s->handle);
245+
/* SW reset procedure:
246+
* PE must be kept low during at least 3 APB clock cycles
247+
* in order to perform the software reset.
248+
* This is ensured by writing the following software sequence:
249+
* - Write PE=0
250+
* - Check PE=0
251+
* - Write PE=1.
252+
*/
253+
handle->Instance->CR1 &= ~I2C_CR1_PE;
254+
while(handle->Instance->CR1 & I2C_CR1_PE);
255+
handle->Instance->CR1 |= I2C_CR1_PE;
256+
}
257+
241258
void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
242259

243260
struct i2c_s *obj_s = I2C_S(obj);
@@ -597,8 +614,14 @@ int i2c_stop(i2c_t *obj) {
597614
* to know when we need to prepare next start */
598615
handle->Instance->CR2 &= ~I2C_CR2_SADD;
599616

617+
/*
618+
* V2 IP is meant for automatic STOP, not user STOP
619+
* SW reset the IP state machine before next transaction
620+
*/
621+
i2c_sw_reset(obj);
622+
600623
/* In case of mixed usage of the APIs (unitary + SYNC)
601-
* re-inti HAL state */
624+
* re-init HAL state */
602625
if (obj_s->XferOperation != I2C_FIRST_AND_LAST_FRAME) {
603626
i2c_init(obj, obj_s->sda, obj_s->scl);
604627
}

0 commit comments

Comments
 (0)