Replies: 7 comments 45 replies
-
demo_auto.mp4
|
Beta Was this translation helpful? Give feedback.
-
|
what exactly do you need to know? I will give you whatever information you need an if the API needs to change in order for the STM bus drivers to work with the current design between the bus drivers and the display drivers then I am OK with doing that. nothing gets changed in libs/micropython. If the code in micropython needs to be changed then changes needs to be hot patched and written in python scripts to handle that. That's of the change is not for a specific port. If the change is port specific then a copy of the existing file need to be placed in the micropy_updates folder retaining the directory structure from the port folder to the file. then that file needs to have the modifications made to it as needed. The bus drivers need to be written in a manner that allows them to be a runtime choice. as an example. If using an I8080 display either 8 pins or 16 pins should be able to be selected when the bus driver starts, The use of DMA memory should also be a runtime choice if a choice is available to make. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks Kevin, that settles the design. One readback on the part I don't want to get subtly wrong, then one question. Framebuffers — my understanding: explicitly allocated and freed (never heap, never stack), handed to LVGL as a memoryview whose backing memory outlives the memoryview itself, since LVGL extracts the raw C pointer and the reference counting ends there. I'll keep the Single layer, ESP32 RGB backend as the reference, bus class identical except the constructor — all clear, no questions. Rotation. Since RGB/LTDC is software-rotation only and you'd rather it not be duplicated, I'll peel it out of the ESP32 RGB backend into a shared module usable by any RGB-type backend. One question: do you want that as a separate commit inside the LTDC PR, or as a small preliminary PR landed first, so the refactor is reviewable on its own before the STM32 code arrives? I'm fine either way — your call on what's easier to review. Starting on reading the ESP32 RGB backend now; I'll come back with a concrete plan rather than guesses. — Nuraci |
Beta Was this translation helpful? Give feedback.
-
|
Two good questions. My take on each. Pin representation. I'd make On the int question specifically: a bare int doesn't work cleanly for STM32. On ESP32 an int is the pin identity (GPIO 0..48), but on STM32 "5" is ambiguous — PA5? PB5? PI5? There's no canonical int→pin mapping the way ESP32 has. So I'd do:
That gives you the common API without forcing an int representation onto STM32 where it doesn't fit. Document Worth noting: my STM32 backend can accept Duplicated-but-explicit constructors. I agree, and I think the apparent tension with "common API" dissolves once you separate two things:
So removing the plumbing/wrapper abstraction in the ESP32 constructor sounds right. The one discipline I'd keep: for concepts that exist on both ports (width, height, timings, pixel format, framebuffer count), keep the public parameter names and meaning identical, so a driver written against one bus works against the other. Only genuinely port-specific inputs — the scattered LTDC pin list on STM32 — differ. One distinction so we don't accidentally undo the rotation decision: the wrapper code you want to remove is plumbing. The software-rotation we agreed to pull out is an algorithm that's genuinely identical across ports — sharing that is clarity-positive, not the kind of abstraction that obscures. So "duplicate the constructors" and "share the rotation service" aren't in conflict; they sit on opposite sides of the right line. — Nuraci |
Beta Was this translation helpful? Give feedback.
-
|
Pins / memory footprint. Agreed on the priority — on a constrained device the lightweight form should win, and the string already gives you that on STM32: it's small, transient, and freed by the GC once the constructor resolves it to (port, pin, AF). No On the int-as-register-address: you're right that every STM32 GPIO maps to a register address, so an int could encode a pin. But I'd still pick the string for STM32, because the register-address int buys nothing over the string on memory while adding two costs:
If you ever want the absolute-minimum-RAM path (no transient string alloc at all), the clean version isn't a raw register address but a packed int — port index in the high nibble, pin number in the low (e.g. PC10 = Shared module — a thought on who does the peel-out. This is your ESP32 code, and you know exactly where rotation, dither and byte-swap live and how they're wired in. You'd almost certainly be faster doing the extraction and the renaming yourself than I would be reverse-engineering it. So one option: you do the peel-out into the shared header/source, and I just consume that shared header from the LTDC backend. That keeps each of us on the code we know best — you on the ESP32 internals, me on the STM32 hardware where I'm the one with the boards and the datasheets. I'm genuinely happy to do the move myself if you'd rather hand it off — it's mechanical enough — but on your own code you'd be quicker, and it keeps me focused on the part only I can do. Either way works for me. On scope, whoever does it: the clean split is the three pure algorithms (rotation / dither / byte-swap) move into the shared header/source, and the task infrastructure stays put — you flagged it needs to stay, and it's the part entangled with the RTOS/multi-core question below. Task stuff / multi-core — answering your STM32 question. The model doesn't transport to STM32 the way it does on ESP32. My H743 is single-core, and MicroPython's stm32 port doesn't run a preemptive RTOS — there's no FreeRTOS task to offload the refresh onto. The LTDC peripheral scans the framebuffer out to the panel autonomously via its own DMA; synchronization happens through the LTDC reload/VSYNC interrupt, not through an RTOS task. So the STM32 "frame done" equivalent is that ISR firing. Practically: if you define a base set of task-handle structures for the common API, STM32 will populate them degenerately (or leave them unused) and signal frame-done from the reload ISR. That's fine as long as the common API doesn't require a real task/RTOS to exist. Multi-core STM32 parts (H745/H747, M7+M4) do exist but they're out of scope here and I wouldn't design for them now. Reading the ESP32 backend now to understand the RGBBus API I need to match and how the shared functions get consumed — useful either way, whoever ends up doing the peel-out. -Nuraci |
Beta Was this translation helpful? Give feedback.
-
|
Totally understand — the other project comes first, and time is exactly the thing you can't get more of. No rush on the peel-out; whenever you make that hole works for me, and in the meantime I'll keep moving on the parts that don't depend on it. Quick context on my side so we schedule something realistic: this porting is a hobby for me. My day job is in a company doing electronic measurements in a lab, so my weekday daytime is taken. That rules out the window I'd have otherwise suggested (it lands right in my work hours). Here's what actually works, given I'm in Italy (UTC+2 right now) and you're UTC-6/-7, ~8–9 hours apart:
So a typical session would be a weekday evening my time / your late morning, 2–3 hours. Tell me which day suits you and I'll be there. If a weekend works better for a longer first session to get rolling, I'm open to that too. One thought on making the most of the limited overlap: since we'll only share a few hours at a time, I'd reserve the synchronous sessions for the hard nodes — the design calls and the "bumps" you mentioned — and do the bulk of the coding async on either side of them. The shared hours go to the decisions that need both of us live, not to watching each other type boilerplate. Hit a bump, thrash it out, peel off and implement. On the channel: I'd prefer text-based real-time over voice — my written English is solid but my spoken English is slower, and for dense technical work a chat keeps things precise and gives us a written trail of what we decide. Something like a Discord text channel (or a shared screen with chat alongside) would be ideal. Happy to use whatever you already live in, as long as we can type. Good starting point. Tell me a day and a channel and let's set the first one up. |
Beta Was this translation helpful? Give feedback.
-
|
when you get some time you should take a look at this project... It will possibly be useful for you in the future. That is the project I am working on that will hopefully fund my retirement. I am currently at more than 500 Python source files totaling over 135,000 lines of code and getting larger each day... I think it will probably be somewhere around 250K lines of code when complete. That's code that I have personally written and not total number of lines. |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
-
Hi @kdschlosser, hi everyone,
I've spent the last several months building LVGL+MicroPython support for a family of affordable STM32H743 boards (DEV190806042, FK743M5-XIH6, STM32H7_CORE). They share the same recipe: external SDRAM, QSPI flash, and an RGB TFT panel driven by the H7's hardware LTDC peripheral. Working end-to-end on real hardware, I currently have:
I originally pushed this upstream as
lvgl/lv_micropython#104, #105andlvgl/lv_binding_micropython#407, but that side of the project is effectively unmaintained: the STM32 CI workflow is disabled, the runner-update PR has been open since Aug 2025, my PRs are sitting untouched. I'd rather invest the migration effort once and land it where the project is actually moving — i.e. here.Before I start cutting code I'd like to align on architecture. To keep this thread focused I'll lead with the one question that drives everything else.
LTDC doesn't really fit the
lcd_bus"push pixels" model — it's a hardware scan-out from SDRAM, conceptually closer to the ESP32RGBBus. Would you prefer:(a) an
LTDCBusas a subclass oflcd_bus, symmetric withRGBBus;(b) a standalone driver under
api_drivers/common_api_drivers/display/behind aCONFIG_STM32/ port guard;(c) something built on top of the existing generic
rgb_displaydriver?I have follow-on questions — board routing (direct PR to
micropython/micropythonvsmicropy_updates/), alignment with the existing GT911 driver, and how STM32 SoC-specific drivers should be wired intomake.py— but they all depend on (a)/(b)/(c), so let's start there.One practical note: you've mentioned on the LVGL forum that lack of STM32 hardware is a blocker. I have these three boards on my bench and I'm willing to do the debugging and ongoing maintenance for them. If a self-hosted GitHub Actions runner wired to one of the boards would help close the CI loop, I can set that up.
Refs:
Thanks!
— Nuraci (@nuraci)
Beta Was this translation helpful? Give feedback.
All reactions