arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c: Calculate the appropriate timeout for I2C transfers. Depending on the bus frequency and transfer size, I2C transactions can take quite a bit, so a fixed timeout is not a good solution. Calculating the timeout at run time poses some overhead but still better than aborting long transactions.

This commit is contained in:
Augusto Fraga Giachero 2019-07-25 13:07:28 -06:00 committed by Gregory Nutt
parent e581647f48
commit f0b74380a5

View File

@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c
*
* Copyright (C) 2012, 2014-2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2012, 2014-2016, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
@ -97,7 +97,6 @@
# define CONFIG_LPC17_40_I2C2_FREQUENCY 100000
#endif
#define I2C_TIMEOUT (20 * 1000/CONFIG_USEC_PER_TICK) /* 20 mS */
#define LPC17_40_I2C1_FREQUENCY 400000
/****************************************************************************
@ -211,15 +210,35 @@ static void lpc17_40_i2c_setfrequency(struct lpc17_40_i2cdev_s *priv,
static int lpc17_40_i2c_start(struct lpc17_40_i2cdev_s *priv)
{
uint32_t total_len = 0;
uint32_t freq = 1000000;
uint32_t timeout;
int i;
putreg32(I2C_CONCLR_STAC | I2C_CONCLR_SIC,
priv->base + LPC17_40_I2C_CONCLR_OFFSET);
putreg32(I2C_CONSET_STA, priv->base + LPC17_40_I2C_CONSET_OFFSET);
/* Get the total transaction length and the minimum frequency */
for(i = 0; i < priv->nmsg; i++)
{
total_len += priv->msgs[i].length;
if (priv->msgs[i].frequency < freq)
{
freq = priv->msgs[i].frequency;
}
}
/* Calculate the approximate timeout */
timeout = ((total_len * (8000000 / CONFIG_USEC_PER_TICK)) / freq) + 1;
/* Initializes the I2C state machine to a known value */
priv->state = 0x00;
(void)wd_start(priv->timeout, I2C_TIMEOUT, lpc17_40_i2c_timeout, 1,
(void)wd_start(priv->timeout, timeout, lpc17_40_i2c_timeout, 1,
(uint32_t)priv);
nxsem_wait(&priv->wait);