Skip to content

Migrate SPI controller operations to async - #3161

Merged
floitsch merged 10 commits into
floitsch/spi.20-buffer-targetfrom
floitsch/spi.30-async-controller
Sep 13, 2026
Merged

floitsch merged 10 commits into
floitsch/spi.20-buffer-targetfrom
floitsch/spi.30-async-controller

Conversation

@floitsch

@floitsch floitsch commented Aug 6, 2026

Copy link
Copy Markdown
Member

Stacked on #3160. The required ESP-IDF patch head is already on master.

This migrates ESP32 SPI controller transfers and explicit bus reservation away from blocking primitives.

Highlights:

  • controller transfers are split into start and finish primitives; start queues with zero timeout and finish polls for the completed descriptor
  • an allocation-free post-transaction callback wakes the waiting Toit task through the resource event queue
  • native DMA buffers are allocated and populated before dispatch, and every synchronous error or retryable OOM path cleans up fully
  • operation cleanup remains protected across yields and cancellation, including deadline handling, so dispatched transactions are always finalized
  • explicit bus reservation uses try-acquire plus a Toit yield loop; a failed try rolls back only its own pending lock request
  • short transmit-only transfers use persistent inline transaction storage, and zero-length transfers avoid null pointer arithmetic
  • two-board tests verify scheduler progress during a deliberately slow transfer and repeatedly exercise reservation contention
  • full SPI target and buffer-target suites pass on classic ESP32 and ESP32-S3, covering modes, bit order, speeds, DMA and non-DMA lengths, partial classic DMA words, overflow, re-arm, and maximum-size transfers

The ESP-IDF patch head on master includes the narrow public nonblocking bus-acquire operation and the later I2C/SPI hardening. A recent upstream ESP-IDF checkout still has no public finite-time or nonblocking SPI bus acquisition, so the private-fork addition remains necessary and follows the existing ESP-IDF lock API.

This is a complete-transaction API. Half-buffer streaming and watermark callbacks are deliberately not included.

@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from 8c5ba0f to ff823a4 Compare August 10, 2026 12:47
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch 2 times, most recently from f84c4ae to 36a90c4 Compare August 10, 2026 14:29
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from 36a90c4 to 0dc5c19 Compare August 10, 2026 16:11
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch 2 times, most recently from 6e9364e to 5ab5adf Compare August 10, 2026 20:13
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from 5ab5adf to e9039a2 Compare August 10, 2026 21:40
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from e9039a2 to c4fddc6 Compare August 10, 2026 21:51
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from c4fddc6 to 81ce542 Compare August 10, 2026 22:58
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from 81ce542 to 63cc407 Compare August 11, 2026 01:18
@floitsch

Copy link
Copy Markdown
Member Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The SPI transfer implementation now separates transaction start and completion. ESP32 transfers use queued transactions, event-driven completion, managed buffers, and non-blocking bus acquisition. The Toit API serializes transfers and closes devices under a mutex.

Changes

SPI transfer flow

Layer / File(s) Summary
Toit transfer flow
lib/spi.toit, src/compiler/propagation/type_primitive_spi.cc, src/primitive.h
Device_ now coordinates start, completion state, and finish operations under a transfer mutex. The SPI primitive contract exposes transfer_start and transfer_finish.
ESP32 event resource wiring
src/resources/spi_esp32.h, src/resources/spi_esp32.cc
SpiDevice now uses an event queue resource. ISR callbacks post completion events, and device creation supplies the queue and callback.
ESP32 transfer and bus primitives
src/resources/spi_esp32.cc
The ESP32 backend queues transactions, retrieves results with timeout handling, manages transfer buffers, and uses try-acquire bus semantics.
Validation and configuration
tests/hw/esp32/spi-buffer-target-shared.toit, toolchains/esp32/sdkconfig, toolchains/esp32/sdkconfig.defaults
Hardware tests cover asynchronous transfers and repeated bus-acquisition attempts. SPI ISR and related IRAM settings are disabled.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🟡 Moderate · up to 5e7af

The asynchronous SPI transfer and bus-reservation changes can leave a reservation unreleased if the device closes while a task is yielding, and certain completion errors may strand an in-flight transaction and its buffers. The associated interrupt configuration and required ESP-IDF change also need explicit validation, so this is not merge-ready until the lifecycle and error paths are addressed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 26 functions across 4 files. (4 skipped: 4… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely summarizes the main change: migrating SPI controller operations to asynchronous behavior.
Description check ✅ Passed The description directly explains the asynchronous SPI transfer migration, nonblocking bus reservation, cleanup behavior, tests, dependencies, and scope.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 26 functions across 4 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch floitsch/spi.30-async-controller

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from 63cc407 to b813676 Compare August 11, 2026 23:56
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from b813676 to a3cd396 Compare August 12, 2026 21:18
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from a3cd396 to 59a5ab5 Compare August 12, 2026 21:46
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from aac57ae to b010aac Compare September 2, 2026 18:38
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from b010aac to f115e1f Compare September 3, 2026 15:48
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from f115e1f to e46fe11 Compare September 3, 2026 15:57
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch 2 times, most recently from 5482b71 to ff93ff9 Compare September 3, 2026 22:15
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch from ff93ff9 to a19c46a Compare September 4, 2026 16:45
@floitsch
floitsch force-pushed the floitsch/spi.30-async-controller branch 2 times, most recently from eeeb310 to 9552d02 Compare September 7, 2026 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant