risc-v/espressif: Fix I2C polling wait timeout comparison. - #20165
Conversation
b97fc78
clock_t is an unsigned type unless CONFIG_SYSTEM_TIME64 is selected, as
documented in sys/types.h. The difference in
while (current - timeout < 0 && priv->error == 0)
therefore underflows to a large positive value instead of being
negative, the comparison is always false, and the loop body never runs.
status keeps its initial value of zero and the function returns OK
without having waited for the transfer at all.
Because the polling path reports completion immediately, every transfer
looks successful: no timeout is ever raised and register reads return
whatever the RX FIFO happens to contain. The function is compiled in
under CONFIG_I2C_POLLED, which boards use when the I2C interrupt is not
wired up.
Cast the difference to int32_t to get the intended signed comparison.
The result also stays correct across the counter wrap, as long as the
timeout is shorter than the counter range, which SEC2TICK(10) satisfies.
Since this file is modified by this commit, the pre-existing nxstyle
violations reported by the check job are fixed as well, as asked in
CONTRIBUTING.md section 2.1 (adapt all modified files even if you did
not introduce the problem yourself):
* esp_i2c.c:1267 - statement over-indented inside its enclosing
block (8 spaces where the block body is at 6)
* esp_i2c.c:1303 - missing blank line after declarations
* esp_i2c.c:1592 - missing blank line after declarations
* esp_i2c.c:1710-1725 - 'case'/'default' labels inside switch(port)
sat at the same indent as the brace opening
the switch body; they belong one level further
in, with the case logic one more level in from
the label
Assisted-by: WorkBuddy:DeepSeek-V4.1-Flash
Signed-off-by: Aurora-QIU0 <2170685247@qq.com>
b97fc78 to
b6c06cf
Compare
|
The issues reported by the Because this PR touches
Verified locally with The workflow runs for the new commit show |
Testing update 鈥?build and runtime logs (ESP32-P4, real hardware)Board: ESP32-P4 Function EV Board ( BuildRuntime before the change (polling mode, GT911 at 0x5d, I2C0)Serial capture after reset 鈥?the I2C devices never come up and Instrumented probe inside
Runtime after the change (same board, same bus)The read of |
|
@xiaoxiang781216 @raiden00pl the NTFC is failing for all PR:
Maybe we should convert NTFC errors to warning to avoid breaking the CI |
|
@acassis but that is exactly why NTFC is for: detecting regressions in code. You have a clear reason why it's failing: a crash in ostest. |
Yes, I was just afraid that it could start producing more false positive and make our CI worst. I just merged apache/nuttx-apps#3790 let's see if it will fix everything. Now everybody needs to rebase |
@raiden00pl but why NTFC can't block the patch which introduce the break: #20112? |
|
@xiaoxiang781216 because #20112 was not a breaking change. Breaking change was in apache/nuttx-apps#3759 |
|
@xiaoxiang781216 @raiden00pl I think any change on sched/ needs to be well tested, because it affects all arch/boards and all applications. We are seeing many patches coming where the test is not properly done. The testings when modifying sched/ should include many real boards. |
|
@acassis but that’s not the problem in this case. Here, the issue is from the separation of |
Understood. I think at least the "Restart Job" button on CI interface should automatically update the master to avoid asking the contributor to do a rebase to let the CI update to the latest nuttx and apps |
The better direction is improving ntfc and nxdart to run the test case on real hardware distributed. Requesting contributor to do the testing with many real boards will decrease the community activity. |

Summary
clock_t is unsigned unless CONFIG_SYSTEM_TIME64 is set (see sys/types.h). The
comparison in esp_i2c_polling_waitdone():
underflows to a large positive value, so the condition is always false and the
loop body never runs. status keeps its initial value of zero and the function
returns OK without ever waiting for the transfer.
Under CONFIG_I2C_POLLED every transfer therefore reports completion immediately:
no timeout is raised and register reads return whatever the RX FIFO happens to
contain. This is a silent "false success" - no error is reported.
Cast the difference to int32_t to restore the intended signed comparison. The
result stays correct across counter wrap since the timeout is much shorter than
the counter range.
Impact
Testing
Validated on real hardware during an ESP32-P4 board bring-up. Before the fix,
I2C reads returned garbage (0x2f) with ret=0 - a mathematically impossible
combination (status==0 yet success). After the fix, the GT911 touch controller
enumerated correctly and register reads returned real values.