Micro Kotlin
In recent years uCs have become much more affordable/accessible. As such this has resulted in more high level languages becoming available to use on various uCs (Microcontrollers). Plenty of room is available for another high level language targeting uCs to fill a void in between the amateur/commercial parts of the uC (Microcontroller) market.
Over the years a number of high level languages have been ported to uCs (Microcontrollers). Many of these languages are subsets of existing languages and use a GC (Garbage Collector). If a language like JavaScript can be ported to a uC via Espurino, then why can’t Kotlin also be ported to a uC as well. Throughout this blog post I will be covering Kotlin on uCs as a purely hypothetical scenario, with a case of Kotlin being successfully ported to a uC as the main exception.
All readers wanting to find out more about the successful Kotlin port will need to read right through to the end. After all there needs to be a juicy tid bit at the end, otherwise the blog post wouldn’t be worth reading.
High Level Languages
If there is one thing that is common to all high level languages that have been successfully ported to uCs, it is that they are all subsets where many language features, and Standard library functionality have been stripped out in order to run on a uC. Some of the major high level languages found on uCs include the following:
MicroPython (based on Python)
- The only high level language with official uC manufacturer support
- Has a sizeable ecosystem (eg lots of electrical hardware drivers/libraries available)
- The most widely used high level language in amateur uC (Microcontroller) projects
- Runs in a VM (Virtual Machine)
- Managed by a community
- Uses a GC (Mark And Sweep) for memory management
TinyGo (based on Go)
- Most resource efficient high level language for uCs
- Generates very small binaries (around 4 KB for a Blinky program)
- Uses a GC (Mark And Sweep) for memory management
- Doesn’t use a VM
- Managed by a community
- Backed by Google
- Uses a LLVM based toolchain
- Most portable high level language for uCs
Embedded Swift (based on Swift)
- Currently the newest high level language ported to uCs
- Uses Reference Counting (a type of GC) for memory management
- Managed by a company (Apple)
- Doesn’t use a VM
- Uses a LLVM based toolchain
.NET nanoFramework (a C# platform for uCs)
- Used in some commercial projects
- Runs in a VM
- Managed by a community
- Uses a GC (Mark And Sweep) for memory management
- A subset of C# is used to develop programs for uCs
Challenges
Porting a high level language to a uC requires removing a lot of stuff (especially at the Standard Library level). Resources on a uC are at a premium where the CPU is weak, RAM is very limited, and internal storage is very low. One cannot go overboard with using a lot of languages features, nor can large software libraries be used without blowing out the binary size.
Memory needs to be managed very carefully. Typical uCs have very little on board RAM, which makes utilizing Stack memory crucial. Especially for a high level language that relies on a GC for memory management. Running the GC for too long or too often will result in a unresponsive program that is too slow to run on a uC.
The Kotlin Native development platform would be the obvious choice to use as a base for developing Kotlin programs that run on uCs. However numerous improvements would need to be made including significant changes to the porting system (e.g. support for Bare Metal targets), improvements to the Mark And Concurrent Sweep GC (e.g. reduce time taken to collect garbage), reduced compilation/static linking times, and good performance benchmarking tools (especially for measuring power usage of a Kotlin program).
Kotlin heavily relies on storing data on the Heap. Many data types use the Heap, especially Strings. Although GC can be disabled it isn’t a practical measure since it is only meant for short lived programs, and for testing purposes. In a uC context the right GC needs to be used to avoid the “stop the world” problem. One should note that there is an option to change the memory allocator that Kotlin Native uses. This can help improve memory performance in certain situations. One way to reduce use of the Heap is to heavily use (abuse) Value classes, which if used properly store data on the Stack. Another way to reduce heap usage is to use ByteArray instead of String.
Code size is another issue that needs to be taken into consideration with a uC. It is guesstimated that the smallest Kotlin binary size (for a Blinky program) would be around 40 KB, which is okish for many newer uC’s although that would require removing a lot of stuff, like useless functionality in the Standard Library for example. Careful choice of libraries used in a uC program also plays a big role, especially when static linking is the standard way to include a library in a program. Since an OS won’t be running on a uC dynamic linking isn’t an option. Even if it were an option the size of the flash (where a program is stored) would be way too small.
Heavily sticking to uC development patterns/best practices (e.g. favour storing data on the Stack rather than the Heap, minimising the use of software libraries), using the right Data structures, and using the right GC (e.g. Mark And Sweep) is the key to keeping RAM usage and code size low.
Having a toolchain based on LLVM, and making significant changes to the build system will be essential to porting Kotlin to many uCs. Kotlin’s porting strategy needs to be based on uC chip targets (eg RP2350) rather than uC board targets (Adafruit Feather RP2350, SparkFun Pro Micro — RP2350 etc). If a uC chip is targeted then most of the hardware functionality is covered (around 88% of the uC board), and many uC boards can be supported without too much work involved provided the same uC chip is used.
Standard Library
In its current form the Common version of the Kotlin Standard library too large in size to be usable on a uC. Luckily there are a few packages that can be easily removed from the Common version.
- kotlin.concurrent
- kotlin.contracts
- kotlin.experimental
- kotlin.js
- kotlin.jvm
- kotlin.native.concurrent
Some packages will likely require significant refactoring in order to be usable.
- kotlin.annotation
- kotlin.io
- kotlin.reflect
- kotlin.text
- kotlin.time
After changes are made to the Common version the following packages will be available:
- kotlin
- kotlin.annotation
- kotlin.collections
- kotlin.comparisons
- kotlin.coroutines
- kotlin.coroutines.cancellation
- kotlin.coroutines.intrinsics
- kotlin.enums
- kotlin.io
- kotlin.io.encoding
- kotlin.math
- kotlin.native
- kotlin.properties
- kotlin.random
- kotlin.ranges
- kotlin.reflect
- kotlin.sequences
- kotlin.text
- kotlin.time
- kotlin.uuid
Overall the most significant changes to the Standard library will involve refactoring key packages (e.g. remove useless functionality), and changing many key APIs to use primitive instead of reference based data types to keep code size/RAM usage low.
Marketing
With a high level language targeting uCs the technical side needs to be covered (85% coverage), however it is important not to neglect the marketing side (15% coverage), which can easily affect the uptake of a high level language. Since a subset of Kotlin is being used on uCs a distinct name needs to be used to indicate a language subset is being used. A perfect name to use for Kotlin on uCs is Micro Kotlin. Even with a good name there needs to be a fitting motto. With Micro Kotlin that would be the following, Connect the physical world!.
No software product can be easily used without good documentation. In order for Micro Kotlin to succeed comprehensive and up to date reference documentation needs to be available, along with getting started articles/tutorials. Having a good video series covering using Micro Kotlin with uCs (incl covering the basics of electronics), called Beginning Electronics With Micro Kotlin would be a great way to learn, that in many ways is much more engaging than going through documentation. Currently no other high level language for uCs provides an official video series.
With that said having some monthly Micro Kotlin webcasts would also be beneficial. On the support side there needs to be a forum and a Slack channel called micro-kotlin, since problems are guaranteed to occur from time to time and there needs to be some official methods to resolve them in a timely manner.
Advantages Of Using Kotlin
Kotlin’s biggest advantage over the other high level languages in the uC space is easy concurrency/parallism via Coroutines, with a tiny resource footprint. This means no RTOS needs to run on a uC to do advanced concurrency/parallelism, which is a huge win. The next biggest advantage of using Kotlin is access to high quality tooling, which more often than not is lacking with many high level languages, including low level languages like C and CPP where many of the tools used are stuck in the 1990's/2000's.
Some of the other advantages of using Kotlin include the following:
- Standard code sharing via KMP (Kotlin Multiplatform)
- Easy to learn the language
- The language can be used on multiple platforms (Linux via Native, WASM, JVM, Android etc)
- Tight platform integration
- Access to C libraries without having to reinvent the wheel (via Kotlin Native’s C Interop system)
- Can utilize an existing uC ecosystem (on the C language side) without having to start from scratch
- A very focused standard library that doesn’t include the kitchen sink
Conclusion
Many people don’t realize that Kotlin was running successfully on a STM32 uC (as a proof of concept) back in 2017. This occurred long before Swift was ported to uCs. Below is a quote from Nikolay Igotti (on Kotlin Slack):
Last year we did student project which was running subset of Kotlin on STM32 microcontroller
I would wager that the chance of Kotlin being announced for uCs at 2025’s Kotlin Conf is around 8%. Since Kotlin has been successfully ported to a uC the lingering question remains. When will there be an official port of Kotlin (as a subset called Micro Kotlin) to uCs? Only the Kotlin team know the answer to that question.