diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-12-12 12:13:31 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-12-12 12:13:31 -0600 |
commit | bce5d15aa7cbc8de58e03f615a7d5926dee95937 (patch) | |
tree | 83cafe10564b87656ac04504bd0493e4d20cf2a9 /nuttx/arch/arm/src/tiva | |
parent | 2066928f1b7e0393d52f7f7b675d87176c9f726f (diff) | |
download | nuttx-bce5d15aa7cbc8de58e03f615a7d5926dee95937.tar.gz nuttx-bce5d15aa7cbc8de58e03f615a7d5926dee95937.tar.bz2 nuttx-bce5d15aa7cbc8de58e03f615a7d5926dee95937.zip |
Tiva I2C: Don't try to ACK and STOP on the same byte. Improve logic that suppresses STOP on a repeated start
Diffstat (limited to 'nuttx/arch/arm/src/tiva')
-rw-r--r-- | nuttx/arch/arm/src/tiva/tiva_i2c.c | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/nuttx/arch/arm/src/tiva/tiva_i2c.c b/nuttx/arch/arm/src/tiva/tiva_i2c.c index 4e3838b25..b75fdc3a8 100644 --- a/nuttx/arch/arm/src/tiva/tiva_i2c.c +++ b/nuttx/arch/arm/src/tiva/tiva_i2c.c @@ -1044,27 +1044,65 @@ static void tiva_i2c_startxfr(struct tiva_i2c_priv_s *priv) static void tiva_i2c_nextxfr(struct tiva_i2c_priv_s *priv, uint32_t cmd) { - /* Set up the basic command. The STOP bit should be set on the last transfer - * UNLESS this there is a repeated start. + /* Set up the basic command. The STOP bit should be set on the last byte transfer. + * + * - CASE 1: If this is the last message in the sequence, then the stop bit should + * always be set. + * - CASE 2.1.1: The next message may be another read or write of the SAME + * direction (read or write) and to the SAME address WITHOUT repeated start, in + * which case this is really just a continuation of the message. No STOP is + * needed. + * - CASE 2.x.2: The next message may be to the SAME address WITH repeated start. + * Because the repeated start, a direction change is possible. This is still + * a continuation of the same message sequence and so no STOP is needed. + * - CASE 2.2.x: The next message may be a DIFFERENT address WITHOUT repeated + * start. This would be an error; The STOP will be sent, the next message will + * fail. */ cmd |= I2CM_CS_RUN; - if (priv->msgc < 2 && priv->mcnt < 2) + if (priv->mcnt < 2) { - /* This is the last byte of the last message... add the STOP bit */ + /* Are there more messages in this sequence? */ + + if (priv->msgc < 2) + { + /* No.. send the STOP */ + + cmd |= I2CM_CS_STOP; + } + else + { + /* Yes.. peek at the next message */ + + struct i2c_msg_s *curr = priv->msgv; + struct i2c_msg_s *next = curr + 1; - cmd |= I2CM_CS_STOP; + /* Same address as the current message? */ + + if (curr->addr != next->addr) + { + /* No.. send the STOP */ + + cmd |= I2CM_CS_STOP; + } + } } /* Set up to transfer the next byte. Are we sending or receiving? */ if ((priv->mflags & I2C_M_READ) != 0) { - /* We are receiving data. Write the command to the control register to - * receive the next byte. + /* We are receiving data. We need to ACK UNLESS we are going to send + * STOP. */ - cmd |= I2CM_CS_ACK; + if ((cmd & I2CM_CS_STOP) == 0) + { + cmd |= I2CM_CS_ACK; + } + + /* Write the command to the control register to receive the next byte. */ tiva_i2c_putreg(priv, TIVA_I2CM_CS_OFFSET, cmd); tiva_i2c_traceevent(priv, I2CEVENT_RECVSETUP, priv->mcnt); @@ -2078,6 +2116,7 @@ int up_i2cuninitialize(struct i2c_dev_s *dev) /* Yes.. Disable power and other HW resource (GPIO's) */ tiva_i2c_uninitialize(priv); + priv->refs = 0; /* Release unused resources */ |