From aa409f46abe47c30a9af694b2dd33924fd78b81f Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Sat, 25 Aug 2018 12:48:29 +0000 Subject: [PATCH] Merged in david_s5/nuttx/master_kinetis_i2c_fix (pull request #711) kinetis:i2c ensure timeout on bus error The code had a dead wait on I2C_S_BUSY. Noise on the bus would cause the driver to hang. Add timeout on invalid states of I2C_S_BUSY to allow the upper layers do deal with restart or abort. Approved-by: GregoryN --- arch/arm/src/kinetis/kinetis_i2c.c | 44 +++++++++++++++++++----------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/arch/arm/src/kinetis/kinetis_i2c.c b/arch/arm/src/kinetis/kinetis_i2c.c index 5e3c51932f..6e5449ee64 100644 --- a/arch/arm/src/kinetis/kinetis_i2c.c +++ b/arch/arm/src/kinetis/kinetis_i2c.c @@ -74,7 +74,7 @@ * Pre-processor Definitions ****************************************************************************/ -#define I2C_TIMEOUT (20*1000/CONFIG_USEC_PER_TICK) /* 20 mS */ +#define I2C_TIMEOUT USEC2TICK(20*1000) /* 20 mS */ #define I2C_DEFAULT_FREQUENCY 400000 @@ -801,6 +801,7 @@ static void kinetis_i2c_setfrequency(struct kinetis_i2cdev_s *priv, static int kinetis_i2c_start(struct kinetis_i2cdev_s *priv) { struct i2c_msg_s *msg; + systime_t start; i2cinfo("START msg=%p\n", priv->msgs); msg = priv->msgs; @@ -816,9 +817,18 @@ static int kinetis_i2c_start(struct kinetis_i2cdev_s *priv) } else { - /* We are not currently the bus master, so wait for bus ready */ + /* We are not currently the bus master, wait for bus ready or timeout */ - while (kinetis_i2c_getreg(priv, KINETIS_I2C_S_OFFSET) & I2C_S_BUSY); + start = clock_systimer(); + + while (kinetis_i2c_getreg(priv, KINETIS_I2C_S_OFFSET) & I2C_S_BUSY) + { + if (clock_systimer() - start > I2C_TIMEOUT) + { + priv->state = STATE_TIMEOUT; + return -EIO; + } + } /* Become the bus master in transmit mode (send start) */ @@ -828,13 +838,18 @@ static int kinetis_i2c_start(struct kinetis_i2cdev_s *priv) if (I2C_M_READ & msg->flags) /* DEBUG: should happen always */ { - /* Wait until start condition establishes control of the bus */ + /* Wait until start condition establishes control of the bus or + * a timeout occurs + */ - while (1) + start = clock_systimer(); + + while ((kinetis_i2c_getreg(priv, KINETIS_I2C_S_OFFSET) & I2C_S_BUSY) == 0) { - if (kinetis_i2c_getreg(priv, KINETIS_I2C_S_OFFSET) & I2C_S_BUSY) + if (clock_systimer() - start > I2C_TIMEOUT) { - break; + priv->state = STATE_TIMEOUT; + return -EIO; } } } @@ -1178,7 +1193,10 @@ static int kinetis_i2c_transfer(struct i2c_master_s *dev, { /* Initiate the transfer, in case restart is required */ - kinetis_i2c_start(priv); + if (kinetis_i2c_start(priv) < 0) + { + goto timeout; + } } /* Wait for transfer complete */ @@ -1194,20 +1212,14 @@ static int kinetis_i2c_transfer(struct i2c_master_s *dev, /* Disable interrupts */ +timeout: kinetis_i2c_putreg(priv, I2C_C1_IICEN, KINETIS_I2C_C1_OFFSET); /* Release access to I2C bus */ kinetis_i2c_sem_post(priv); - if (priv->state != STATE_OK) - { - return -EIO; - } - else - { - return 0; - } + return (priv->state != STATE_OK) ? -EIO : 0; } /************************************************************************************