CircuitPython 2026 - Execute within OS
I recently got a notification for this: https://blog.adafruit.com/2026/01/02/circuitpython2026-kickoff/
(If you want to get to the feature request itself fast, skip the first two paragraphs. These are background information that you can come back to if you need to know my rationale and thought process.)
Adafruit is asking for what are essentially new feature requests for CircuitPython. I read that a few days ago, and I couldn’t think of anything. The one significant issue I have with CircuitPython is its lack of a decent real-time graphics system. displayio is great…for tasks with limited animation where precise timing isn’t important. It’s too slow for serious real-time game animation though. Even at 320x240, with 16-bit color, it can’t get very good framerates. For status displays, it’s great. It has features for maximizing performance when only specific parts of the screen need to be written to at a time. In theory this can be used to do some sprite graphics tricks that ancient consoles used to get higher frame rates than the consoles were technically capable of, but in practice Python itself is too slow to get really good gains using this technique. A major reason for this is that most (maybe all) of the LCD display drivers for CircuitPython don’t use DMA, which means writes to the display are blocking even on microcontrollers with hardware SPI. Now, to be clear, I’m not trying to attack CircuitPython or Adafruit here. I understand that CircuitPython is a huge undertaking to maintain and improve, and Adafruit has limited resources for doing this. This isn’t the reason I’m not asking for this feature though. The reason I’m not asking for it is that I’ve already started working on it myself, and I fully intend on contributing whatever code is needed to add it to CircuitPython to ensure the feature is added, at least for the RP2350 and hopefully for a broader range of microcontrollers in the long run. I’ve currently got a 320x240 ST7789 doing 16-bit color at 50 fps, and once I’ve done some refactoring, I’m going to try to start the process of integrating my drivers for this, perhaps as well as the simple graphics library (SGL) I’ve written for it, into CircuitPython for the RP2350. (I don’t currently know any other microcontrollers well enough to do the same optimizations for them. I do have two other displays with different graphics controllers that I plan to integrate into this though, and maybe someone more familiar with other chips can port my SPI/DMA optimizations to them.)
I want a different feature. More and more CircuitPython is running on top of microcontrollers that are sufficiently powerful to run their own operating systems on. The RP2350 is one of these, and it’s the one I’m currently spending most of my time on. Specifically, I’ve got a few Adafruit Fruit Jam boards, which use the RP2350, and I’ve done the math: These boards are about on par with the Intel 486 systems of the 1990s. It doesn’t have the full 640KB of on-CPU RAM that the 486 had (the RP2350 only has 520KB), but it does come with the full 8MB of external RAM that was the maximum most 486 systems could handle. It has 16MB of flash memory, which is rather less storage space than my family’s 486 with its enormous (for the time) 256MB hard drive. On the other hand, I’ve already got some 64GB microSD cards that should work with the Fruit Jam, which absolutely blows away anything available to consumers in the 1990s. In terms of speed, the RP2350 is rated for clock speeds up to 150MHz, while the top speed for 486 CPUs was 100MHz. I had Pentiums with lower clock speeds than 150MHz (in fact, I upgraded my second hand Pentium machine to 133MHz). The ARM architecture used by default in the RP2350 also has far more registers than the 486, massively reducing memory accesses required for certain common types of loops and other tasks. In other words, even the architecture is better, at least for certain common types of tasks. It also has more than double the number of DMA channels of the 486 and a handful of other features that can save large amounts of CPU time. What it doesn’t have is an MMU, so no protected mode memory management, but this isn’t strictly necessary. The 486 did have an MMU, but programs (at least in DOS) could, and often did, kick it out of protected to mode to run in real-mode, giving them full access to memory and memory mapped hardware. MMUs are mainly valuable for multi-user systems, multi-threaded multi-tasking systems, and systems that are running untrusted software along side software that is managing sensitive information. A system like the RP2350 could do any of this, but in practice it’s almost always going to be single user, and it will be running only one program at a time. It might be multi-tasking that one program, but it’s probably never going to be used like a modern general purpose computer. What it might be used for, and will be if I have anything to say about it, is a single process mobile computer system capable of being used as a gaming console but also capable of running other kinds of apps as well. For this to work though, it needs to be able to load an executable into memory, turn execution over to that executable, and then clean up when that executable terminates.
And now for my feature request: I want a CircuitPython version that will run on the RP2350 (and maybe some of the ESP line and anything else that is powerful enough to be used similarly) in this mode. Basically, I want to be able to write up a C program that calls out to CircuitPython, giving it a .py (or .mpy) file as an argument, and CircuitPython will run that Python program. And then instead of rebooting the RP2350 when it is done, I want it to free any resources it was using and return to the calling address, so that my C program can continue running with the full resources available. I want it to use one of the user defined interrupts to issue system calls to the OS for things like allocating memory, so that the OS can be coded to manage memory so that CircuitPython doesn’t accidentally clobber memory being used by the OS. CircuitPython doesn’t need to use system calls for every hardware access, and it should be able to assume that when it is running, the OS is generally paused aside from potential DMA stuff that might have been triggered by system calls (or the USB subsystem that will probably be running on the second core, for the Fruit Jam).
I think this will require a handful of things. First, it will probably require compiling CircuitPython to be address independent, or it will require CircuitPython to be compiled into the OS, so that the locations of all of its components in the program flash memory are predictable at link time. Second, it will require coming up with a system call standard that all operating systems designed to be able to run CircuitPython this way will have to adhere to. (POSIX? Or maybe a micro version of POSIX adapted specifically for microcontrollers that lack things like MMUs?) Anyone writing an OS for this would need to implement all of these system calls for CircuitPython to work correctly within the OS. Third, CircuitPython would need to take an argument when it is called, that is a pointer to a string identifying the file that needs to be executed (or an open file handle, or some such). It would also be nice if the pointer could point to a string in memory that is an actual Python program itself, so maybe it needs to take an additional argument to identify whether the primary argument is a filename or a pointer to the actual program string itself.
How would this be useful? I’ve played around a bit with FruitJamOS, and to be quite honest, it’s a bit of a pain. I’m talking specifically about writing new programs. I can fire up a shell and mess around with files a bit, which is kind of nice, but then if I want to write a program I have to exit the shell and open an editor. Oh, but first, in the shell, I have to execute a command to make the CircuitPython drive read-only for the host OS it might be plugged into. To run my program, CircuitPyton has to reboot after changing some stuff so that it starts my new .py file instead of code.py or whatever. When my program terminates, it has to reboot again after reversing whatever it did to run my program. If I want to do stuff on the host OS, I have to first get into the shell in FruitJamOS and flip it back to read-write for the host OS. Now I’m sure there’s some way to setup CircuitPython so that it can do cleanup and start a new Python program without having to reboot, but what if I also want to be able to run native executables without CircuitPython taking up a ton of resources? What if I want something that functions just a little bit more like a real operating system than a graphical Python program selector menu that has to reboot to execute and to terminate programs?
Here’s what I’d really like to see: I want the Fruit Jam to be more accessible in general both to novices and to those who want to learn more advanced stuff. I don’t really care what kind of operating systems people want to make. I’d like to have a CLI operating system that can run graphical applications including both native executables and CircuitPython programs (and I’m willing to make this myself). Maybe someone else would like to make something similar to FruitJamOS but that functions more smoothly. Maybe another person wants to make a more full featured desktop/windowing OS. Sure, there’s going to be a limit at some point, but that’s not something CircuitPython needs to worry about. All it needs to do is work within an OS that provides the specific system calls it needs to function correctly without stepping on the toes of the OS. This would make the Fruit Jam an incredibly versatile system. I’d love to see it used as a handheld/TV console hybrid, and that’s part of the reason I’m working on the improved graphics drivers. I grew up using computers that seem ancient now though, and while it can be fun to imagine that they were too primitive to be useful today, the reality is that computers less powerful than the Fruit Jam did a lot of the things we do with computers today just as well. Sure, our spread sheets have more advanced functions…that we don’t use that much, and our word processors have more font options…that we shouldn’t use as much as we do, but the reality is that while modern software sometimes can made things prettier, it often has no more practical value than the productivity software my dad used on our 486 back in the early 1990s. Due to artificial constraints added by Apple and Google, tablet computers don’t do very much productivity stuff very well, but I know from experience that a computer like the Fruit Jam is plenty powerful enough to have significant practical value, but it needs to be able to run an OS, and without CircuitPython, doing stuff in a real OS on the Fruit Jam will be extremely difficult for beginners. So I’m proposing that CircuitPython be designed such that it can be compiled for the RP2350 and perhaps also other suitable microcontrollers to run under an operating system, so that people like me can make operating systems that make systems like the Fruit Jam practical mobile computing systems that can be programmed in an easy language like Python.
Anyhow, that’s my feature request. I know it’s probably a big ask. Maybe there’s a better way to do it, but CircuitPython is already designed to interact with the CPU in exactly the ways that are needed for this kind of thing. Maybe Blinka would be a better option for adapting to this use case, but then we would still need a Python port compiled to run under a very simple OS for Blinka to run in. CircuitPython may be the closest Python there is to something that could work like this. Overall, I see the RP2350 being an incredibly powerful mobile computing device, if the right coding support is available for it, and a critical step is going to be making it easy and smooth to program on it, not just for it externally. If CircuitPython could run on the RP2350 under a minimal operating system, that would be a huge step in allowing this to happen.
Lastly, I’d like to thank Adafruit for making CircuitPython and the Fruit Jam in the first place. CircuitPython may not be terribly performant, but it makes it super easy to write simple programs for microcontrollers that are much more complicated to program for in other languages. And I feel like the Fruit Jam is what the original Raspberry Pi was trying to be and honestly kind of missed the mark on a bit. I’d really like to see the Fruit Jam reach it’s full potential, and I hope this suggestion (and the actual work I’m putting into driver development) will help to get it there!

