PIO and state machine helper functions

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
User avatar
Roberthh
Posts: 3668
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

PIO and state machine helper functions

Post by Roberthh » Fri Mar 05, 2021 12:06 pm

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.

User avatar
Roberthh
Posts: 3668
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: PIO and state machine helper functions

Post by Roberthh » Mon Mar 08, 2021 10:22 am

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".

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: PIO and state machine helper functions

Post by pythoncoder » Tue Mar 09, 2021 7:36 am

Impressive work :D

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.

User avatar
Roberthh
Posts: 3668
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: PIO and state machine helper functions

Post by Roberthh » Tue Mar 09, 2021 8:02 am

or does the UART driver's ring buffer ensure that this doesn't occur for the brief duration
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.
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.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: PIO and state machine helper functions

Post by pythoncoder » Wed Mar 10, 2021 1:19 pm

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.
Peter Hinch
Index to my micropython libraries.

User avatar
Roberthh
Posts: 3668
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: PIO and state machine helper functions

Post by Roberthh » Wed Mar 10, 2021 1:37 pm

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

User avatar
Roberthh
Posts: 3668
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: PIO and state machine helper functions

Post by Roberthh » Wed Mar 10, 2021 1:44 pm

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.

richardm292
Posts: 3
Joined: Tue Mar 09, 2021 8:24 am

Re: PIO and state machine helper functions

Post by richardm292 » Mon Mar 15, 2021 10:02 pm

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)

richardm292
Posts: 3
Joined: Tue Mar 09, 2021 8:24 am

Re: PIO and state machine helper functions

Post by richardm292 » Tue Mar 16, 2021 1:20 am

Answering my own question...almost.


Will thrash it out properly...

User avatar
Roberthh
Posts: 3668
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: PIO and state machine helper functions

Post by Roberthh » Tue Mar 16, 2021 7:11 am

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

Post Reply