-
Notifications
You must be signed in to change notification settings - Fork 7.4k
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
I2C driver bug (IDFGH-2966) #4999
Comments
Hi, @fpgamaster thanks !! |
Hi @koobest , Best Regards |
Hi, thanks |
Hi @koobest, |
I am encountering this problem as well @koobest The device I am using is the LTC2499 ADC. With this part, a conversion is initiated by addressing the device for a write (and optionally writing config data) - the stop bit of the write cycle initiates the conversion. Then, at a later time, a read can be performed to retrieve the result. However, while the conversion is in progress, the device does not respond to reads at all (i.e. it does not acknowledge the address with read flag). If a sufficient amount of time is allowed before attempting the read, then everything works. But, if you try to poll the device, you will run into this bug. No matter what value you give for Probing the bus with a logic analyzer, I see the following: Oddly enough, though, it does not appear to happen when the i2c address byte has the r/w bit set to write, rather than read. |
I'm suffering from this bug as well. I have a system where multiple devices sit on the same I2C bus, and I poll each on a regular basis, at well over 100 Hz. The timing here needs to be precise. Occasionally, one of the devices has an unavoidable failure and will not respond on the I2C bus for some time. I don't understand why the timeout specified in The |
To add a vote here: the Moddable SDK team would also like to see a way to customize We have a software example for developers that automatically scans the I2C bus for connected devices. Because we attempt a read from every possible I2C peripheral address, it encounters many expected device failures during normal operation. On other platforms we can scan every address in less than a second, but due to this issue it takes more than a minute to do the same on ESP32. Because individual developers are building with our tools and their own ESP-IDF clones, we cannot easily simply modify |
I just ran into this as well. The effect of this value is that it's impossible to use a timeout less than a full 1 second in |
Hello, |
We are looking at this in adafruit/circuitpython#5908. I went back in time, and when TickType_t wait_time = (ticks_to_wait < (I2C_CMD_ALIVE_INTERVAL_TICK) ? ticks_to_wait : (I2C_CMD_ALIVE_INTERVAL_TICK)); |
I thing this commit is where it gets wrong |
I can confirm this is an issue as well. Now that Arduino uses IDF's I2C driver, we are getting reports and I was able to reproduce it. |
Fix problem that i2c_master_cmd_begin() waits longer (at least 1 second) than specified in ticks_to_wait, in case the bus is stuck.
@KlausPopp Would you be interested in proposing this as a PR to https://github.com/espressif/esp-idf ? |
Hi Is there any update on this? I am having this same issue. |
It is amazing how long this issue can persist :) |
@fpgamaster yes its been a hopeful few years for reliable i2c communication. |
I have this problem too. Hope for a speedy solution |
Hi @chuyec Try my ugly workaround. I use it for a while :)
Best regards |
@fpgamaster Thanks a lot for your suggestion! I have already applied this fix from @KlausPopp: https://github.com/ci4rail/esp-idf/pull/5/files |
Hi @dhalbert! You made a mistake in mentioning the author. Of course, if he hasn't changed his nickname.🤔 He may not have seen your question. Best regards |
@o-marshmallow @mythbuster5 |
I am having the same issue... the thing is I am using an environment in which I can't simply patch the idf library. Espressif, please fix this. |
This is still an issue in 4.4.5. A quick glance at the master branch makes me think it will still be an issue there too. I2C_CMD_ALIVE_INTERVAL_TICK is internal to i2c.c and is only used for the modbus master in one place. It looks like all it is doing is making sure the i2c event queue doesn't wait less than a minimum amount of time. It looks like this has been done because there is a generic event in the interrupt saying some sort of master activity has occured. If it doesn't have some sort of activity it does a low level reset on the i2c state machine. I don't see why it has to be so long though? If you know your I2C is slow, or going to clock stretch a long time, you would have to make your total timeout for that command longer than the maximum clock stretch period you can expect anyway? If you are going fast you could quite reasonably consider the i2c hardware dead enough to need a reset after much less than 1 second. I might be missing something, but it looks reducing I2C_CMD_ALIVE_INTERVAL_TICK to a lower value would work fine? Even 50ms seems generous? I have only done about 5 minutes testing with 50ms but it seems to work ok so far? |
Hi @igrr |
go this same bug. Transmission over i2c between esp32 and arduino leonardo for bluetooth controllers support. During gameplay stops reacting fo 1 sec. i dont have this problem with xbox one s/x series x/s gamnepads but all others supported by blueretro, from time to time doesnt react 1 sec. |
I ran into the same problem: IMU sensor hanging for 1 second a couple times per minute... As a workaround I've created a fast bit-bang I2C lib, maybe it is of use for somebody else: https://github.com/qqqlab/ESP32_SoftWire |
We upgraded to ESP-IDF 5.1 and I2C issues that we had been seeing with clock-stretching in 4.4.x went away (e.g. with LC709203F). We are still seeing problems with BNO055 and related chips, but these peripherals do not obey the I2C protocol spec and don't work well.on several other chip families as well. Note also that the upcoming 5.2 has redone the I2C driver, at least from the API point of view: |
I had a look at the new API a little while ago and was disappointed to see it doesn't look like you can do partial transactions like the old one lets you do. We have an I2C slave where the request changes part way through depending on the reply of the slave. The read length is not known/fixed at compile time. E.g. Slave replies with a number of bytes to follow. On the current cmd list system I send two separate parts. One from start to the length byte, and then another to read the payload and send the stop etc. In our case we could do a repeat start i guess at the expense of a little speed, but the new API, while simple, is more abstracted than the old one. Actually, looking at it I don't think you can do that either. You can only do a repeat start on a single transmit/receive operation... The old API is a bit long winded, but it does give a lot more control. I'm having good luck so far with just using I2C_CMD_ALIVE_INTERVAL_TICK at 50ms by the way. |
Small update; I think problem is triggered when Bluetooth classic is used in the same time with I2c. Mine PS4 Gamepad, and Wii U are BT classic only. When I using those, timeout is triggered. |
Now I'm wondering if this will be fixed in 2023? |
@AxelLin Now its 2024, still waiting. Need the patch too... #12079 |
I'm pretty sure the espressif's developers know current behavior and this issue. |
I insist, I think in line 1148 should be >, not < |
@simonddd that was my conclusion above as well |
Fixes #4999 Former usage of I2C_CMD_ALIVE_INTERVAL_TICK macro overrode the ticks_to_wait parameter when the latter was too big
@o-marshmallow |
Fixes #4999 Former usage of I2C_CMD_ALIVE_INTERVAL_TICK macro overrode the ticks_to_wait parameter when the latter was too big
Fixes #4999 Former usage of I2C_CMD_ALIVE_INTERVAL_TICK macro overrode the ticks_to_wait parameter when the latter was too big
Fixes #4999 Former usage of I2C_CMD_ALIVE_INTERVAL_TICK macro overrode the ticks_to_wait parameter when the latter was too big
components/driver/i2c.c:
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait)
{
....
TickType_t wait_time = xTaskGetTickCount();
if (wait_time - ticks_start > ticks_to_wait) { // out of time
wait_time = I2C_CMD_ALIVE_INTERVAL_TICK;
} else {
wait_time = ticks_to_wait - (wait_time - ticks_start);
if (wait_time < I2C_CMD_ALIVE_INTERVAL_TICK) {
wait_time = I2C_CMD_ALIVE_INTERVAL_TICK;
}
}
....
}
This code results in wait_time = I2C_CMD_ALIVE_INTERVAL_TICK.
For situations when a timeout is needed it defaults to 1s (I2C_CMD_ALIVE_INTERVAL_TICK)!
A simple workaround is to replace this part of code with:
wait_time = ticks_to_wait;
The text was updated successfully, but these errors were encountered: