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:
parent
e581647f48
commit
f0b74380a5
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user