Embedded GUI Development

Nick Apperley
5 min readJan 25, 2022

Kotlin is used in various areas of GUI development, but hasn’t been used for Embedded GUI development. This type of development sets itself apart from other areas with an emphasis on performance with a small footprint on resource constrained hardware without dedicated graphics hardware and limited RAM, no Windowing System and Window Manager is run on the hardware, the application uses the entire screen, and either SBC’s (Single Board Computers) or uC’s (Microcontrollers) are used as base hardware with MicroSD or eMMC for internal storage. With SBC’s Embedded Linux is usually used in an environment with direct access to the Frame Buffer (no Windowing System is run). Two classic examples of resource constrained hardware are the Raspberry Pi, and the Beaglebone Black.

Software Landscape

A limited number of software libraries are available that cover Embedded GUI development where most of them are written in C (not C++). It is very common for these libraries to only cover the graphics side, leaving extra work to be done by a Software Developer to cover the UI side. There are some exceptions to this with QT Embedded, and LVGL for example. On the Kotlin side there are no libraries/frameworks that cover Embedded GUI development. Although there are some libraries/frameworks that cover cross platform GUI development like JetBrains Compose, and TornadoFX for example, but these libraries/frameworks mainly cover desktop applications.

Some people might think the JetBrains Compose covers Embedded GUI development. However the framework requires the target hardware to run a Windowing System along with a Window Manager, doesn’t include a reasonable range of widgets (controls), has a high RAM footprint (around 150 MB for a Hello World app), and requires using a VM which comes with some significant overhead (eg large sized JAR files).

LVGL

Out of all the software libraries/frameworks covering Embedded GUI development LVGL emerges as one of the best options. Originally designed for uC’s the library supports a range of different platforms including Embedded Linux with the Linux Frame Buffer and SDL2 display backends. The modular nature of LVGL means the library can be fine tuned to only include functionality that is used at the application level. Most of the library configuration is currently done with two header files, lv_conf.h and lv_drv_conf.h. Some library configuration is done through the LVGL API. Do note there are some future plans for simplified library configuration, where header files aren’t required for configuration on some target platforms.

One of the biggest strengths of LVGL is the fact that most things are an Object (including widgets), which has the following builtin:

  • Basic attributes (position, parent, size etc)
  • Local styling
  • Standard event handling
  • Individual parts that can be styled separately
  • Basic lifecycle

Documentation of the library is another highlight of using LVGL with the reference documentation being very high quality and often has interactive examples, which one doesn’t normally expect from reference documentation. Especially with a C library which is rare. Reference documentation can be filtered by library version, and there is decent search functionality which adheres to the library version filter. Code samples exist for the Raspberry Pi, and there is even a blog post that covers the Embedded Linux platform although it is out of date.

User interface support is available with LVGL supporting a range of widgets, including one for doing charts. Multiple displays are supported, and a range of display/input devices (including display backends) are supported by the LV Drivers library that LVGL depends on. Styling is very easy to do in an application which can either be applied at the Object level or done as a separate style. Even theming is supported with LVGL including a default flat theme called Material.

Kotlin

To cover Embedded GUI development with Kotlin there is a library under development called LVGL KT (not published yet), which provides Kotlin bindings to the LVGL library and supports Kotlin Native (via the linuxArm32Hfp target). Unfortunately Kotlin doesn’t support uC’s (which is a pity) so there isn’t the possibility of supporting some uC platforms in the future with LVGL KT, although that would make sense given LVGL already supports some uC platforms with its uC development roots.

Even though LVGL KT is in the early stages it can be used to develop a Hello World type application, which looks similar to the Styling Buttons example. Below is an example of a Hello World type application using LVGL KT:

Kotlin code sample using LVGL KT

A Hello World application using LVGL KT (utilising the new Kotlin Native memory model) is very quick to start up, has low RAM usage (around 3.3 MB reserved RAM), low CPU usage (around 0.7%), and a small binary size (around 1.3 MB; the LVGL and LV Drivers libraries are statically linked). Performance is one of the key advantages of using the library without having to throw away developer productivity in the process. LVGL KT is designed to strike a balance between performance and developer productivity. If Kotlin supported uC’s then the code would be reasonably portable between uC’s, and a significant proportion of the code would be shareable across multiple uC’s and non uC platforms (eg Embedded Linux).

Implementing the equivalent application in C would take much longer and be far more verbose (less readable). Although the application would have much better performance it would come at a huge cost to developer productivity, and dealing with worse developer tooling.

Some of the key design goals with LVGL KT are the following:

  • Easy interop with the LVGL, and LV Drivers libraries to cover API gaps, and allow performance critical code to be handled directly by LVGL if needed
  • Keep RAM overhead and binary size low (with a statically linked binary) without compromising developer productivity
  • Provide declarative API’s for some key API’s (styling, objects etc) to boost developer productivity
  • Remove unnecessary boilerplate/ceremony with setting up an Embedded GUI application

Conclusion

Embedded GUI development shouldn’t be overlooked as an important software development area, which in itself is large business with the Embedded Linux and uC platforms. Having Kotlin (via Kotlin Native) combined with LVGL and LVGL KT allows Kotliners to access the Embedded GUI development area with Embedded Linux, and SBC hardware. Not all GUI development will be Web or mobile based, and in many cases it is important to cover all major bases by including Embedded platforms (especially ones that are Embedded Linux based).

--

--