From 5a6d95dd9f051be548a8d2378aaef75f0a1ba5e1 Mon Sep 17 00:00:00 2001 From: Freddie Chopin Date: Thu, 9 Mar 2017 07:29:12 -0600 Subject: [PATCH] ave elapsed time before handling I2C in stm32_i2c_sem_waitdone() It is possible that a context switch occurs after stm32_i2c_isr() call but before elapsed time is saved in stm32_i2c_sem_waitdone(). It is then possible that the handling code was executed 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 handling code was not executed "recently". Fix this by inverting the order of operations in the loop - save elapsed time before handling I2C. This way a context switch anywhere in the loop will not cause an erroneous "timeout" error. --- arch/arm/src/stm32/stm32_i2c_alt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/src/stm32/stm32_i2c_alt.c b/arch/arm/src/stm32/stm32_i2c_alt.c index f9a2905f0e1..6d4171163ca 100644 --- a/arch/arm/src/stm32/stm32_i2c_alt.c +++ b/arch/arm/src/stm32/stm32_i2c_alt.c @@ -678,15 +678,15 @@ static int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv) do { + /* Calculate the elapsed time */ + + elapsed = clock_systimer() - start; + /* Poll by simply calling the timer interrupt handler until it * reports that it is done. */ stm32_i2c_isr(priv); - - /* Calculate the elapsed time */ - - elapsed = clock_systimer() - start; } /* Loop until the transfer is complete. */