You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ag...@apache.org on 2020/03/02 21:14:15 UTC

[incubator-nuttx] branch pr419 updated: arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c: Cancel timeout on i2c stop

This is an automated email from the ASF dual-hosted git repository.

aguettouche pushed a commit to branch pr419
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/pr419 by this push:
     new 0be87af  arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c: Cancel timeout on i2c stop
0be87af is described below

commit 0be87af99d4b1bee2110e1378a2fb9767d6bf2c2
Author: Augusto Fraga Giachero <au...@gmail.com>
AuthorDate: Mon Mar 2 16:34:54 2020 -0300

    arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c: Cancel timeout on i2c stop
    
    Not canceling the I2C timeout watch dog immediately after finishing
    all I2C transactions in interrupt context can lead to a race condition
    due to nxsem_wait(&priv->wait) in lpc17_40_i2c_start() not resuming
    execution fast enough (this can be easily triggered if another task /
    thread is using a lot of cpu time).
    
    Falling to cancel the watchdog up to time will cause the priv->wait
    semaphore to be incremented twice (first by lpc17_40_i2c_stop() then
    by lpc17_40_i2c_timeout()), so all I2C transactions after that will
    return immediately and priv->msgs will hold pointers to memory it
    doesn't own anymore.
    
    Canceling the priv->timeout watch dog in lpc17_40_i2c_stop() prevents
    this as it is executed from the I2C interrupt handler.
    
    arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c: Fix timeout calculation
    
    For each byte received / transmitted, an acknowledge bit is also
    transmitted / received, requiring effectively 9 bits for each byte.
---
 arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c b/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c
index f6e43d3..2052e7b 100644
--- a/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c
+++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c
@@ -232,7 +232,7 @@ static int lpc17_40_i2c_start(struct lpc17_40_i2cdev_s *priv)
 
   /* Calculate the approximate timeout */
 
-  timeout = ((total_len * (8000000 / CONFIG_USEC_PER_TICK)) / freq) + 1;
+  timeout = ((total_len * (9000000 / CONFIG_USEC_PER_TICK)) / freq) + 1;
 
   /* Initializes the I2C state machine to a known value */
 
@@ -242,8 +242,6 @@ static int lpc17_40_i2c_start(struct lpc17_40_i2cdev_s *priv)
            (uint32_t)priv);
   nxsem_wait(&priv->wait);
 
-  wd_cancel(priv->timeout);
-
   return priv->nmsg;
 }
 
@@ -263,6 +261,7 @@ static void lpc17_40_i2c_stop(struct lpc17_40_i2cdev_s *priv)
                priv->base + LPC17_40_I2C_CONSET_OFFSET);
     }
 
+  wd_cancel(priv->timeout);
   nxsem_post(&priv->wait);
 }