Skip to content

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

Merged
merged 1 commit into from
Jul 20, 2021

Conversation

rkotan
Copy link

@rkotan rkotan commented Jun 20, 2021

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 of I2C::read, I2C::write or I2C::transfer from another I2C instance completely reconfigures it via calling I2C::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 and I2C::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

[x] Patch update (Bug fix / Target update / Docs update / Test update / Refactor)
[] Feature update (New feature / Functionality change / New API)
[] Major update (Breaking change E.g. Return code change / API behaviour change)

Test results

[] No Tests required for this change (E.g docs only update)
[x] Covered by existing mbed-os tests (Greentea or Unittest)
[] Tests / results supplied as part of this PR

Reviewers


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.
@ciarmcom ciarmcom added the release-type: patch Indentifies a PR as containing just a patch label Jun 20, 2021
@ciarmcom
Copy link
Member

@rkotan, thank you for your changes.
@ARMmbed/mbed-os-maintainers please review.

@idea--list
Copy link
Contributor

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.

@0xc0170
Copy link
Contributor

0xc0170 commented Jun 21, 2021

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

@0xc0170 0xc0170 requested a review from a team June 21, 2021 08:02
@0xc0170 0xc0170 changed the title Fix issue #14735 with multiple I2C buses i2c: fix issue #14735 with multiple buses Jun 21, 2021
@0xc0170
Copy link
Contributor

0xc0170 commented Jun 21, 2021

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.

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();
Copy link
Contributor

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 ?

Copy link
Contributor

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.

Copy link
Contributor

@0xc0170 0xc0170 Jun 21, 2021

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.

Copy link
Contributor

@kjbracey kjbracey Jun 21, 2021

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.

Copy link
Contributor

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 😎

Copy link
Author

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.

Copy link
Contributor

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?

Copy link
Contributor

@idea--list idea--list Jun 22, 2021

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.

Copy link
Contributor

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

@kjbracey
Copy link
Contributor

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 I2C object for the mutexing to work.

Looking more carefully at the Doxygen, I do note that it already says that the I2C object represents an "I2C Master", so this change is making the implementation consistent with that.

But the SPI object uses the same "SPI Master" wording, and that does contradict its implementation and the way you give the slave select pin to its constructor. It possibly needs some adjustment...

@rkotan
Copy link
Author

rkotan commented Jun 21, 2021

Hi @0xc0170,

Can you elaborate how this fix addresses this - document it with this fix - it would be helpful for reviewers.

Do you mean documented examples, like I2C hello, world here? How would it be more helpful for reviewers, a comment in this topic or pull request in the documentation repository?

Also, I think that an agreement should be reached on how I2C should operate. This is maintainers' decision, not mine.

@MarceloSalazar MarceloSalazar requested a review from ithinuel June 23, 2021 08:19
@ciarmcom ciarmcom added the stale Stale Pull Request label Jun 25, 2021
@ciarmcom
Copy link
Member

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.

Copy link
Member

@ithinuel ithinuel left a 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.

@ciarmcom ciarmcom added stale Stale Pull Request and removed stale Stale Pull Request labels Jun 25, 2021
@ciarmcom
Copy link
Member

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.

@ciarmcom ciarmcom added stale Stale Pull Request and removed stale Stale Pull Request labels Jul 2, 2021
@ciarmcom ciarmcom added the stale Stale Pull Request label Jul 11, 2021
@0xc0170 0xc0170 removed the stale Stale Pull Request label Jul 14, 2021
@mergify mergify bot added the needs: CI label Jul 14, 2021
@mergify mergify bot removed the needs: review label Jul 14, 2021
@0xc0170
Copy link
Contributor

0xc0170 commented Jul 14, 2021

Ci started

@0xc0170
Copy link
Contributor

0xc0170 commented Jul 14, 2021

We agreed to integrate this fix , same as for QSPI as mentioned above.

@mbed-ci
Copy link

mbed-ci commented Jul 14, 2021

Jenkins CI Test : ✔️ SUCCESS

Build Number: 1 | 🔒 Jenkins CI Job | 🌐 Logs & Artifacts

CLICK for Detailed Summary

jobs Status
jenkins-ci/mbed-os-ci_unittests ✔️
jenkins-ci/mbed-os-ci_cmake-cloud-example-ARM ✔️
jenkins-ci/mbed-os-ci_build-cloud-example-ARM ✔️
jenkins-ci/mbed-os-ci_build-cloud-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_cmake-cloud-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_build-greentea-ARM ✔️
jenkins-ci/mbed-os-ci_build-greentea-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_cmake-example-ARM ✔️
jenkins-ci/mbed-os-ci_build-example-ARM ✔️
jenkins-ci/mbed-os-ci_cmake-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_build-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_greentea-test ✔️

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

Successfully merging this pull request may close these issues.

9 participants