Skip to content

Commit c46e7e3

Browse files
ABOSTMfpistm
authored andcommitted
[I2C] Fix error management in Read/Write
When NACK is received by master, instead of immediate re-transmission by twi driver, error is reported. Up to application to manage re-transmission. This fix regression found on STM32F2 and STM32F4 when using I2C_OTHER_FRAME. See PR stm32duino#663
1 parent f56b7a6 commit c46e7e3

File tree

1 file changed

+37
-40
lines changed

1 file changed

+37
-40
lines changed

cores/arduino/stm32/twi.c

+37-40
Original file line numberDiff line numberDiff line change
@@ -731,9 +731,10 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
731731
uint8_t *data, uint16_t size)
732732

733733
{
734-
i2c_status_e ret = I2C_ERROR;
734+
i2c_status_e ret = I2C_OK;
735735
uint32_t tickstart = HAL_GetTick();
736736
uint32_t delta = 0;
737+
uint32_t err = 0;
737738

738739
/* When size is 0, this is usually an I2C scan / ping to check if device is there and ready */
739740
if (size == 0) {
@@ -744,30 +745,28 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
744745
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
745746
#endif
746747

747-
do {
748748
#if defined(I2C_OTHER_FRAME)
749-
if (HAL_I2C_Master_Seq_Transmit_IT(&(obj->handle), dev_address, data, size, XferOptions) == HAL_OK) {
749+
if (HAL_I2C_Master_Seq_Transmit_IT(&(obj->handle), dev_address, data, size, XferOptions) == HAL_OK) {
750750
#else
751-
if (HAL_I2C_Master_Transmit_IT(&(obj->handle), dev_address, data, size) == HAL_OK) {
751+
if (HAL_I2C_Master_Transmit_IT(&(obj->handle), dev_address, data, size) == HAL_OK) {
752752
#endif
753-
ret = I2C_OK;
754-
// wait for transfer completion
755-
while ((HAL_I2C_GetState(&(obj->handle)) != HAL_I2C_STATE_READY)
756-
&& (ret == I2C_OK)) {
757-
delta = (HAL_GetTick() - tickstart);
758-
uint32_t err = HAL_I2C_GetError(&(obj->handle));
759-
if ((delta > I2C_TIMEOUT_TICK)
760-
|| ((err & HAL_I2C_ERROR_TIMEOUT) == HAL_I2C_ERROR_TIMEOUT)) {
761-
ret = I2C_TIMEOUT;
762-
} else if (err != HAL_I2C_ERROR_NONE) {
763-
ret = I2C_ERROR;
764-
}
753+
// wait for transfer completion
754+
while ((HAL_I2C_GetState(&(obj->handle)) != HAL_I2C_STATE_READY) && (delta < I2C_TIMEOUT_TICK)) {
755+
delta = (HAL_GetTick() - tickstart);
756+
if (HAL_I2C_GetError(&(obj->handle)) != HAL_I2C_ERROR_NONE) {
757+
break;
765758
}
766759
}
767-
/* When Acknowledge failure occurs (Slave don't acknowledge it's address)
768-
Master restarts communication */
769-
} while (((HAL_I2C_GetError(&(obj->handle)) & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF)
770-
&& (delta < I2C_TIMEOUT_TICK));
760+
761+
err = HAL_I2C_GetError(&(obj->handle));
762+
if ((delta > I2C_TIMEOUT_TICK)
763+
|| ((err & HAL_I2C_ERROR_TIMEOUT) == HAL_I2C_ERROR_TIMEOUT)) {
764+
ret = I2C_TIMEOUT;
765+
} else if (err != HAL_I2C_ERROR_NONE) {
766+
ret = I2C_ERROR;
767+
}
768+
}
769+
771770
return ret;
772771
}
773772

@@ -807,38 +806,36 @@ i2c_status_e i2c_slave_write_IT(i2c_t *obj, uint8_t *data, uint16_t size)
807806
*/
808807
i2c_status_e i2c_master_read(i2c_t *obj, uint8_t dev_address, uint8_t *data, uint16_t size)
809808
{
810-
i2c_status_e ret = I2C_ERROR;
809+
i2c_status_e ret = I2C_OK;
811810
uint32_t tickstart = HAL_GetTick();
812811
uint32_t delta = 0;
812+
uint32_t err = 0;
813813

814814
#if defined(I2C_OTHER_FRAME)
815815
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
816816
#endif
817817

818-
do {
819818
#if defined(I2C_OTHER_FRAME)
820-
if (HAL_I2C_Master_Seq_Receive_IT(&(obj->handle), dev_address, data, size, XferOptions) == HAL_OK) {
819+
if (HAL_I2C_Master_Seq_Receive_IT(&(obj->handle), dev_address, data, size, XferOptions) == HAL_OK) {
821820
#else
822-
if (HAL_I2C_Master_Receive_IT(&(obj->handle), dev_address, data, size) == HAL_OK) {
821+
if (HAL_I2C_Master_Receive_IT(&(obj->handle), dev_address, data, size) == HAL_OK) {
823822
#endif
824-
ret = I2C_OK;
825-
// wait for transfer completion
826-
while ((HAL_I2C_GetState(&(obj->handle)) != HAL_I2C_STATE_READY)
827-
&& (ret == I2C_OK)) {
828-
delta = (HAL_GetTick() - tickstart);
829-
uint32_t err = HAL_I2C_GetError(&(obj->handle));
830-
if ((delta > I2C_TIMEOUT_TICK)
831-
|| ((err & HAL_I2C_ERROR_TIMEOUT) == HAL_I2C_ERROR_TIMEOUT)) {
832-
ret = I2C_TIMEOUT;
833-
} else if (err != HAL_I2C_ERROR_NONE) {
834-
ret = I2C_ERROR;
835-
}
823+
// wait for transfer completion
824+
while ((HAL_I2C_GetState(&(obj->handle)) != HAL_I2C_STATE_READY) && (delta < I2C_TIMEOUT_TICK)) {
825+
delta = (HAL_GetTick() - tickstart);
826+
if (HAL_I2C_GetError(&(obj->handle)) != HAL_I2C_ERROR_NONE) {
827+
break;
836828
}
837829
}
838-
/* When Acknowledge failure occurs (Slave don't acknowledge it's address)
839-
Master restarts communication */
840-
} while (((HAL_I2C_GetError(&(obj->handle)) & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF)
841-
&& (delta < I2C_TIMEOUT_TICK));
830+
831+
err = HAL_I2C_GetError(&(obj->handle));
832+
if ((delta > I2C_TIMEOUT_TICK)
833+
|| ((err & HAL_I2C_ERROR_TIMEOUT) == HAL_I2C_ERROR_TIMEOUT)) {
834+
ret = I2C_TIMEOUT;
835+
} else if (err != HAL_I2C_ERROR_NONE) {
836+
ret = I2C_ERROR;
837+
}
838+
}
842839

843840
return ret;
844841
}

0 commit comments

Comments
 (0)