-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
ports/rp2: Provide direct memory access to PIO FIFOs via proxy arrays. #7650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ports/rp2/rp2_pio.c
Outdated
STATIC mp_obj_t rp2_state_machine_get_fifo_proxy(mp_obj_t self_in, mp_obj_t read_not_write) { | ||
rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in); | ||
|
||
mp_obj_array_t *proxy = m_new_obj(mp_obj_array_t); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be better as a memoryview
? Or because it's only 1 entry it doesn't really matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it an array since it never needs to be sliced, but since they are both mp_obj_array_t
under the hood it doesn't make much difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you print the resulting array object (eg at the REPL) then I think it will attempt to read the element, right? A memoryview
would not. If reading from the FIFO modifies the FIFO then it might be better to use a memoryview
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't aware of that difference, but it is a very good point. I will change it to be a memoryview
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
>>> import array
>>> array.array('I', [123])
array('I', [123])
>>> array.array('B', b'1234')
array('B', [49, 50, 51, 52])
>>> memoryview(b'1234')
<memoryview>
137e07b
to
96fd89a
Compare
I have pushed a new version of this rebased against the current master, since it goes hand-in-hand with #7641, which is now tagged for release in 1.22. |
Thinking about the API here: ideally we could use the buffer protocol (essentially Maybe that can be done automatically, because when the DMA requests the buffer/pointer it does know whether it's for reading or writing, in the d.config(read=my_sm, write=a, count=len(a)//4, ctrl=c, trigger=True) You can still get a memoryview(my_sm) That will be for the RX FIFO. To access the TX FIFO... not sure exactly how to do that, but is that even needed? Otherwise, the current Still, I think I prefer the buffer protocol approach better. |
Using the buffer protocol could make for tidy code, but it sort of makes me uneasy having a buffer protocol implementation that returns different values depending on if it's called for reading or writing. I agree that having the |
I think the API should match the existing patterns used by this class. That would be two separate methods then. |
For clarity, you'd like |
So, upon reflection (and reading the RP2040 datasheet), I think that the buffer protocol idea might be best, but if we go that way then I think we should also implement the same thing for the UART and SPI objects. Both of those peripherals use the same address for reading and writing, so the implementation is simpler for them. Note that for this to work we need to fix the DMA class's code in the that gets the buffer address, since at the moment it only ever asks for a readable buffer. If you agree then I will fix up this PR, including the fix needed for the issue mentioned above, and I will take a stab at a separate PR to add buffer protocol support for the SPI and UART objects. |
45a683e
to
dfd2fa5
Compare
Code size report:
|
I have updated this to use the buffer protocol, and also added buffer protocol support for the SPI data FIFO. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #7650 +/- ##
==========================================
+ Coverage 98.36% 98.40% +0.04%
==========================================
Files 159 159
Lines 21088 21088
==========================================
+ Hits 20743 20752 +9
+ Misses 345 336 -9 ☔ View full report in Codecov by Sentry. |
dfd2fa5
to
5f49069
Compare
This looks good now, using the buffer protocol on PIO and SPI. So, can you now pass a Is it also possible to make this work with UART? (At least in principle, so we don't have to have a special case for UART.) The only downside I can imagine for using the buffer protocol this way (for the address to pass to DMA) is that maybe in the future there needs to be another kind of buffer access on SPI/PIO/UART/etc. Eg for UART maybe you want to access the underlying ring-buffer, rather than the hardware data register. But that seems rather unlikely. I think using the buffer protocol to interface with DMA is a good idea. (An alternative would be to make the Can you please split this up into two separate commits: one to fix the DMA code that gets the buffer address (that's definitely a bug!), and another commit to implement the buffer interface on PIO and SPI? |
Yes, an I can also do this for UART object. The only slight complexity there is that the UART class gets defined in Regarding your speculation that we might want to use the buffer interface on some device for some other purpose, I guess it might happen one day, but I struggle to see what that use case would look like. Most peripherals only have two types of register: configuration and data transfer. It's possible that one day someone will come up with a reason to use a buffer to access some other part of the hardware but the current proposal seems to fit for all the use cases we have in hand. If there is another, more unusual use case then a function could be provided to fetch a proxy I'm happy to split the bug fix. Do you want that as a separate commit in the single PR, or as a separate bug fix PR? |
Just a separate commit in this PR would be fine, thanks. (One of the reasons for splitting out the bug fix is so it can be potentially merged to a patch-release branch.) |
5f49069
to
4dd26fe
Compare
@dpgeorge This is now split into two commits: one for the fix and one for the new functionality. |
Signed-off-by: Nicko van Someren <[email protected]>
Signed-off-by: Nicko van Someren <[email protected]>
4dd26fe
to
1da45e8
Compare
Thanks for updating. Now merged. |
As per the discussion in #7641, this PR adds a new
get_fifo_proxy()
method torp2.StateMachine
that allows a user to get a memory proxy for either the TX or RX FIFO of an instance. This can either be used directly to gain non-blocking access to the FIFO values or it can be passed to anrp2.DMA
instance for theread
orwrite
values. For example: