Skip to content

Busio: Added DMA functions for I2C, SPI, and UART#10854

Open
kamocat wants to merge 4 commits intoadafruit:mainfrom
kamocat:busio-dma
Open

Busio: Added DMA functions for I2C, SPI, and UART#10854
kamocat wants to merge 4 commits intoadafruit:mainfrom
kamocat:busio-dma

Conversation

@kamocat
Copy link

@kamocat kamocat commented Feb 26, 2026

Implemented and tested on rp2040 port. Other ports to come after we settle on the structure of the new additions.

Tested on rp2040 using the examples from the async busio library:
https://github.com/kamocat/CircuitPython_Async_Busio

I have structured the new DMA methods into the existing I2C, SPI, and UART classes, and implemented the actual async functions in a separate Python library. Please let me know if there is a better way.

Implemented and tested on rp2040 port
@kamocat
Copy link
Author

kamocat commented Feb 26, 2026

I need to set up a more robust test suite

  • What happens if an I2C slave NACKs early?
  • Does UART RX respect the timeout?
  • Can I recover the DMA channel after a failure?
  • Is the data actually transmitted correctly?

I am working on a PIO I2C device to better test long writes.

@anecdata
Copy link
Member

anecdata commented Feb 26, 2026

You're probably aware that there is a native i2ctarget module, but it has an issue currently for raspberrypi port (re: PIO I2C device in test suite). (Looking forward to async busio!)

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR. I have some suggestions about the API.

The idea is to implement non-blocking busio operations. DMA is one way of doing that, but it could also be done without DMA, by internal polling, etc.

So instead of exposing the name "DMA" to the user, could you make the API routines just use names like start_read() or non_blocking_read() or something like that?

The handle that is returned is currently an int. However, I think it would be better if it were an object, perhaps with some opaque (but perhaps printable or equal-comparable) characteristics. This would make porting the API across other ports be easier, in case the handle had to have other forms. It would also prevent passing invalid handles in.

I think it would be good to have a discussion in an issue about what the right general API is for non-blocking I/O operations.

@kamocat kamocat mentioned this pull request Feb 26, 2026
Removed any mention of DMA from the shared-bindings
Added opaque object for tracking transfer state
Updated uncrustify config to replace deprecated options
@kamocat
Copy link
Author

kamocat commented Feb 27, 2026

You're probably aware that there is a native i2ctarget module, but it has an issue currently for raspberrypi port (re: PIO I2C device in test suite). (Looking forward to async busio!)

That's an interesting option. Is clock stretching actually supported on the rp2040? I didn't see anything about it in the datasheet.

@kamocat kamocat requested a review from dhalbert February 27, 2026 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants