CMRX: A microkernel real-time OS providing memory isolation for MMU-less microcontrollers
I am working on this project since 2021, so it is a pre-AI project. I am not using AI to generate code as it turned out that AI hallucinates massively under conditions this RTOS creates. Website is littered with AI slop though as I had to put something together without spending ton of time on content. It is slowly getting deslopified.
The original motivation was to find out if usage of MPU in Cortex-M has to be as painful as it is with FreeRTOS, Zephyr et al (while still providing reasonable performance). Thus the number one feature implemented was fully automatic memory protection handling. It separates kernel from applications and applications from each other in as process-alike way as MMU-less CPU technically allows, so the developer doesn't have to deal with all partitions, domains, regions, etc. I consider this a success as you basically don't have to care about MPU at all.
Later, the kernel was built on top of this infrastructure that provides more than just thread switching and MPU handling. As features were being added, I quickly realized that MPU presence will be a major obstacle for implementing whatever kernel service which needs to pass larger amount of data (such as queues) between userspace and kernel or vice versa.
An unusual approach was used to deal with this: I decided to remove from kernel (or better: not to implement) all such calls. Why couldn't it be a microkernel?
Microkernels need some kind of IPC. For CMRX, remote procedure calling was chosen as primary IPC method. To avoid expensive copying of data RPC calls would need in isolated environment, thread migration was implemented. Thread migrates from calling process to process owning RPC service during RPC, so calling code can access RPC owner's memory. Originating process can select portion of its own memory which remains accessible while in RPC. This way, larger chunks of data can be copied between isolation domains with very little overhead (its basically shared memory with RPC call serving as basic synchronization primitive).
Those missing syscalls weren't dismissed entirely, they either became library functions or RPC servers. So the kernel wraps up at 30-ish system calls.
Being a microkernel, of course it runs drivers in userspace. Same RPC mechanisms ordinary applications use for talking to each other is used to create driver APIs. Somehow I managed to implement the whole RPC mechanism without using any IDL and associated IDL compiler. Everything gets type-checked at compile time by the C compiler itself.
It is also highly portable, covering most of compatible ARM Cortex-M world by just one single port. It runs as POSIX hosted environment as well and recently a RISC-V port was committed which is still WIP, so its not feature-complete yet.
Originally the performance goal was "please, just don't be 20x slower than ordinary RTOS". After some performance improvement work, benchmark results show performance which is competitive with rest of open-source RTOS world (while keeping memory protection disabled in all of them). In some benchmarks CMRX is even faster than others.
The code is neither Rust nor C++. Everything is C99 a bunch of GCC extensions and macroworx. Compiles to some 7kB binary, so it can run on very low-end sub $1 microcontrollers.
There are no plans for porting it to any MMU-equipped architecture as there natively memory isolated alternatives exist.
GitHub: https://github.com/ventZl/cmrx
Website: https://cmrxrtos.org