Skip to content

Commit

Permalink
ave elapsed time before handling I2C in stm32_i2c_sem_waitstop()
Browse files Browse the repository at this point in the history
This patch follows the same logic as in previous fix to
stm32_i2c_sem_waitdone().

It is possible that a context switch occurs after I2C registers are read
but before elapsed time is saved in stm32_i2c_sem_waitstop(). It is then
possible that the registers were read only once with "elapsed time"
equal 0. When scheduler resumes this thread it is quite possible that
now "elapsed time" will be well above timeout threshold. In that case
the function returns and reports a timeout, even though the registers
were not read "recently".

Fix this by inverting the order of operations in the loop - save elapsed
time before reading registers. This way a context switch anywhere in the
loop will not cause an erroneous "timeout" error.
  • Loading branch information
FreddieChopin authored and gregory-nutt committed Mar 10, 2017
1 parent d391f9d commit 3cd66af
Showing 1 changed file with 4 additions and 4 deletions.
8 changes: 4 additions & 4 deletions arch/arm/src/stm32/stm32_i2c_alt.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,10 @@ static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv)
start = clock_systimer();
do
{
/* Calculate the elapsed time */

elapsed = clock_systimer() - start;

/* Check for STOP condition */

cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
Expand All @@ -752,10 +756,6 @@ static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv)
{
return;
}

/* Calculate the elapsed time */

elapsed = clock_systimer() - start;
}

/* Loop until the stop is complete or a timeout occurs. */
Expand Down

0 comments on commit 3cd66af

Please sign in to comment.