Lilota (Little Interpreted Language Over The Air) is an operating system for microcontrollers including the ESP32, ESP8266, and Raspberry Pi Pico boards. Its goal is to provide an easy-to-use scripting interface, the Tcl language , allowing users to program IoT devices.
During the 2026 Simons Summer Research Program, I expanded support dynamic module building and loading for Lilota. This allows individual features to be stored as .elf module files, reducing the size of the core Lilota binary. Each module can also be individually added and updated to a system, improving flexibility.
Abstract#
Lilota is an embedded firmware platform for resource-constrained microcontrollers. Embedded firmware is traditionally built as one statically linked image with every available module and its dependencies. This increases core firmware size even when a device does not need many included features. This project extends Lilota’s dynamic module implementation for the ESP32, where module code executes directly from flash through execute-in-place (XIP). As flash-mapped code is read-only at runtime, address loads and calls cannot be patched after a module is loaded. Each module and its source-level dependencies, such as ESP-IDF driver code, are linked into one ELF file. Dependencies on other modules are declared and loaded at runtime. During the build, the rewriter parses generated assembly, assigns entries in a Global Offset Table (GOT), and rewrites address loads and external calls to use GOT lookups. To access this writable GOT from XIP code, the rewritten module first reads a fixed table using its module ID. The table entry points to the module’s GOT in memory, which contains symbol addresses. Executable text and read-only data are placed in flash-mapped segments, while the GOT, initialized data, and BSS use RAM. At runtime, the loader maps the module, allocates RAM, loads declared dependencies, resolves kernel and module symbols to populate the GOT, and invokes the module entrypoint. On an ESP32, the present dynamic-module configuration, which includes the GPIO, RF, and DHT11 modules, reduced the statically linked core by 33.2 KiB from 1182.6 KiB to 1149.4 KiB (a 2.8% reduction).
