From 38b986290230214382b244c77152f894a4d48c66 Mon Sep 17 00:00:00 2001 From: Augusto Fraga Giachero Date: Thu, 25 Jul 2019 08:31:06 -0600 Subject: [PATCH] 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. --- arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c | 31 ++++++++++++++++++------ configs/imxrt1060-evk/README.txt | 11 +++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c b/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c index be28ac617a..74d60e8893 100644 --- a/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c +++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c @@ -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) diff --git a/configs/imxrt1060-evk/README.txt b/configs/imxrt1060-evk/README.txt index d9cd222bcc..956d865587 100644 --- a/configs/imxrt1060-evk/README.txt +++ b/configs/imxrt1060-evk/README.txt @@ -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 ==============