SAMV7 TWIHS: Fix logic that performs multi-message tranfers with and without repeated starts. This change is the final piece that was required to get the maXTouch Xplained Pro workding.

This commit is contained in:
Gregory Nutt 2015-05-12 17:48:01 -06:00
parent 7942c2f6d5
commit c4db8e440d

View File

@ -597,21 +597,53 @@ static int twi_interrupt(struct twi_dev_s *priv)
if (priv->xfrd >= msg->length) if (priv->xfrd >= msg->length)
{ {
/* The transfer is complete. Disable the RXRDY interrupt and struct i2c_msg_s *next = msg++;
* enable the TXCOMP interrupt
/* Is there another message to after this one? Does it require a
* restart?
*/ */
twi_putrel(priv, SAM_TWIHS_IDR_OFFSET, TWIHS_INT_RXRDY); if (priv->msgc <= 1 || (next->flags & I2C_M_NORESTART) == 0)
twi_putrel(priv, SAM_TWIHS_IER_OFFSET, TWIHS_INT_TXCOMP); {
/* The transfer is complete. Disable the RXRDY interrupt and
* enable the TXCOMP interrupt
*/
twi_putrel(priv, SAM_TWIHS_IDR_OFFSET, TWIHS_INT_RXRDY);
twi_putrel(priv, SAM_TWIHS_IER_OFFSET, TWIHS_INT_TXCOMP);
}
else
{
/* No.. just switch to the next message and continue receiving.
* On the next RXRDY, we will continue with the first byt 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? */ /* Not yet complete, but will the next be the last byte? */
else if (priv->xfrd == (msg->length - 1)) else if (priv->xfrd == (msg->length - 1))
{ {
/* Yes, set the stop signal */ struct i2c_msg_s *next = msg++;
twi_putrel(priv, SAM_TWIHS_CR_OFFSET, TWIHS_CR_STOP); /* Is there another message to after this one? Does it require a
* restart?
*/
if (priv->msgc <= 1 || (next->flags & I2C_M_NORESTART) == 0)
{
/* This is the last message OR a restart is required before
* the next mesage. Send the stop signal.
*/
twi_putrel(priv, SAM_TWIHS_CR_OFFSET, TWIHS_CR_STOP);
}
} }
} }
@ -623,18 +655,38 @@ static int twi_interrupt(struct twi_dev_s *priv)
if (priv->xfrd >= msg->length) if (priv->xfrd >= msg->length)
{ {
/* The transfer is complete. Disable the TXRDY interrupt and struct i2c_msg_s *next = msg++;
* enable the TXCOMP interrupt
/* Is there another message to after this one? Does it require a
* restart?
*/ */
twi_putrel(priv, SAM_TWIHS_IDR_OFFSET, TWIHS_INT_TXRDY); if (priv->msgc <= 1 || (next->flags & I2C_M_NORESTART) == 0)
twi_putrel(priv, SAM_TWIHS_IER_OFFSET, TWIHS_INT_TXCOMP); {
/* The transfer is complete. Disable the TXRDY interrupt and
* enable the TXCOMP interrupt
*/
/* Send the STOP condition */ twi_putrel(priv, SAM_TWIHS_IDR_OFFSET, TWIHS_INT_TXRDY);
twi_putrel(priv, SAM_TWIHS_IER_OFFSET, TWIHS_INT_TXCOMP);
regval = twi_getrel(priv, SAM_TWIHS_CR_OFFSET); /* Send the STOP condition */
regval |= TWIHS_CR_STOP;
twi_putrel(priv, SAM_TWIHS_CR_OFFSET, regval); regval = twi_getrel(priv, SAM_TWIHS_CR_OFFSET);
regval |= TWIHS_CR_STOP;
twi_putrel(priv, SAM_TWIHS_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_TWIHS_THR_OFFSET, next->buffer[0]);
priv->xfrd = 1;
}
} }
/* No, there are more bytes remaining to be sent */ /* No, there are more bytes remaining to be sent */
@ -646,7 +698,9 @@ static int twi_interrupt(struct twi_dev_s *priv)
} }
} }
/* Transfer complete */ /* Transfer complete, Occurs on message only if the STOP bit was set on
* the previously sent byte.
*/
else if ((pending & TWIHS_INT_TXCOMP) != 0) else if ((pending & TWIHS_INT_TXCOMP) != 0)
{ {