Electronics > Projects, Designs, and Technical Stuff
I2C automatic data rate adaption to pullups
(1/6) > >>
jmaja:
I've been working with Cypress PSoC BLE chip and found out by testing it adapts I2C data rate based on pullups. When I set 400 kHz I get 300 kHz with 20 k, 330 kHz with 10 k, 345 kHz with 5 k and 397 kHz with 470 pullups. That's without any slaves on the bus, thus totally controlled by PSoC.

How does it know, which pullups I have used? Probably not from rise time, since I get 100 ns 30%->70% even with 10 k. I2C 400 kHz spec requires just 300 ns.

So it likely measures the current needed to hold the scl low and assumes 400 pF capasitance (I2C specs requirement) and sets data rate based on that.

Is that common? I have never heard about such before and can't find much from documentation. It only mention that real data rate may be different depending on tR and tF.

Is there a way to get 400 kHz with 5-10 k pullups? Maybe the 5 k internal ones? Some setting to override the adaptation, since I wont have large capacitance. Just one slave and 25 mm long PCB track.
T3sl4co1l:
More likely it's waiting until a valid logic high is received, before beginning the next clock-high period.  So the output frequency is 1 / (t_cycle + t_rise).

Easy way to prove/disprove it's based on current sense: place a capacitor in parallel.  A capacitor has no effect on DC current, but proportionally increases risetime. :)

You can also emulate a lower value resistor with a constant current source, which draws the same current all the way up, whereas a resistor only delivers the most current at the lowest voltage.  You get a slanted rise, rather than a slow curve.  A 1mA CCS will be equivalent to about a 1.5k resistor, but only requires the current of a ~3.3k resistor.

To get higher clock speeds, it would seem the better option is to increase the internal clock rate, however you would do that (prescaler from a master clock? dedicated oscillator/timer section?).  This begins to violate the I2C spec, though, and you should consider the high speed mode if supported by all devices, or something with higher overall speed, like SPI, asynchronous serial, or parallel.

Tim
jmaja:
I haven't found anything helpful yet, but I did find that also ESP32 suffers from the same problem/feature: https://www.esp32.com/viewtopic.php?f=14&t=1350

It seems to measure the high time based on actual logic value crossing. That doesn't seem to be the case with Cypress, since then I should get very close to 400 kHz with 100 ns rise time, which is already clearly inside I2C specs.

Or maybe it is? The period (with internal 5 k) is 2.90 us (345 kHz). If I measure the low time at very close to 0 V, it is 1.38 us. Thus clearly less than half period (1.45 us) but still more than half period at 400 kHz (1.25 us). The high time (measured from 0 V) is 1.52 us. So apparently driving low is asymmetric and it actually needs to be, since I2C specs require 1.3 us minimum low time and only 0.6 us minimum high time. At 1.38 us before the very sharp falling edge the voltage is already over 70%.

Even measuring at 90% the high time is 1.3 us so more than double the spec requirement. So either the chip is extremely conservative with the specs or it is measuring something other than voltage level change.

With 0.47 k pullup (SCL only) the period is 2.52 us, low time 1.37 us (measured at 0 V) and high time 1.15 us. So it seems to just reduce the high time.

Then I tried to increase system and SCB clocks to get more oversampling. With 30 oversampling instead of 20 used earlier I got 359 kHz with 5k and 352 kHz with 0.47k. So the effect of pullup became smaller but even with 0.47 k the data rate is 10% below what is it set at.

Distributing the 20 oversamplings differently (originally 11 low and 9 high) I can adjust the asymmetry, but the total period stays the same.

Playing with clock frequencies and oversampling set up I can get e.g. 424 kHz actual with 1.26 us low time (1.31 us to 30%) and 1.1 us high time (0.93 us to 70% and 0.80 us to 90%). Would that work reliably with a slave only capable of 400 kHz? The actually set data rate is 500 kHz. With 0.47k pullups I get 498 kHz with 1.25 us low and 0.77 us high. Then low time would be a bit too short, since it's only 1.26 us to 30%.

I didn't have a suitable capacitor at hands. I could find only 1 nF through hole capacitor and it stopped the I2C line permanently (needed a boot, probably reseting the I2C line would have worked as well). So it certainly notices capacitance.

I tried the slave at 800 kHz (about 0.6 us high and low time, actual setting 1000 kHz). Still worked OK, so I guess it is safe to use it at 500 kHz?
ataradov:
All I2C controllers I've seen rely on releasing the line and waiting for the logic level to go high. So bus capacitance and pull-up resistors affect the period.

How do you "set 400 kHz"? Typically you set some sort of a prescaler/baudrate register, which is not directly related to the actual I2C clock frequency. May be whoever wrote the library used different R/C values for calibration.

I fund it is easier to adjust the baudrate divider until I hit the necessary frequency. And if bus structure does not change in run-time, it is good enough.
jmaja:
OK, so it's common to adjust the clock rate based on rise time. I've used mostly SPI so far so I didn't know about this and it doesn't seem to be easy to find anything actually said about it. I guess it is somewhat related to clock stretching, since master needs to monitor the SCL line.

It's a hardware I2C so the actual clock rate must be defined by hardware. Software just inputs register values and the byte to be sent/read.

I don't quite like the idea that data rate and thus timing depends on what the bus capacitance and internal pullup value happen to be. Then the whole timing of the software gets messed up. Sounds stupid to make the data rate slower even with perfectly OK rise time.
Navigation
Message Index
Next page
There was an error while thanking
Thanking...

Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod