Introducing my GSoC Project!
I will be contributing to the RTEMS Project under Google Summer of Code (GSoC) 2025!
RTEMS is an open source Real-Time Operating System. It is used in space flight, medical, networking and many more embedded devices. RTEMS currently supports 18 processor architectures and approximately 200 Board support packages. You can learn more here.
My project is titled “Implementing MicroPython Support and Packaging It For RTEMS”. MicroPython is a Python 3 implementation designed to run on microcontrollers and in other constrained environments. Being able to interact with an embedded device using Python is very cool, because you can just spin up an interpreter and start playing with the thing. No compilation and fiddling around with random vendor IDE parameters required.
This is the first post of many that I will be writing throughout the program as I work with my mentors and the larger community to add this support to RTEMS. For this post, I want to share what I’ve done so far and give you an idea of what this will look like.
During the Application Period, I created a simple proof-of-concept using a special MicroPython port which they call the “embed” port. As the name suggests, this is designed to make “embedding” MicroPython easier. The build output is a bunch of C source files with no other dependencies that you can directly include in your project and execute MicroPython code by passing it as a string to the the function mp_embed_exec_str. There’s also some other housekeeping functions like mp_embed_init, but the main functionality here is the ability to execute MicroPython code and get some output which you might decide to process further based on your application. This works for a small demo, and the fact that I was also able to bring this proof-of-concept up on actual STM32F4 hardware helped me learn more about using RTEMS with different BSPs as I had to tweak the Linker Script to get RTEMS to boot up on my board.
This, however, is not enough. We need a higher level of integration between MicroPython and the “host” system (RTEMS in this case) to really call it a “port”.
The “Porting MicroPython” page in the MicroPython docs gives an example of a very basic port. We can follow this and the source code of the other available ports to get our RTEMS port going. Currently it has a mphalport.c file that implements mp_hal_stdin_rx_chr, mp_hal_stdout_tx_strn and readline that allow us to output a MicroPython shell over serial by calling pyexec_friendly_repl() in our main code. We can’t yet enter things into the shell so that needs to be fixed.
You can take a look at the current mphalport.c and the main mpy.c. Additionally, mpconfigport.h is used to enable and disable features like the machine module at compile-time.
Now here’s the problem - we need this to work across a lot of different boards (RTEMS BSPs or “Board Support Packages”). Taking a simple example like machine.SPI in MicroPython, not all BSPs might have SPI support, and it’s not a good idea to compile all of this code and take up useful Flash space on a device that doesn’t have those features.
Here’s my current mental model of what this could end up looking like:
An ideal solution would really be one that simply doesn’t build features that aren’t available on the BSP being used. Let me quickly go through the ones discussed in the diagram:
Simply using mpconfigport.h
So we include the MicroPython library, and it will be a requirement for all applications that use this library to define this config file. If you’re wondering what this file looks like, here you go:
#include <stdint.h>
// Python internal features.
#define MICROPY_ENABLE_GC (1)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_READLINE_HISTORY_SIZE (0)
// Fine control over Python builtins, classes, modules, etc.
#define MICROPY_PY_ASYNC_AWAIT (0)
#define MICROPY_PY_BUILTINS_SET (0)
#define MICROPY_PY_ATTRTUPLE (0)
#define MICROPY_PY_COLLECTIONS (0)
#define MICROPY_PY_MATH (0)
#define MICROPY_PY_IO (0)
#define MICROPY_PY_STRUCT (0)
// Type definitions for the specific machine.
typedef intptr_t mp_int_t; // must be pointer size
typedef uintptr_t mp_uint_t; // must be pointer size
typedef long mp_off_t;
// We need to provide a declaration/definition of alloca().
#include <alloca.h>
// Define the port's name and hardware.
#define MICROPY_HW_BOARD_NAME "rtems-i386/pc686"
#define MICROPY_HW_MCU_NAME "unknown-cpu"
#define MP_STATE_PORT MP_STATE_VM
You can see that we have a lot of control over Python builtins like set, collections, etc.
We can also choose to define things like MICROPY_PY_MACHINE to build the machine module that further gives us access to machine.I2C, machine.SPI and friends. If you look at how the Zephyr Port does it, you’ll notice some interesting definitions:
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_INCLUDEFILE "ports/zephyr/modmachine.c"
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
namely MICROPY_PY_MACHINE_I2C and MICROPY_PY_MACHINE_SPI.
These are used to conditionally compile I2C and SPI support in machine_i2c.c and machine_spi.c. I think this is probably going to be how we specify the features we want to include. So based on the BSP being used and our requirements, we create a config file to enable the relevant MicroPython internal features and modules.
There will of course be examples config files and documentation for the supported “flags” here.
Higher Level Configuration
This is still a bit vague, but it would be neat if there was a way to enable/disable support without leaving the Python environment / using a high level config file (not sure what that would look like yet) / automatically selecting features based on the BSP being used.
This post was supposed to come out sooner (last week) but here we are, in week 1 of GSoC 2025! I am currently looking into the RTEMS Source Builder (RSB) and create a “recipe” so my “port”, which is right now more of a test application can be used as a library. So basically I will remove mpy.c (contains the actual “program” entry point) and mpconfigport.h out of the “port”, write an RSB Recipe so that I can include it in an RTEMS Application where I will have the main code along with the config.
Thank you for your time.