-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
rp2: RP235: PSRAM support #15620
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
rp2: RP235: PSRAM support #15620
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #15620 +/- ##
=======================================
Coverage 98.57% 98.57%
=======================================
Files 164 164
Lines 21336 21336
=======================================
Hits 21031 21031
Misses 305 305 ☔ View full report in Codecov by Sentry. |
37b869b
to
325f90a
Compare
Code size report:
|
325f90a
to
0f3012d
Compare
I've retitled this PR to avoid it being confused with the RP2350 MCU support one 😆 |
I seem to be having trouble with PSRAM when using split heap, a crude test which uses RAM until a garbage collection is forced will crash/hang on that collection when using split heap, but seems to work fine using exclusively PSRAM. I'm going to refactor this code slightly to make split heap an option, rather than a requirement. |
443003d
to
71f561d
Compare
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.
Couple of small remarks (about my code!) while I'm on a train.
ports/rp2/rp2_psram.c
Outdated
// - Max select assumes a sys clock speed >= 120MHz | ||
// - Min deselect assumes a sys clock speed <= 138MHz | ||
// - Clkdiv of 1 is OK up to 133MHz. | ||
qmi_hw->m[1].timing = 1 << QMI_M1_TIMING_COOLDOWN_LSB | |
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.
This else branch could use a lower max select time, but given we're reprogramming this on every clock frequency change, let's just get it right for whatever the frequency is - I'll send a PR for that.
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.
Did we ever correct this? I've lost the plot a little!
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.
Yes, the timings are all correctly calculated now: https://github.com/micropython/micropython/pull/15620/files#diff-6f1e8a5d5fc889e64290b8285133f981f926db5d689e1ad2118b5c2bc967937fR135-R162
a732af7
to
7f1fcc7
Compare
56abd12
to
870d858
Compare
2fae3a9
to
3cd6781
Compare
e3ba430
to
c98c139
Compare
55880bf
to
1585553
Compare
Likewise! Let me know if you have any issues with the latest very aggressive rebase/refactor. A git diff suggested I didn’t mess anything up (outside perhaps of grouping the changes into the wrong commits) but the flash copy buffer is now 256 bytes instead of 4K. I ran the test suite and flash benchmarks so I’m pretty sure it at least works. But I’m mostly building from feature branches mixing PSRAM and other things so I won’t be cutting releases from this branch until I rebase those. |
Ah that's great, thanks @sfe-SparkFro. It hadn't dawned on me that the board definitions would be added already with the PSRAM support sitting dormant. 👍 I think we should probably build one of the PSRAM boards in CI to avoid surprise bitrot, but we can add that in a follow-up PR. |
Thanks @Gadgetoid. I dropped these into text files and ran the comparison pass (which isn't as nice as a graph, but it's something):
The numbers are all over the place, which is to be expected with flash caching differences - just a different binary layout can be more or less cache-friendly for a particular build, and the cache behaviour is probably totally different with PSRAM. However, I think it's encouraging that nothing is massively slower with PSRAM enabled and there is a reasonable mix of faster and slower. |
This is definitely one of the weirder set of uncrustify formatting choices that I've seen it make. 😆 I've pushed a fixup commit here that seems to keep it happy: Feel free to cherry-pick and squash into this PR. |
It's also in @mattytrentini's board def for the WeAct Studio RP2350B in the main repo:
|
c8eb6c5
to
eb9e0b3
Compare
This could be a good candidate for covering a couple of bases at once. (B variant and PSRAM)
Done, thank you! I have added |
Yes, I agree that it would be good to give more control to the user as to how they use PSRAM. There are lots of possibilities here about how the API could look and what functionality it would have. And that could also be implemented on esp32 and other ports that may have large external (and slower) RAM. But in the interests of getting this PR across the line and merged, I think what you have here is pretty good: just allowing a board to enable PSRAM or not, and using SRAM+PSRAM or just PSRAM for the GC heap. That's nice and simple, for now. The only downside of doing it that way now is that if we change it in the future, it'll be a backwards incompatible change (because most likely we will change it so there is less RAM available by default on start up). |
As someone relying heavily on this code in shipping products- that ship has already sailed 😆 at least for some of us, anyway. I think it could be reasoned that it'll be mostly vendors- not end users- who will see the fallout from such a compatibility break? Gotta keep us on our toes! |
7441621
to
bc2fb20
Compare
I tested this on a Pimoroni Pico Plus2 RP2350 (thanks @Gadgetoid for it!), which has 8MiByte PSRAM. I ran the standard MP test suite. And also an extensive RAM test that I have which does 8-, 16- and 32-bit write and then verification (using a PRNG), in sequential forward and sequential reverse mode (the entire RAM) and also in random access mode. All tests passed. |
Add PSRAM support with auto detection. Performs a best-effort attempt to detect attached PSRAM, configure it and *add* it to the MicroPython heap. If PSRAM is not present, should fall back to use internal RAM. Introduce two new port/board defines: * MICROPY_HW_ENABLE_PSRAM to enable PSRAM. * MICROPY_HW_PSRAM_CS_PIN to define the chip-select pin. Changes: ports/rp2/rp2_psram.c/h: Add new PSRAM module. ports/rp2/main.c: Add optional PSRAM support. ports/rp2/CMakeLists.txt: Include rp2_psram.c. ports/rp2/mpconfigport.h: Add MICROPY_HW_ENABLE_PSRAM. ports/rp2/modmachine.c: Reconfigure PSRAM on freq change. Co-authored-by: Kirk Benell <kirk.benell@sparkfun.com> Co-authored-by: Mike Bell <mike@mercuna.com> Signed-off-by: Phil Howard <phil@gadgetoid.com>
PSRAM will be used exclusively if MICROPY_GC_SPLIT_HEAP == 0, it will be added to RAM if MICROPY_GC_SPLIT_HEAP == 1, and the system will fall back to RAM only if it's not detected. Due to the size of PSRAM, GC stack was overflowing and causing the GC to scan through the entire memory pool. This caused noticable slowdowns during GC. Increase the stack from 256 to 4096 bytes to avoid overflow and increase the stack entry type size to accomodate 8MB+ PSRAM. Changes: ports/rp2/mpconfigport.h: Make split-heap optional and enable by default. Increase GC stack entry type to uint32_t. Raise GC stack size. Co-authored-by: Kirk Benell <kirk.benell@sparkfun.com> Signed-off-by: Phil Howard <github@gadgetoid.com>
Add a 256 byte (FLASH_PAGE_SIZE) SRAM copy buffer to allow copies from PSRAM to flash. This would otherwise hardfault since PSRAM is disabled to write flash. Changes: ports/rp2/rp2_flash.c: Add 256 byte (flash page size) SRAM copy buffer for PSRAM to flash copies. Invalidate the XIP cache to purge any PSRAM data before critical flash operations. Co-authored-by: Phil Howard <github@gadgetoid.com> Co-authored-by: Angus Gratton <angus@redyak.com.au> Signed-off-by: Phil Howard <github@gadgetoid.com>
Configure flash timings dynamically to match the system clock. Reconfigure timings after flash writes. Changes: ports/rp2/main.c: Set default flash timings. ports/rp2/modmachine.c: Configure optimal flash timings on freq change. ports/rp2/rp2_flash.c: Reconfigure flash when leaving critical section. Signed-off-by: Phil Howard <github@gadgetoid.com>
Depends upon RP2350 support: #15619
This is a rough draft gathering our PSRAM support code - with a dash of SparkFun's - and attempting to get it into the right shape for mainline.
TODO:
Potential: Remove init frommain.c
and add bindings tomodrp2
so PSRAM can be enabled (or not) inboot.py
Known issues:
Possibly crashy, need a good test to reliably test the extent of the PSRAMNeeds to be reconfigured whenmachine.freq()
is called, since a clock change breaks PSRAM timingsMight break USB on startup or otherwise fail to start upImprovements:
We're (Pimoroni) currently using yet more customisations on top of this PSRAM code for Presto, which stores the entire display buffer in SRAM and leaves basically none for others buffers. See: pimoroni@888f52f
This is a bit rough for inclusion into MicroPython - I always wince at a near duplicate linker script - but incredibly useful nonetheless.
Some kind of bindings for PSRAM
rp2.PSRAM()
inmodrp2
might be nice, too. This would allow us to - theoretically - add a portion of PSRAM to thegc_heap
and reserve the remainder for RAMFS, long-lived buffers, custom memory pools and other such nonsense. I did contemplate addingMICROPY_HW_PSRAM_RESERVE_BYTES
for this, which would reserve N bytes from the detected PSRAM size for tomfoolery and shenanigans.