Skip to content

Commit 5408b14

Browse files
fpistmcparata
authored andcommitted
fix(wire): ensure i2c bus is ready
Previously, i2c_master_write and i2c_master_read returned I2C_OK if first HAL call returned HAL_BUSY which was not correct. Now make sure the i2c is ready, which guarantees a good initialization of the read or write sequence. Fixes stm32duino#1774 Signed-off-by: Frederic Pillon <[email protected]>
1 parent 243940b commit 5408b14

File tree

1 file changed

+36
-6
lines changed
  • libraries/Wire/src/utility

1 file changed

+36
-6
lines changed

libraries/Wire/src/utility/twi.c

+36-6
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,7 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
848848
uint32_t tickstart = HAL_GetTick();
849849
uint32_t delta = 0;
850850
uint32_t err = 0;
851+
HAL_StatusTypeDef status = HAL_OK;
851852

852853
/* When size is 0, this is usually an I2C scan / ping to check if device is there and ready */
853854
if (size == 0) {
@@ -856,12 +857,26 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
856857
#if defined(I2C_OTHER_FRAME)
857858
uint32_t XferOptions = obj->handle.XferOptions; // save XferOptions value, because handle can be modified by HAL, which cause issue in case of NACK from slave
858859
#endif
859-
860+
do {
860861
#if defined(I2C_OTHER_FRAME)
861-
if (HAL_I2C_Master_Seq_Transmit_IT(&(obj->handle), dev_address, data, size, XferOptions) == HAL_OK) {
862+
status = HAL_I2C_Master_Seq_Transmit_IT(&(obj->handle), dev_address, data, size, XferOptions);
862863
#else
863-
if (HAL_I2C_Master_Transmit_IT(&(obj->handle), dev_address, data, size) == HAL_OK) {
864+
status = HAL_I2C_Master_Transmit_IT(&(obj->handle), dev_address, data, size);
864865
#endif
866+
// Ensure i2c ready
867+
if (status == HAL_BUSY) {
868+
delta = (HAL_GetTick() - tickstart);
869+
if (delta > I2C_TIMEOUT_TICK) {
870+
ret = I2C_BUSY;
871+
break;
872+
}
873+
} else {
874+
ret = (status == HAL_OK) ? I2C_OK : I2C_ERROR;
875+
}
876+
} while (status == HAL_BUSY);
877+
878+
if (ret == I2C_OK) {
879+
tickstart = HAL_GetTick();
865880
// wait for transfer completion
866881
while ((HAL_I2C_GetState(&(obj->handle)) != HAL_I2C_STATE_READY) && (delta < I2C_TIMEOUT_TICK)) {
867882
delta = (HAL_GetTick() - tickstart);
@@ -926,16 +941,31 @@ i2c_status_e i2c_master_read(i2c_t *obj, uint8_t dev_address, uint8_t *data, uin
926941
uint32_t tickstart = HAL_GetTick();
927942
uint32_t delta = 0;
928943
uint32_t err = 0;
944+
HAL_StatusTypeDef status = HAL_OK;
929945

930946
#if defined(I2C_OTHER_FRAME)
931947
uint32_t XferOptions = obj->handle.XferOptions; // save XferOptions value, because handle can be modified by HAL, which cause issue in case of NACK from slave
932948
#endif
933-
949+
do {
934950
#if defined(I2C_OTHER_FRAME)
935-
if (HAL_I2C_Master_Seq_Receive_IT(&(obj->handle), dev_address, data, size, XferOptions) == HAL_OK) {
951+
status = HAL_I2C_Master_Seq_Receive_IT(&(obj->handle), dev_address, data, size, XferOptions);
936952
#else
937-
if (HAL_I2C_Master_Receive_IT(&(obj->handle), dev_address, data, size) == HAL_OK) {
953+
status = HAL_I2C_Master_Receive_IT(&(obj->handle), dev_address, data, size);
938954
#endif
955+
// Ensure i2c ready
956+
if (status == HAL_BUSY) {
957+
delta = (HAL_GetTick() - tickstart);
958+
if (delta > I2C_TIMEOUT_TICK) {
959+
ret = I2C_BUSY;
960+
break;
961+
}
962+
} else {
963+
ret = (status == HAL_OK) ? I2C_OK : I2C_ERROR;
964+
}
965+
} while (status == HAL_BUSY);
966+
967+
if (ret == I2C_OK) {
968+
tickstart = HAL_GetTick();
939969
// wait for transfer completion
940970
while ((HAL_I2C_GetState(&(obj->handle)) != HAL_I2C_STATE_READY) && (delta < I2C_TIMEOUT_TICK)) {
941971
delta = (HAL_GetTick() - tickstart);

0 commit comments

Comments
 (0)