Skip to content

rp2 autosize, headroom that scales with flash, and the Picos in the exercise - #33

Merged
bdbarnett merged 2 commits into
mainfrom
scripts/exercise-rp2
Oct 6, 2026
Merged

bdbarnett merged 2 commits into
mainfrom
scripts/exercise-rp2

Conversation

@bdbarnett

Copy link
Copy Markdown
Contributor
  • rp2 autosize. When the link overflows the FLASH region, build_mp.py reads the linker's memory table, gives the firmware the image plus headroom, and rebuilds with the rest as the filesystem (MICROPY_HW_FLASH_STORAGE_BYTES, recorded as rp2_storage_bytes in the build record). --no-autosize refuses and prints the value that would fit.
  • Headroom scales with the flash on both ports: 1/32, between 64 KB and 256 KB. That's 64 KB on a 2 MB Pico and 128 KB on a 4 MB Pico 2, and esp32 boards from 8 MB up keep the old 256 KB. Brad: 256 KB was an eighth of a 2 MB RP2040.
  • The exercise script gains pico (RPI_PICO: displayif,pygraphics,palettes,pdwidgets) and pico2 (RPI_PICO2: displayif,lvgl-micropython). Its sdkconfig hash replaces the build dir with <build> (the partition-table path), and its list hashes sort in the C locale, so the comparable fields really are comparable across machines.
  • Docs: the Picos join the board table; autosize is described for both ports; the build plan is marked built and step 6 dropped.
  • modules.lock moves audiodsp, lvgl-micropython and displayif to the commits that let a bare clone build: Fetch Adafruit_MP3 at its pin when it's missing audiodsp#185 and Fetch the pinned lvgl-bindings when there's no sibling checkout lvgl-micropython#20 fetch their own pinned dependencies, and jpegio builds without LVGL displayif#47 lets jpegio build without LVGL.

Proven 2026-10-05:

  • RP2040 (RPI_PICO, displayif,pygraphics,palettes,pdwidgets) builds at 84% of its 640 KB region.
  • RP2350 (RPI_PICO2, displayif,lvgl-micropython) overflowed by 67,820 bytes. Autosize took it to 1280 KB of firmware and 2816 KB of filesystem on a clean build, with lvgl-micropython's CMake glue on its fetched bindings and jpegio's LVGL decoder compiled.
  • esp32 autosize with the new headroom, run against the LCD-7 build's real sdkconfig, gives the same 0x440000 table as before.
  • all overflows both Picos by 1.7 MB and 1.2 MB, as the script now says.
  • shellcheck -s sh passes on the script, and catches all three planted bash-isms.

…, the Picos in the exercise and the board table; the build plan is no longer a draft
…-their-own-deps and jpegio-without-LVGL merges
@bdbarnett
bdbarnett merged commit 2bcaec0 into main Oct 6, 2026
@bdbarnett
bdbarnett deleted the scripts/exercise-rp2 branch October 6, 2026 04:11
bdbarnett added a commit that referenced this pull request Oct 19, 2026
…stride (#33)

displaydev's FBDisplay.fill_rect tries bitmaptools, then a native fill_rect,
then a native blit, then per-row memoryview assigns. Three of displayif's five
framebuffer backends fell off the end of that list: a 100x100 fill on the P4
Touch-LCD-4B measured 1.387 s through Python band assigns into SPIRAM, against
12.3 ms for 400x240 on the S3, whose backend has a native fill (displayif#28).

Added, each about twenty lines around the same loop:

  esp32   mipidsi.Display   -- had blit and no fill; this is the P4 case
  mimxrt  mipidsi.Display   -- had neither
  common  rgbmatrix.RGBMatrix -- draw_buf is RGB565 (bit_depth is the matrix's
                                 PWM depth, not the buffer's)

The loop and the bounds rule now live once in src/include/displayif/fb_fill.h,
and the two backends that already had a fill_rect -- esp32 and mimxrt
dotclockframebuffer -- use it too, so all five agree on what a bad rectangle is.

Not added: rp2 picodvi.Framebuffer. Its buffer is 1/2/4/8/16bpp
(color_depth, default 8) over two SoC backends, so a fill is per-depth work
rather than a shared loop, and nothing here can build or run it. The issue says
so. The buses -- i80bus, spibus, qspibus, i2cbus -- cannot have one at all:
a panel fill is 0x2A/0x2B window commands plus a repeated RAMWR, and the window
belongs to BusDisplay, which already caches its fill strip.

Verified: the helper against a host harness (odd width, padded stride, corner
pixel, ten bounds cases) -- green, and 28 failures when the stride is planted
wrong, so it is not vacuous. mod_rgbmatrix.c syntax-checks against real
MicroPython headers with no new diagnostic (the one m_free error it reports is
the unix port's signature and is there before this change too). The esp32 and
mimxrt files need their SDKs and were not compiled here.
bdbarnett added a commit that referenced this pull request Oct 19, 2026
…35)

picodvi was the one framebuffer backend here with no fill_rect, so on an
RP2040 or RP2350 with a DVI output every displaydev.FBDisplay.fill_rect
fell off the end of the dispatch ladder onto per-row memoryview assigns
from Python. On the ESP32-P4, where the same fallback was measured on
hardware, a 400x240 fill costs 2.46 s that way against 3.5 ms through
the native fill -- a factor of 698 (#28). Nobody has measured it on an
rp2, but the ladder is the same one, and an app that clears a region
reads as a hung program rather than a slow one.

It was left out of #33 for a real reason: unlike the other five backends
this one is not fixed at 16bpp. color_depth is 1, 2, 4, 8, 16 or 32 and
defaults to 8, across two different SoC backends, so it cannot use the
shared displayif_fb_fill_rect16 and the sub-byte depths need partial-byte
masking at the left and right edges that none of the others has to think
about.

So the masking goes in the shared header as
displayif_fb_fill_rect_packed, beside the 16bpp fill, and picodvi is a
thin caller of it -- bounds through the same displayif_fb_rect_ok, so it
refuses exactly the rectangles the other five refuse.

Which end of a byte is the LEFT pixel is not a choice and the header says
where it is read from: the RP2350 HSTX command expander pops pixels by
shifting the word RIGHT, so the first pixel on the wire is the low bits.
Getting that backwards does not crash and does not look like a fill_rect
defect -- a fill comes out mirrored within each byte, which at 1bpp is a
four-pixel stagger along an edge. It is written down once so the board
bring-up has something to check rather than something to discover.

The deinit guard is not decoration either: picodvi_rp2350_deinit()
m_free()s the framebuffer and sets it NULL, so a fill after deinit would
write through freed memory. RuntimeError and the wording match
rgbmatrix's guard beside it.

Proven two ways, neither of them a DVI monitor. tests/test_fb_fill_packed.c
runs the packed fill against a naive per-pixel reference over 4908
rectangles across all six depths, walking every start and width the byte
boundaries can produce rather than sampling a few, with canary bytes
either side because writing outside the rectangle is this code's first
failure mode. Three planted faults: MSB-first packing (1615 failures),
a whole-byte write that spills past the right edge (1605), and OR
instead of replace (3 -- caught only by the fill-with-zero case, which
is why that case is there). And mod_picodvi.c compiles for rp2350 with
the real ARM toolchain, no warnings.

THE BOARD PROOF IS OWED: no rp2 board is here, nothing was flashed, and
the pixel order above has not been seen on a screen.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant