Repository navigation
fix(i2c): refresh target RX FIFO count between interrupt causes - #135
Merged
Merged
Conversation
floitsch
added a commit
to toitlang/toit
that referenced
this pull request
Sep 20, 2026
Update `third_party/esp-idf` from `1d89388f11383182b35c06fe44278847235b3a53` to `bf81d4c8cdaeaee5a13feca0c8aea60988f12807`, incorporating two merged I2C fixes: - [toitware/esp-idf#134](toitware/esp-idf#134): drain the controller TX FIFO before a repeated START so the next address cannot overwrite pending write data. - [toitware/esp-idf#135](toitware/esp-idf#135): refresh the target RX FIFO count between interrupt causes, preventing a 20-byte write from being reported as 40 bytes with a corrupt suffix. Includes a deterministic two-device Unity regression.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When RX-watermark and transaction-complete interrupts are pending together, the I2C target v2 ISR drains the RX FIFO in the watermark branch and then reuses its entry-time byte count in the completion branch. A 20-byte write can therefore be reported as 40 bytes, with a corrupt extra 20-byte suffix.
Refresh the hardware RX count before COMPLETE handling and before passing it to STRETCH handling, since an earlier branch may already have drained the FIFO. This keeps later consumers from reading bytes that are no longer present.
Validation
A deterministic two-ESP32 hardware test disables only the target's I2C interrupt, writes 20 bytes followed by STOP, and then re-enables that interrupt. The 20 bytes exceed the 16-byte watermark but fit inside the 32-byte FIFO, forcing watermark and completion to be pending together without overflowing it.
patch-head-5.4.2;git diff --checkpasses. The production change is the same two-line fix tested on hardware.Test source, unpatched log, patched log, and investigation are included with toitlang/toit#3241. The forced hardware case covers watermark plus COMPLETE on classic ESP32; the conditional STRETCH path receives the same defensive refresh.
Assertion-based regression in this PR
components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_slave_v2.cnow includesI2C slave refreshes RX FIFO count between interrupt causes. The classic-ESP32 two-device Unity case is discovered by the existingslave_v2pytest configuration.For three distinct payloads, it disables only the target I2C interrupt until the controller has written 20 bytes and issued STOP, verifies co-latched watermark/completion interrupts and FIFO occupancy, then re-enables the interrupt and asserts exact receive length, exact contents, and no hardware/driver overflow. Peripheral resources are released before checking the captured results. Both controller operations and callback waits have timeouts; the multi-device harness also enforces the case timeout.
The ESP32
slave_v2test application compiled and linked successfully. The app README documents wiring, an isolated build configuration, and the pytest command.Fresh hardware A/B of this Unity case on two classic ESP32s (2026-09-20, test commit
5a7e6182a615416095a09e7c1b44094c34b059fa):Expected 20 Was 40Both roles complete three transfers before asserting their captured results. The fixed target passes all three sets of interrupt, FIFO, overflow, length, and payload assertions. The unpatched target fails the first length assertion after its interrupt/FIFO/overflow preconditions pass.
The case was selected by name and its two stages run through the Unity serial menu, relaying the standard Unity synchronization signals. The existing rig required build-only overrides from GPIO18/19 to GPIO17/16 and releasing GPIO13 as an input with pull-up: GPIO13 is connected through a resistor to the rig's SCL. These fixture overrides were identical in both builds and are absent from the committed generic test. Initial runs without releasing that probe timed out and are not counted as regression evidence. The controller remains synchronous.
Application SHA-256:
238ede84b48ba92401c98d5cef5f4c7eca2a88e55b903c5093eaaf50b15680adb346785ccaeb6ab21dc8d1ff6c393c7c4fe2381e1a09146012f829e1352cce4bRelationship to other I2C fixes
This is independent of #134, which drains the controller TX FIFO before a repeated START. That change touches
i2c_master.c; this change fixes target RX handling ini2c_slave_v2.c, so the two can be merged independently.This patch fixes the demonstrated corrupt suffix. It does not claim to fix the separate intermittent early NACK/long interrupt-service gaps observed with a classic ESP32 Jaguar target at 400 kHz; an IRAM-safe A/B did not eliminate those gaps.