I2C SDA/SCL race #83

Closed
opened 2021-06-20 21:53:24 +08:00 by sb10q · 3 comments

The current I2C code switches SDA and SCL almost at the same time, which can create false start/stop conditions.

Quick fix (not well thought through):

diff --git a/libboard_zynq/src/i2c/mod.rs b/libboard_zynq/src/i2c/mod.rs
index 8290903..28b9405 100644
--- a/libboard_zynq/src/i2c/mod.rs
+++ b/libboard_zynq/src/i2c/mod.rs
@@ -150,6 +150,7 @@ impl I2c {
         self.sda_oe(true);
         self.half_period();
         self.scl_oe(true);
+        self.half_period();
         // postcondition: SCL and SDA low
         Ok(())
     }
@@ -188,6 +189,7 @@ impl I2c {
             self.scl_oe(false);
             self.half_period();
             self.scl_oe(true);
+            self.half_period();
         }
         self.sda_oe(false);
         self.half_period();
@@ -196,6 +198,7 @@ impl I2c {
         // Read ack/nack
         let ack = !self.sda_i();
         self.scl_oe(true);
+        self.half_period();
         self.sda_oe(true);
         // postcondition: SCL and SDA low

The bug was inherited from the main ARTIQ repos and is also present there, but only became symptomatic on Kasli-SoC.

The current I2C code switches SDA and SCL almost at the same time, which can create false start/stop conditions. Quick fix (not well thought through): ``` diff --git a/libboard_zynq/src/i2c/mod.rs b/libboard_zynq/src/i2c/mod.rs index 8290903..28b9405 100644 --- a/libboard_zynq/src/i2c/mod.rs +++ b/libboard_zynq/src/i2c/mod.rs @@ -150,6 +150,7 @@ impl I2c { self.sda_oe(true); self.half_period(); self.scl_oe(true); + self.half_period(); // postcondition: SCL and SDA low Ok(()) } @@ -188,6 +189,7 @@ impl I2c { self.scl_oe(false); self.half_period(); self.scl_oe(true); + self.half_period(); } self.sda_oe(false); self.half_period(); @@ -196,6 +198,7 @@ impl I2c { // Read ack/nack let ack = !self.sda_i(); self.scl_oe(true); + self.half_period(); self.sda_oe(true); // postcondition: SCL and SDA low ``` The bug was inherited from the main ARTIQ repos and is also present there, but only became symptomatic on Kasli-SoC.

So there is this issue where, after NACK (i.e. SDA does NOT get pulled down by the receiver), SCL might not go low before a transition happens on SDA, meaning a "repeated" START could be triggered, is that correct?

In addition to your suggestion, we can also loop to read from SCL before the transmtter pull down SDA, and that should consume less than half an SCL period.

So there is this issue where, after NACK (i.e. SDA does NOT get pulled down by the receiver), SCL might not go low before a transition happens on SDA, meaning a "repeated" START could be triggered, is that correct? In addition to your suggestion, we can also loop to read from SCL before the transmtter pull down SDA, and that should consume less than half an SCL period.

Yes, I also just noticed that SCL might not be held low long enough before the next bit is shifted in/out on the SDA line. If my understanding is right, the I2C spec requires that no transition shall take place when SCL is not pulled LOW.

Yes, I also just noticed that SCL might not be held low long enough before the next bit is shifted in/out on the SDA line. If my understanding is right, the I2C spec requires that no transition shall take place when SCL is not pulled LOW.
Poster
Owner

So there is this issue where, after NACK (i.e. SDA does NOT get pulled down by the receiver), SCL might not go low before a transition happens on SDA, meaning a "repeated" START could be triggered, is that correct?

See the patch, there are at least 3 potential places where SCL/SDA races could happen.

the I2C spec requires that no transition shall take place when SCL is not pulled LOW.

Correct, unless you are doing START or STOP, you can only toggle SDA while SCL is low (and there should be some time margins).

> So there is this issue where, after NACK (i.e. SDA does NOT get pulled down by the receiver), SCL might not go low before a transition happens on SDA, meaning a "repeated" START could be triggered, is that correct? See the patch, there are at least 3 potential places where SCL/SDA races could happen. > the I2C spec requires that no transition shall take place when SCL is not pulled LOW. Correct, unless you are doing START or STOP, you can only toggle SDA while SCL is low (and there should be some time margins).
sb10q closed this issue 2021-06-25 16:27:03 +08:00
Sign in to join this conversation.
No Label
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: M-Labs/zynq-rs#83
There is no content yet.