Skip to content

Calculate proper I2C SDA hold time #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 29, 2021
Merged

Conversation

dhalbert
Copy link

@dhalbert dhalbert commented Mar 29, 2021

Instead of empirically determining the I2C SDA hold time, calculate the number of clock ticks to get the 300ns required value. See https://www.nxp.com/docs/en/user-guide/UM10204.pdf#page-48, table note [3] for the origin of the 300ns value.

The hardware default is 1, but that is arbitrary, since the length depends on ic_clk. 2 was enough to fix several I2C devices. 5 was need for PA1010D. However, the calculated value is 38 for 300ns. So the other values were quite marginal; this should be a lot safer.

Tested with PA1010D, LIS3DH, BME280, BNO055, and TCS34725.

These two traces show 5 vs 38. Note that the hold time applies only when SDA falls and SCL is high.

pa1010d-5-vs-38

Copy link

@jepler jepler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes real sense!

@lurch
Copy link

lurch commented Mar 29, 2021

@dhalbert You might want to also delete .github/workflows/cmake.yml from your fork, in order to get rid of those "skipped checks" icons 😉

@dhalbert dhalbert merged commit 7a66601 into circuitpython Mar 29, 2021
@dhalbert dhalbert deleted the calc-sda-hold-time branch March 29, 2021 18:16
@kevinjwalters
Copy link

kevinjwalters commented Mar 30, 2021

This is a far better approach than using a fixed value of 125MHz clock cycles (clk_sys) of the RP2040. That sounded very device specific and was going to do peculiar things for under/over clocking.

Note that the hold time applies only when SDA falls and SCL is high.

Isn't the requirement to have SDA held regardless of its value as SCL falls and the 300ns is the protection for that?

BTW, in your traces I don't understand what's going on around 6.3us (based on timescale at top). SDA is changing but it's nowhere near an SCL fall? Is that the slave NAKing? Is that trace with 400kHz requested and 10k pull-ups?

@kevinjwalters
Copy link

From a look at your traces changing this value does not appear to affect the SCL low time (based on i2c->hw->fs_scl_lcn) which is good from the point of view of not impacting the i2c clock speed.

@dhalbert
Copy link
Author

Note that the hold time applies only when SDA falls and SCL is high.

Isn't the requirement to have SDA held regardless of its value as SCL falls and the 300ns is the protection for that?

It's described in terms of the falling edge; see the USB spec screenshot below. I was just emphasizing that it is only for the case when SCL is high, which addresses:

From a look at your traces changing this value does not appear to affect the SCL low time (based on i2c->hw->fs_scl_lcn) which is good from the point of view of not impacting the i2c clock speed.

Yes, it took me a while to find what was being lengthened in the trace, because it's a specific case of SDA and SCL.

BTW, in your traces I don't understand what's going on around 6.3us (based on timescale at top). SDA is changing but it's nowhere near an SCL fall? Is that the slave NAKing? Is that trace with 400kHz requested and 10k pull-ups

It might well be the NAKing, but I haven't tried to analyze that. The trace is 100kHz and 10k pullups.

image

@kevinjwalters
Copy link

Each clock cycle looks around 3us which makes it around 330kHz?

@dhalbert
Copy link
Author

Each clock cycle looks around 3us which makes it around 330kHz?

Oh, yes, maybe you are right, I did test at 400 kHz as well. I took a lot of traces.

Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noted on the CP PR that this likely won't work for 1mhz I2C because the fall time for it is 120ns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants