-
Notifications
You must be signed in to change notification settings - Fork 3k
i2c: fix issue #14735 with multiple buses #14805
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
Conversation
Make the _mutex non-static and remove _owner and acquire() When two or more I2C buses are used then static__mutex and _owner are shared between all I2C class instances in the program. That wastes time to reconfigure periphery on every transfer. Make _mutex non-static. Remove _owner and acquire() method because in non-static case they have no practical meaning.
@rkotan, thank you for your changes. |
This PR fixes the issue i described in #14742 , so i do not need to destroy my I2C instance to avoid MCU overload while recording my signal. That means i can use I2C sensors again while recording via SPI. |
Also referencing another issue where this fix was discussed #14735 (comment). Also https://forums.mbed.com/t/global-i2c-mutex-across-all-i2c-buses-causing-contention/13438/11 that was reported a month ago. cc @kjbracey-arm |
Can you elaborate how this fix addresses this - document it with this fix - it would be helpful for reviewers. |
unlock(); | ||
} | ||
|
||
// write - Master Transmitter Mode | ||
int I2C::write(int address, const char *data, int length, bool repeated) | ||
{ | ||
lock(); | ||
aquire(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removing aquire
from write/read and transfer methods might break applications or it does not? If owner != this, freq() would be invoked and we are removing this case completely. Is it intention and actually fixes the issue ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change would potentially break applications that are using multiple I2C
objects to represent the same bus. Whether they should ever have been doing that is open to debate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whether they should ever have been doing that is open to debate.
Someone from @ARMmbed/mbed-os-hal could help reviewing this and help us finding a solution for now and the next major version
If this is a breaking change (not just functionality change), we might want to hide this behind a configuration and do this breaking change for Mbed 7. all changes are related so it's not just acquire. Or any other options?
Config option could be i2c-aquire-enabled
, set to true by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Config option is probably a good idea.
Not sure about naming. I don't think you can use the misspelt name of a non-public method though :)
A few more suggestions, for either polarity - i2c-fully-mutually-exclusive
/ i2c-independent-objects
/ i2c-require-one-object-per-peripheral
/ i2c-permit-multiple-objects-per-peripheral
?
Whatever you choose, it's going to need a slightly long description as well to spell it out. I can't see a way of making the name self-explanatory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a planned release date for Mbed 7?
If i get it right using this fix we just need to reconfigure the I2C object before using a sensor that needs another frequency/I2C config than the sensor we communicated with last time on the same port. If that would be all that is there to it, i would not hesitate to merge this fix into the next minor release.
A config option is a good compromise, however that way Mbed would default to an I2C implementation that puts a huge load on the MCU that can result in several unspecific symptoms which are not straightforward to find the root cause of (just finding the root would probably take more time than reading the porting guide of the next release, understanding the flaw in I2C that has been addressed and change code).
As for config options names: the proposed names are hard to remember and i do not see people wanting to use more than 1 I2C implementation. So why not just call it i2c-high-processor-impact
and document clearly that an identified and fixed bug causes high mcu load but still leave space for the developer to decide if they want to struggle with a buggy implementation when they finally realize it eats up much of their MCU time...or they prefer using a fixed implementation that allows them to use the MCU for useful stuff 😎
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @0xc0170,
might break applications or it does not?
This is a breaking change only in case when two or more I2C instances simultaneously exist for a single physical bus. I'm not sure that such design is valid, see the issue
As @kjbracey-arm said,
Whether they should ever have been doing that is open to debate
I fully agree. I also think that config option is a good idea. I would say i2c-one-instance-per-bus
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an I2C implementation that puts a huge load on the MCU
I'd say that issue remains and is worth investigating - is the STM HAL taking longer to reconfigure that it should? If someone is really needing to reconfigure a bus, this could still be an issue. However...
another frequency/I2C config than the sensor we communicated with last time on the same port.
Is this a real-life use case? Devices that need to be spoken to at a lower frequency, but can cope with you speaking to other devices at a higher speed without getting confused? Don't you have to run the whole bus at the signalling rate of the slowest device on it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say that issue remains and is worth investigating - is the STM HAL taking longer to reconfigure that it should?
I have no idea as i do not have any STM targets.
Is this a real-life use case?
Yes, theoretically it is possible if you are lucky enough and your slow device does not begin to output erronous data when it gets confused. Though you are right that it should be avoided in practice as you can never tell in advance if your slow device would begin to misbehave or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If all agree, this would be feature type update - functionality change. Fixing the broken premise we did with I2c - no breaking change. No config, we will need to document this in the release notes.
Impact of changes and Migration guide would need more details to understand the scope of this change.
Let's wait for @ARMmbed/mbed-os-hal to review
I think the fix is viable (because it tallies with my most recent comment in that other PR/issue). I think it maybe needs a tad more explicit documentation. Give a specific note or example in the header Doxygen of how to handle two slaves on one bus - threads accessing those slaves must share a single Looking more carefully at the Doxygen, I do note that it already says that the But the |
Hi @0xc0170,
Do you mean documented examples, like Also, I think that an agreement should be reached on how I2C should operate. This is maintainers' decision, not mine. |
This pull request has automatically been marked as stale because it has had no recent activity. @ithinuel, @ARMmbed/mbed-os-hal, please complete review of the changes to move the PR forward. Thank you for your contributions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previous work either accepted the breaking change or proposed alternative solutions.
Either was is fine by me.
This pull request has automatically been marked as stale because it has had no recent activity. , please complete review of the changes to move the PR forward. Thank you for your contributions. |
Ci started |
We agreed to integrate this fix , same as for QSPI as mentioned above. |
Jenkins CI Test : ✔️ SUCCESSBuild Number: 1 | 🔒 Jenkins CI Job | 🌐 Logs & ArtifactsCLICK for Detailed Summary
|
Summary of changes
Make the _mutex non-static and remove _owner and acquire()
Since
_owner
and_mutex
are static both of them are shared between all I2C instances in the program and every call ofI2C::read
,I2C::write
orI2C::transfer
from another I2C instance completely reconfigures it via callingI2C::acquire
. When two or more physical I2C buses are used it wastes time and in some cases eats up all available CPU time.So,
_mutex
is made non-static,_owner
andI2C::acquire
method are removed because in non-static case they have no practical meaning.Impact of changes
Only one I2C instance per bus is allowed.
Migration actions required
Documentation
Currently there is no documentation on how to deal with neither multiple I2C buses nor several devices on single bus. This causes misunderstandings, see the forum topic and related issue. In my opinion both cases should be documented.
Pull request type
Test results
Reviewers