await SPI reads and writes #13054
-
Hi, is there a way to await SPI reads/writes as we can do with UART? And what about I2C? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
No. The SPI and I2C classes are synchronous. In my display drivers I make the large SPI transfers more A nonblocking SPI interface would be difficult because the data rates are so high (typically 40MHz). Task switching in |
Beta Was this translation helpful? Give feedback.
-
I've actually been thinking about this a lot lately, I believe it wouldn't actually be that hard to add support. Both SPI and I2C are out a type where both write and read operations are initiated by the MCU (in the default host / controller / master mode) so you don't have to worry about data reception at any time like UART does, it's a lot more structured. These peripherals could have an
Then write/readinto functions extended such that in non-blocking mode they return immediately, but hold onto reference to the buffer provided. The transfer to/from buffer can be handled in background by IRQ/dma - indeed the dma is already used for (blocking) spi transfers on stm already. I expect the write/readinto functions would immediately return the "expected length" of the buffers' been successfully queued to process and 0 if it's already busy. The ioctl should make these classes essentially stream compatible, so existing asyncio.Stream wrapper could be used. read function can also likely be made to work for stream compatibility but it would maybe need to allocate the required size buffer itself and return that immediately, to be filled in the background. Apart from asyncio use, this background mode would be useful for display drivers driven by C libraries like lvgl where much of the screen update handling could be done in the background. Your point about speed is interesting @peterhinch, it's true that for many SPI transfers they'd process so fast this isn't worth doing with async, however if enough data is queued, like a larger screen worth, it's likely to help. I wonder if this could possibly be used with external SPI flash too, push some of a write operation into background... Many of them are probably immediately followed by a (page) read so likely not help much. |
Beta Was this translation helpful? Give feedback.
-
The OP asked whether there was The issue of nonblocking interfaces has been discussed since the very early years of MicroPython - also in the context of ADC and DAC API's. With IRQ and DMA support they are undoubtedly feasible, and such an API would be useful in both synchronous and asynchronous code. For a definitive answer you'd need to talk to @dpgeorge but I assume that the reason such interfaces were never implemented was the issue of platform dependence. |
Beta Was this translation helpful? Give feedback.
No. The SPI and I2C classes are synchronous. In my display drivers I make the large SPI transfers more
asyncio
-friendly by sending part of the data and yielding to the scheduler so that the maximum blocking time is limited (see code).A nonblocking SPI interface would be difficult because the data rates are so high (typically 40MHz). Task switching in
asyncio
applications typically happens in tens of ms. The UART driver does clever things with buffers and interrupts so data is not lost - but data rates are much lower.