From 5ca9adbe61350453f3bc175cb436ec6556a67e0d Mon Sep 17 00:00:00 2001 From: Bernd Walter Date: Sun, 5 Mar 2023 15:15:43 +0100 Subject: [PATCH] Copy I2C_M_NOSTART support from sam7v/sam_twihs.c driver --- arch/arm/src/sam34/sam_twi.c | 82 ++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 14 deletions(-) diff --git a/arch/arm/src/sam34/sam_twi.c b/arch/arm/src/sam34/sam_twi.c index 8f110ad82e..3cd93c2f41 100644 --- a/arch/arm/src/sam34/sam_twi.c +++ b/arch/arm/src/sam34/sam_twi.c @@ -475,21 +475,53 @@ static int twi_interrupt(int irq, void *context, void *arg) if (priv->xfrd >= msg->length) { - /* The transfer is complete. Disable the RXRDY interrupt and - * enable the TXCOMP interrupt + struct i2c_msg_s *next = (msg + 1); + + /* Is there another message to after this one? Does it require a + * restart? */ - twi_putrel(priv, SAM_TWI_IDR_OFFSET, TWI_INT_RXRDY); - twi_putrel(priv, SAM_TWI_IER_OFFSET, TWI_INT_TXCOMP); + if (priv->msgc <= 1 || (next->flags & I2C_M_NOSTART) == 0) + { + /* The transfer is complete. Disable the RXRDY interrupt and + * enable the TXCOMP interrupt + */ + + twi_putrel(priv, SAM_TWI_IDR_OFFSET, TWI_INT_RXRDY); + twi_putrel(priv, SAM_TWI_IER_OFFSET, TWI_INT_TXCOMP); + } + else + { + /* No.. just switch to the next message and continue + * receiving. On the next RXRDY, we will continue with the + * first byte of the next message. + */ + + DEBUGASSERT((next->flags & I2C_M_READ) != 0); + priv->msg = next; + priv->msgc--; + priv->xfrd = 0; + } } /* Not yet complete, but will the next be the last byte? */ else if (priv->xfrd == (msg->length - 1)) { - /* Yes, set the stop signal */ + struct i2c_msg_s *next = (msg + 1); - twi_putrel(priv, SAM_TWI_CR_OFFSET, TWI_CR_STOP); + /* Is there another message to after this one? Does it require a + * restart? + */ + + if (priv->msgc <= 1 || (next->flags & I2C_M_NOSTART) == 0) + { + /* This is the last message OR a restart is required before + * the next message. Send the stop signal. + */ + + twi_putrel(priv, SAM_TWI_CR_OFFSET, TWI_CR_STOP); + } } } @@ -501,18 +533,40 @@ static int twi_interrupt(int irq, void *context, void *arg) if (priv->xfrd >= msg->length) { - /* The transfer is complete. Disable the TXRDY interrupt and - * enable the TXCOMP interrupt + struct i2c_msg_s *next = (msg + 1); + + /* Is there another message to after this one? Does it require a + * restart? */ - twi_putrel(priv, SAM_TWI_IDR_OFFSET, TWI_INT_TXRDY); - twi_putrel(priv, SAM_TWI_IER_OFFSET, TWI_INT_TXCOMP); + if (priv->msgc <= 1 || (next->flags & I2C_M_NOSTART) == 0) + { + /* The transfer is complete. Disable the TXRDY interrupt and + * enable the TXCOMP interrupt + */ - /* Send the STOP condition */ + twi_putrel(priv, SAM_TWI_IDR_OFFSET, TWI_INT_TXRDY); + twi_putrel(priv, SAM_TWI_IER_OFFSET, TWI_INT_TXCOMP); - regval = twi_getrel(priv, SAM_TWI_CR_OFFSET); - regval |= TWI_CR_STOP; - twi_putrel(priv, SAM_TWI_CR_OFFSET, regval); + /* Send the STOP condition */ + + regval = twi_getrel(priv, SAM_TWI_CR_OFFSET); + regval |= TWI_CR_STOP; + twi_putrel(priv, SAM_TWI_CR_OFFSET, regval); + } + else + { + /* No.. just switch to the next message and continue + * sending. + */ + + DEBUGASSERT((next->flags & I2C_M_READ) == 0); + priv->msg = next; + priv->msgc--; + + twi_putrel(priv, SAM_TWI_THR_OFFSET, next->buffer[0]); + priv->xfrd = 1; + } } /* No, there are more bytes remaining to be sent */