PIO and state machine helper functions
PIO and state machine helper functions
I've cut a few simple functions which are the equivalent to the sm class extension which I provided as pull request #6973. You'll find them here https://github.com/robert-hh/RP2040-Exa ... r/rp2_util.
There is a small readme. Examples are to follow.
There is a small readme. Examples are to follow.
Re: PIO and state machine helper functions
I added support for using DMA with PIO state machines and UART read.
P.S.: Programming the PIO reminds me of writing assembler code for the 6502. Only that the 6502 was way more flexible, even if it had the nick name "OR gate with clock".
P.S.: Programming the PIO reminds me of writing assembler code for the 6502. Only that the 6502 was way more flexible, even if it had the nick name "OR gate with clock".
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: PIO and state machine helper functions
Impressive work
Looking at your UART read example, I see why you abort the DMA and re-initialise it. Is there any potential for data loss here, or does the UART driver's ring buffer ensure that this doesn't occur for the brief duration?
It would be interesting to write an ioctl to integrate the UART DMA with uasyncio. On some platforms (ESP32) read data can be lost in uasyncio unless the UART rxbufsize is substantially increased. RP2 doesn't have this option. This is something I could look at once I've finished testing the 433MHz remote control library on RP2.
I wonder if there is any interest from the maintainers in putting your helper functions into mainline?

Looking at your UART read example, I see why you abort the DMA and re-initialise it. Is there any potential for data loss here, or does the UART driver's ring buffer ensure that this doesn't occur for the brief duration?
It would be interesting to write an ioctl to integrate the UART DMA with uasyncio. On some platforms (ESP32) read data can be lost in uasyncio unless the UART rxbufsize is substantially increased. RP2 doesn't have this option. This is something I could look at once I've finished testing the 433MHz remote control library on RP2.
I wonder if there is any interest from the maintainers in putting your helper functions into mainline?
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: PIO and state machine helper functions
The UART has no ring buffer, just a FIFO. And with DMA active even a UART IRQ will never be fired simply because DMA is faster.or does the UART driver's ring buffer ensure that this doesn't occur for the brief duration
Using DMA or the ring buffer driver which I am just sketching is exclusive. You cannot have both. You can however set up DMA to use the target buffer as a ring. See the posts of @mw66 in this thread viewtopic.php?f=21&t=9697, which I re-used.
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: PIO and state machine helper functions
Looking at the docs, the source, and the issue on GitHub I now know a bit more about the UART
Your comments are of course correct.
It does appear that the current RP2 UART class is broken when it comes to reception of fast streams. I briefly looked at what would be involved in making a uasyncio-compatible UART class using your DMA work to implement a double buffer. I hit a bit of a problem - but also lost interest a bit, concluding that this is a hack to fix an issue which should be tackled at the C level.

It does appear that the current RP2 UART class is broken when it comes to reception of fast streams. I briefly looked at what would be involved in making a uasyncio-compatible UART class using your DMA work to implement a double buffer. I hit a bit of a problem - but also lost interest a bit, concluding that this is a hack to fix an issue which should be tackled at the C level.
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: PIO and state machine helper functions
I'm jusr working on a change to machine_uart.c which supports already buffering for the receive side. It also supports timeout and timeout_char. It works. There were however problem in a stress test. These disappeared after I added gc.collect() in the main loop of the receiving script. Even if that script is plain vanilla python, it showed data that was never sent and never stored to the receive buffer. So it looks as if there is a problem with memory management.
https://github.com/robert-hh/micropython/tree/rp2_uart
https://github.com/robert-hh/micropython/tree/rp2_uart
Re: PIO and state machine helper functions
For just the timeout and non-blocking behavior there is a PR waiting to be honored: https://github.com/micropython/micropython/pull/6870
Edit: There is almost no activity in the rp2 port at the moment. I guess Damien waited for version 1.1 of the Pico SDK.
Edit: There is almost no activity in the rp2 port at the moment. I guess Damien waited for version 1.1 of the Pico SDK.
-
- Posts: 3
- Joined: Tue Mar 09, 2021 8:24 am
Re: PIO and state machine helper functions
Robert, have I got this right? To keep the DMA going forever all I have to do is top up the trans count regularly?
def dma_topup(chan:int, nword:int):
dma=ptr32(uint(DMA_BASE) + chan * 0x40)
dma[TRANS_COUNT] = nword
edit: using a circular buffer.
RING_SEL = const(1)
RING_SIZE = const(0b1111)
def dma_topup(chan:int, nword:int):
dma=ptr32(uint(DMA_BASE) + chan * 0x40)
dma[TRANS_COUNT] = nword
edit: using a circular buffer.
RING_SEL = const(1)
RING_SIZE = const(0b1111)
-
- Posts: 3
- Joined: Tue Mar 09, 2021 8:24 am
Re: PIO and state machine helper functions
Answering my own question...almost.
Will thrash it out properly...
Will thrash it out properly...
Re: PIO and state machine helper functions
Using RING_SEL and RING_SIZE is limited to buffers of 2**n size. If you want to use other buffer sizes, you have to use a second DMA channel and chain the two. See the post of @mw66 from Feb, 7, 2021 at viewtopic.php?f=21&t=9697