-
Notifications
You must be signed in to change notification settings - Fork 3k
STM32 I2C: Replace call to wait_us by a sw loop #6538
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
@fahim-ublox can you make sure this is OK on C030/C027? |
targets/TARGET_STM/i2c_api.c
Outdated
/* Timeout values for flags and events waiting loops. These timeouts are | ||
not based on accurate values, they just guarantee that the application will | ||
not remain stuck if the I2C communication is corrupted. | ||
*/ | ||
#define FLAG_TIMEOUT ((int)0x1000) | ||
|
||
/* Instead of using wait_us() which can causes issues in some cases */ | ||
#define WAIT_LOOP {uint32_t waitloop_timeout = BYTE_TIMEOUT_D2; while(--waitloop_timeout != 0);} |
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 wont be different with optimizations (different times) ? wont be optimized out?
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.
Also, instead of macro , use a function. Should do the same trick, but more readable
I have replaced the macro by a function and added some pragma to avoid compiler optimization. Tested with ARM, IAR and GCC. The loop time is between 3us to 10us depending of the board/compiler. |
I believe a problem was wait() that can cause an issue if object is created during the boot and RTOs might not be initialized. This can be solved as its here, but looking at the wait loop implementation - it shall fix it but having the optimization set in the code, and relying on it might not be the best approach. Why can't we use us ticker api. I recall some other HAL implementation uses it - what should fix this as well. Using us ticker read function and loop until the time passes? |
OK... I changed it by using us_ticker_read and loop timings are of course closer to the expected 1us... |
/morph build |
Build : SUCCESSBuild number : 1667 Triggering tests/morph test |
Exporter Build : SUCCESSBuild number : 1301 |
Test : FAILUREBuild number : 1462 |
We seem to have one I2C test failure that occurs when we include the [original version] of this PR. We're just running the test again with the latest version, back with you soon... |
One comment: we're assuming here that us_ticker makes use of 1 microsecond - this is tru for all STM32 targets as far as I know, nevertheless this is not a requirement in mbed |
+1 |
We've now tested with the latest version of this PR and all our tests are passing. We must have an I2C chip with slightly sensitive timing; it was a particular I2C command, RESET, that had been failing. Returning to an accurate wait was probably what we needed. So we're OK with this PR. |
@RobMeades Thanks for testing and the feedback.
|
/morph test |
Test : FAILUREBuild number : 1470 |
cc @studavekar - can you review the failures please? /morph test |
Test : FAILUREBuild number : 1482 |
@bcostm Can you please review the test results? What commit is your branch based on? |
I am on master branch. I have rebased this PR. |
/morph build |
Build : SUCCESSBuild number : 1745 Triggering tests/morph test |
targets/TARGET_STM/i2c_api.c
Outdated
t1 = us_ticker_read(); | ||
do { | ||
t2 = us_ticker_read(); | ||
elapsed = (t2 > t1) ? (t2 - t1) : ((uint64_t)t2 + 0xFFFFFFFF - t1 + 1); |
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.
All the above isn't necessary - just elapsed = t2 - t1;
will suffice even on wrap because of the way unsigned arithmetic works.
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.
OK. Thanks for the review. I will update 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.
are you sure ? we don't know if the ticker is 32 bits or 16 bits wide ...
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 wasn't aware the ticker could be less than 32 bits wide, but seems it can.
But if it can be, that wrap logic wouldn't be correct. It's adding 2^32 when it sees it wrap. It should be adding 2^(ticker width), right?
I've seen similar wrap logic in other places in the tree, with both 2^16 and 2^32 increments, apparently with hard knowledge of their timer width. For this platform, it seems to be 32-bit.
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.
You're right ! the bit width of timer needs to be used. In STM32 targets we have both 32-bits and 16-bits timers and the I2C driver is common for all ... I definitely think that this function should be implemented carefully and would better belong to common code in mbed hal common layer for instance.
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 it can be 16-bit for you, I think you should be implementing us_ticker_get_info()
to reveal that to the world, which I don't see in any STM32 target directory. That is relied on to get the wrap right in some existing code.
Double-checking, looks like you implement your own 16->32-bit expansion in us_ticker_16b.c. So your us_ticker_read
is always 32-bit.
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.
The implementation of us_ticker_get_info() is done in ticker feature branch. This should land on master very soon. So this needs to be taken into account from now on.
Exporter Build : SUCCESSBuild number : 1380 |
Test : SUCCESSBuild number : 1548 |
Restarting CI since it appears that PRs have been rebased since the last run. /morph build |
Build : SUCCESSBuild number : 1778 Triggering tests/morph test |
Exporter Build : SUCCESSBuild number : 1421 |
/* Timeout values for flags and events waiting loops. These timeouts are | ||
not based on accurate values, they just guarantee that the application will | ||
not remain stuck if the I2C communication is corrupted. | ||
*/ | ||
#define FLAG_TIMEOUT ((int)0x1000) | ||
|
||
/* This function assumes the tick is 1 us */ |
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.
At a minimum should also comment that it assumes it's 32-bit - not sure if@LMESTM is happy with that assumption for this patch, given his comments.
I close this PR and I have open Issue #6664 instead in order to have this function at mbed level and not in ST platform only. |
Test : SUCCESSBuild number : 1588 |
Description
Replace the call to
wait_us()
with a sw loop using us_ticker_read.This has been already done in PR #6069 but canceled due to another fix.
Tested OK with I2C ci-tests on different boards
report_CISHIELD_fix_i2c_wait.txt
cc @RobMeades Maybe verify it also on your platforms ?
cc @LMESTM
Pull request type
[X] Fix
[ ] Refactor
[ ] New target
[ ] Feature
[ ] Breaking change