5 ms·
I just spent the last two weeks choosing an embedded ui framework and then building out a little demo to test out its capabilities. I settled on Slint and have
by davidhyde 3y ago
I just spent the last two weeks choosing an embedded ui framework and then building out a little demo to test out its capabilities. I settled on Slint and have been very impressed with the design of the domain specific language they came up with. It’s small, simple, powerful and easy to learn IMO. The vs code extension for real time gui feedback is amazing. I’ve used swift ui before and Slint is as much of a joy to use. This is a breath of fresh air compared to Microsoft’s Windows Presentation Foundation that took me years to master.
My only concern is optimising for binary size. My little microcontroller only has a measly 1MB of flash storage and I’m already at 900kb on a 15 screen app with no icons or images. It would be nice to know what actually uses up all that space (as little as it is). Perhaps I need to use ui element virtualisation or something.
Edit: 1kb of flash -> 1MB of flash
- nicce 3y agoOut of curiosity, 1kb of flash storage sounds quite tiny for a chip which is expected to provide GUI capabilities. Can you provide more information about the context?
- davidhyde 3y agoTypo, I meant 1MB. The actual specs are 1MB flash, 564KB sram and around 500Mhz mcu speed. I’m using the STM32H735G-DK development board which comes with a few bits extra to drive a 4.2” lcd screen directly. There are already demos for it in the Slint repo which is why I chose that hardware in particular.
- ogoffart 3y agoThank you for your comment and feedback! I'm glad to hear that you have chosen Slint for your embedded UI framework and have been impressed with its design and ease of use. Feel free to post on Github for issues or discussions. I assume you meant 1Mb of flash and not 1kb of total flash :-) We might find some way to optimize the generated code to reduce the binary size further.
- davidhyde 3y agoYes, I meant 1MB, typo! Thanks I’ll engage on GitHub. :)
- MallocVoidstar 3y agoI assume you're already doing this since you're on a microcontroller, but have you set [profile.release] codegen-units = 1 lto = true
- samstave 3y agoELI5 what this does?
- hyperbrainer 3y agoThe lto setting controls the -C lto flag which controls LLVM’s link time optimizations. LTO can produce better optimized code, using whole-program analysis, at the cost of longer linking time. The valid options are: false: Performs “thin local LTO” which performs “thin” LTO on the local crate only across its codegen units. No LTO is performed if codegen units is 1 or opt-level is 0. true or "fat": Performs “fat” LTO which attempts to perform optimizations across all crates within the dependency graph. "thin": Performs “thin” LTO. This is similar to “fat”, but takes substantially less time to run while still achieving performance gains similar to “fat”. "off": Disables LTO. Basically, increases performance at cost of compile time. Great for release builds, not so much for debug builds (because most of the time that rustc spends is on linking anyways.)
- MallocVoidstar 3y agoAlso, codegen-units = 1 disables some compiler parallelization which means it can find more optimizations, including for size: https://nnethercote.github.io/perf-book/build-configuration.html#codegen-units https://nnethercote.github.io/perf-book/build-configuration....
- bombela 3y agoThis is what I found to reduce code size the most for the 8bit AVR MCU: [profile.release] opt-level = "z" lto = true overflow-checks = false codegen-units = 1 debug = false Also invoking cargo with: cargo build --release -Z build-std=core -Z build-std-features=panic_immediate_abort You must then implement panic handling yourself: pub mod std { #[lang = "eh_personality"] #[no_mangle] pub unsafe extern "C" fn rust_eh_personality() -> () {} // panic can be replaced by abort with the panic_immediate_abort feature. // -Z build-std-features=panic_immediate_abort // This saves space by getting rid of the unwinding. #[panic_handler] pub unsafe fn panic_impl(_info: &::core::panic::PanicInfo) -> ! { loop {} } #[no_mangle] pub unsafe extern "C" fn abort() { // blink led loop {} } } If I still have some room in the flash, I will make some led blink with a noticable pattern on abort. You can also experiment with the inlining threshold: export RUSTFLAGS+=-C inline-threshold=0
- ilyt 3y agoI wish that there was some GUI lib dedicated to small embedded systems, I just want to draw some buttons and sliders without eating hundreds of flash/ram...
- deleted 3y ago[deleted]
- peelz 3y agoHave you looked into fltk-rs?
- ilyt 3y agolooking at required dependencies it couldn't even run on the microcontroller
- ogoffart 3y agoThis was our aim with Slint
- varjag 3y agoSome popular embedded display controllers have commands to draw primitives.
- ilyt 3y agoI'm essentially looking for something like imgui but with ability to draw directly to framebuffer. I looked at egui but that has same issue.
- jrylnd 3y agoImgui doesn’t write to a framebuffer, it records GPU commands. Really embedded MCUs don’t have space for a framebuffer either, a technique used is filling a line buffer on a timer interrupt and driving the lcd off that. The gui has to be written quite differently.