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
Unable to work with two physical I2C buses #14735
Comments
Originally I used commit 14e5d30 from May 17 which was made before merging this feature. Nevertheless, I updated my local version to 5047bd3 and reverted d974b47 -- nothing has changed. Besides, I've fixed this issue locally and can make a PR if it's ok. |
Updated the original post: added |
Sure, we will be happy to review your proposition! |
Hi @rkotan,
|
I was not able to reproduce this issue.
Method used for reproduce: Observations:
After Rebase (Commit: c780165)
|
Besides the change in the target code (to increase the time). We still shall consider doing similar work as SPI did in the pull request #9469 (cc @kjbracey-arm - would it make sense to do the same peripheral logic for I2c). |
Of course, my specs are: Target: custom, based on the STM32H743VIT6 (mbed-os target inherited from I use a blocking read/write for configuring sensors and managing settings in the EEPROM and asynchronous transfer to obtain measurements from sensors. For each physical bus I have a dedicated thread in which this piece of code is called every time when sensor measurements are requested:
My program currently hangs during the asynchronous transfer to BMX160 which contains 1 TX byte (which is 0x04 -- start address of measurement results) and 20 RX bytes. I can share sensor configurations in case you need it. |
Hi @rkotan |
Quite possibly, yes - conceptually the I2C is akin to the SPI. The C++ object really represents an endpoint on a shared bus, so to cope with two independent users you need both objects referencing one bus to be using the same mutex. The suggestion in the OP to remove the But having only one mutex impairs performance of multiple buses - they become needlessly mutexed against each other. The format switching as if on a single bus shouldn't be totally breaking multiple bus use though. The buses should be used sequentially, and if the other bus was last used, then the bus will get reconfigured. But that shouldn't be doing anything other than wasting time. I guess that is just the complaint? Low performance? I'm surprised that any sort of peripheral reconfiguration would be slow compared to actual transfer speed - I2C is so slow! |
Oh, I note that rkotan mentions asynchronous transfers. That was something that was never properly addressed in the SPI case - asynchronous transfers for SPI basically bypass all the "acquire" and "mutex" logic. If you're using them, then you pretty much have to be on a dedicated bus, and know that no-one else is trying to use it while your async transfer is ongoing. My changes in that PR only tackled the blocking API, making that safe but efficient for all use cases. I didn't have the answer for async transfers, as they were never really safe. It is possible that some implementation error in I2C's asynchronous transfers is causing a conflict between the two buses. Maybe the asynchronous transfer is messing with |
Hi @rkotan, Can you confirm you are using |
Can you try this method and update CPU method.
|
Yep, I use this one:
I have a class for managing all transfers on each physical I2C bus which contains a
It will take some time to incorporate your code into my program. I'll post the results in a couple of days. |
@rkotan Thanks for the comment. |
I wrote the simple program, the code is following: Code
Without Console log
If both Console log
|
Thanks for the comment. Give you an update as soon as possible. |
Hi @rkotan and @affrinpinhero-2356
|
Hi, @idea--list
Unfortunately, I also don't have any non-STM target, so my opinion is questionable here. Based on the bug place, I would say it is the common issue which may hit any target with multiple devices on I2C buses at any moment.
It depends on how maintainers decide to deal with it. I think it is the architectural issue and for a start an agreement on how to handle several devices on I2C bus(es) should be reached. I have read forum topic and the related issue and it seems to me, for now there is no clear way how to use I2C in this situation. Some people think that I2C instance should be created every time when it is needed (I don't like this though see some reasons), others suggest that it must be created once and shared in some way between whoever needs it and there is no any actual documentation on how to handle this. In addition, @kjbracey-arm mentioned that some methods are thread-safe and some are not... In my opinion removing |
I've rechecked the I2C code, and realise I've been writing under a misconception - that it worked like
That means it is one bus per object, and then in that case, actually having multiple objects per bus is getting into sketchy territory - Mbed OS generally doesn't support that for HAL buses. Which in turn means if drivers do just make their own objects for (pin, pin address) tuples, you could get into a mess from duplicates. Also consider frequency - this is set per-object, ie per-bus - and that is correct. An I2C bus can only operate at the speed of the slowest device on the bus, unlike SPI where you've got the chip select pins to "mute" other devices, and you can run different devices at different speeds (and formats). Given that, I think correct behaviour does require that the top-level application create bus objects, configure their frequency, and then pass And then given that, I actually think removing the Does this help? |
Looking yet again, I see that there is shuffling of the |
i2c: fix issue #14735 with multiple buses
This one is fixed by #14805? |
I believe it is, closing |
Description of defect
Some time ago I updated mbed-os to 6.11 and suddenly faced performance issue.
CPU load has become very high, min 95% though it had never been above 45-50% before. After some profiling and digging in the sources I found the cause of this in the I2C driver. I use two physical buses with several devices on each, so it seems appropriate to me to have one I2C class instance per bus. However, I2C class has static members
_owner
and_mutex
(lines 237-239 of I2C.h):So, both of them are shared between all instances in the program and every call of
I2C::read
orI2C::write
from another I2C instance completely reconfigures it via callingI2C::acquire
. For obvious reasons this behavior seems completely wrong and in my case after some timeI2C::set_frequency
starts to eat up all available CPU time, because of deadlock or some improperly configured periphery.I simply made
_owner
and_mutex
non-static and issue was gone, though in that caseI2C::acquire
and_owner
also seems useless.I suggest that
_owner
and_mutex
should be non-static for obvious reasons and some consistency with behavior of SPI class where both of them are non-static.Target(s) affected by this defect ?
probably all, tested on STM32H743
Toolchain(s) (name and version) displaying this defect ?
gcc version 10.2.1 20201103 (release)
What version of Mbed-os are you using (tag or sha) ?
mbed-os-6.11.0
What version(s) of tools are you using. List all that apply (E.g. mbed-cli)
mbed-cli 1.10.5
How is this defect reproduced ?
The text was updated successfully, but these errors were encountered: