arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c: Abort I2C transfers if a timeout has occurred. If a timeout has occurred in the middle of a I2C transfer, the next I2C interrupt should abort any transfers and send a stop condition to the corresponding I2C bus. Failed to do so will result in memory corruption / undefined behavior as priv->msgs points to a region of memory it doesn't owns anymore after lpc17_40_i2c_start returns.
This commit is contained in:
parent
d99595f1a5
commit
38b9862902
@ -215,6 +215,10 @@ static int lpc17_40_i2c_start(struct lpc17_40_i2cdev_s *priv)
|
||||
priv->base + LPC17_40_I2C_CONCLR_OFFSET);
|
||||
putreg32(I2C_CONSET_STA, priv->base + LPC17_40_I2C_CONSET_OFFSET);
|
||||
|
||||
/* Initializes the I2C state machine to a known value */
|
||||
|
||||
priv->state = 0x00;
|
||||
|
||||
(void)wd_start(priv->timeout, I2C_TIMEOUT, lpc17_40_i2c_timeout, 1,
|
||||
(uint32_t)priv);
|
||||
nxsem_wait(&priv->wait);
|
||||
@ -275,7 +279,7 @@ static int lpc17_40_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
struct lpc17_40_i2cdev_s *priv = (struct lpc17_40_i2cdev_s *)dev;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(dev != NULL && msgs != NULL && count > 0);
|
||||
DEBUGASSERT(dev != NULL && msgs != NULL && count > 0);
|
||||
|
||||
/* Get exclusive access to the I2C bus */
|
||||
|
||||
@ -348,11 +352,20 @@ static int lpc17_40_i2c_interrupt(int irq, FAR void *context, void *arg)
|
||||
state = getreg32(priv->base + LPC17_40_I2C_STAT_OFFSET);
|
||||
msg = priv->msgs;
|
||||
|
||||
priv->state = state;
|
||||
state &= 0xf8; /* state mask, only 0xX8 is possible */
|
||||
/* Checks if a timeout occurred */
|
||||
|
||||
if (priv->state == 0xff)
|
||||
{
|
||||
state = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->state = state;
|
||||
state &= 0xf8; /* state mask, only 0xX8 is possible */
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
|
||||
case 0x08: /* A START condition has been transmitted. */
|
||||
case 0x10: /* A Repeated START condition has been transmitted. */
|
||||
/* Set address */
|
||||
@ -402,7 +415,8 @@ static int lpc17_40_i2c_interrupt(int irq, FAR void *context, void *arg)
|
||||
|
||||
case 0x50: /* Data byte has been received; ACK has been returned. */
|
||||
priv->rdcnt++;
|
||||
msg->buffer[priv->rdcnt - 1] = getreg32(priv->base + LPC17_40_I2C_BUFR_OFFSET);
|
||||
msg->buffer[priv->rdcnt - 1] =
|
||||
getreg32(priv->base + LPC17_40_I2C_BUFR_OFFSET);
|
||||
|
||||
if (priv->rdcnt >= (msg->length - 1))
|
||||
{
|
||||
@ -411,7 +425,8 @@ static int lpc17_40_i2c_interrupt(int irq, FAR void *context, void *arg)
|
||||
break;
|
||||
|
||||
case 0x58: /* Data byte has been received; NACK has been returned. */
|
||||
msg->buffer[priv->rdcnt] = getreg32(priv->base + LPC17_40_I2C_BUFR_OFFSET);
|
||||
msg->buffer[priv->rdcnt] =
|
||||
getreg32(priv->base + LPC17_40_I2C_BUFR_OFFSET);
|
||||
lpc17_40_stopnext(priv);
|
||||
break;
|
||||
|
||||
@ -425,7 +440,7 @@ static int lpc17_40_i2c_interrupt(int irq, FAR void *context, void *arg)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: lpc17_40_i2c_reset
|
||||
*
|
||||
* Description:
|
||||
@ -437,7 +452,7 @@ static int lpc17_40_i2c_interrupt(int irq, FAR void *context, void *arg)
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
static int lpc17_40_i2c_reset(FAR struct i2c_master_s * dev)
|
||||
|
@ -43,6 +43,7 @@ Contents
|
||||
|
||||
o Serial Console
|
||||
o LEDs and buttons
|
||||
o J-Link External Debug Probe
|
||||
o Configurations
|
||||
- Configuration sub-directories
|
||||
|
||||
@ -115,6 +116,16 @@ LEDs and buttons
|
||||
Only the user button is available to the software. It is sensed on the
|
||||
WAKEUP pin which will be pulled low when the button is pressed.
|
||||
|
||||
|
||||
J-Link External Debug Probe
|
||||
===========================
|
||||
|
||||
Install the J-Link Debug Host Tools and make sure they are in your search path.
|
||||
|
||||
Attach a J-Link 20-pin connector to J21. Check that jumpers J47 and J48 are
|
||||
off (they are on by default when boards ship from the factory) to ensure SWD
|
||||
signals are disconnected from the OpenSDA microcontroller.
|
||||
|
||||
Configurations
|
||||
==============
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user