Our PineTime Application Firmware bundles the Watch App together with the operating system (Mynewt OS). If PineTime were a real consumer gadget like an Android phone, we would expect the Watch App to be flashed separately from the operating system.
How can we unbundle Watch Apps from Mynewt OS on PineTime?
This can be done in the Rust Wrappers for Mynewt OS. Right now we auto-generate Rust Wrappers for every Mynewt OS API, via a bindgen
script and a Rust Procedural Macro safe_wrap
.
Rust Wrappers are needed so that our Rust Application and Driver Code may safely call Mynewt OS functions (written in C). More details here
We can modify the Rust Wrappers so that they can be split across two firmware images: Watch App Firmware and OS Firmware.
When the Rust Wrappers are called in the Watch App Firmware, they will dispatch the call to the Rust Wrappers in the OS Firmware.
When the Rust Wrappers are called in the OS Firmware, they will be dispatched locally.
Thus we implement something like a Kernel Space / User Space boundary that's found in Unix operating systems.
The addresses of each Mynewt OS function will be found in the Dispatch Table, which is generated by the Rust Procedural Macro during Rust Wrapper generation.
When a Watch App calls an OS function (like spi_open()
), the Rust Wrapper will lookup this Dispatch Table to obtain the OS firmware address of that function, by calling get_dispatch_address()
.
To support multitasking, we will reserve 4 slots in ROM and RAM for running 4 Watch Apps concurrently. Each Watch App will be compiled 4 times, based on the ROM and RAM addresses of each of the 4 slots.