official software project ? (Rust for IOT ?) - Printable Version +- PINE64 (https://forum.pine64.org) +-- Forum: PineTime (https://forum.pine64.org/forumdisplay.php?fid=134) +--- Forum: Development Discussion on PineTime (https://forum.pine64.org/forumdisplay.php?fid=136) +--- Thread: official software project ? (Rust for IOT ?) (/showthread.php?tid=8375) |
official software project ? (Rust for IOT ?) - abdel - 11-19-2019 Hi I don't have yet my dev kit, but I have just started to check for the current status. Am I wrong if I say that there is no official project for now and people are testing things/setting up their dev setup on their side ? Look like the most advanced project is Lup Yuen Lee's rust project (https://twitter.com/MisterTechBlog), but he seems to not use this forum. So maybe this project is kind of official ? I was first very surprised to see he is working in rust language. I always thought that rust is a very good language but not for IOT because of the code size and lack of full control. (just compare a hello world in rust and C (in release mode) and check the code size). After few research I saw that this big size come from libraries that are statically linked. In barre metal we dont use external library like libstd, so we are fine. But I then dont have an answer to my question: is rust code bigger than C ? If yes is it acceptable ? I have nothing against rust, it can be an opportunity to learn (I like the philosophy behind rust, and I have planed to learn it in the future), but when doing IOT stuff it's better to have full control on what we are doing. And in C you can understand what is happening in low level (assembly code). I suppose I wont be able to do that in rust. Also in C you have full control of the FW size and of your structure. Is it also the case in rust ? I read in the net that Rust references can be fat ... One argument of Lup Yuen Lee to use rust is that, rust protect us on memory corruption. But on very small system it's better to avoid use of heap (malloc/free). You dont need that. And you may even end up by fragmenting your few RAM because of different size object allocation. And in rust if you use things like map or vector, are you then indireclty use the heap ? If yes, is there any issue on RAM fragmentation ? One more thing: There is 512KB of ROM. In case of FW update which I suppose has to be done via bluetooth., where can we save the blob we receive ? We may have to split in 2 the ROM, right ? If it's the case then the FW code has to fit in 256 KB (less if we count the bootstrap). Is the rust code able to fit ? Or maybe you prefer to have a smart bootloader with DFU and bluetooth inside the bootloader ? Again I have nothing against rust, and will be happy to learn it sooner that I was expecting, but then I would like to know if someone is comfortable enough to handle this kind of issue ? RE: official software project ? (Rust for IOT ?) - pfeerick - 11-19-2019 I have this feeling from looking at the video of the code Lup Yuen Lee was demoing that it ended up around the 165k mark... so not insignificant... but considering it was a RTOS plus Rust, display drivers, touch drivers, who knows what else plus it was a debug build, not a release build, and it's still early days... so there is plenty of room for improvement. If I have to learn Rust to program the thing, so be it... my preference being C++. RE: official software project ? (Rust for IOT ?) - abdel - 11-19-2019 Ok, so it sould be ok then. I will investigate more when I will have my device RE: official software project ? (Rust for IOT ?) - lupyuen - 11-20-2019 Hi All: I'm here (the writer of that long PineTime article), so glad the forum is still alive :-) Here's the build size as of today, which includes the Rust driver touch controller... Code: + newt size -v nrf52_my_sensor Current ROM size is 189 KB, that's less than half of the 512 KB total available ROM. What's taking up the ROM? libs_rust_app.a (56 KB): This is the Rust application + third-party (non-system) Rust libraries, including the Embedded Graphics library. The large size is probably due to the font embedded in the library. nimble_host.a (44 KB): This is the NimBLE Bluetooth Stack host code that runs the Bluetooth iBeacon logic. (Similar to Nordic SoftDevice) nimble_controller.a (35 KB): This is the NimBLE Bluetooth Driver code for the nRF52 2.4 GHz transceiver. (Similar to Nordic SoftDevice) libs_rust_libcore.a (13 KB): This is the Rust Core Library. System functions needed by Rust. Similar to stdlib and stdio. Rest of the code is from the Mynewt OS, written in C. So right now the Bluetooth Stack (written in C) is actually a little bigger than the combined Rust code. And the Rust code is bloated really because of the graphical UI. In any case, we still got plenty of ROM space to use. I think eventually we should offload the font data to the SPI Flash memory (8 MB) About the Bootloader and Doing Direct Firmware Upgrade (DFU) via Bluetooth... I'm now using a Stub Bootloader. It doesn't do anything, it just jumps to the Application Code. The proper bootloader to use is MCUboot (also used in Zephyr OS). It supports swapping of Application Code Images and can rollback in case of problems. Which means we need to store 2 copies of the Application Code: Old (before upgrade) and New (after upgrade). How shall we fit 2 copies of Application Code into 512 KB ROM? We could offload the font data and other graphical assets into the SPI Flash (8 MB). Any user-developed Watch Apps that run on top of the system Rust Application could also be offloaded to the SPI Flash. Or we could store both copies of Application Code into the SPI Flash. Which means the bootloader will need to overwrite the ROM by SPI Flash during upgrades and rollback. More work for the bootloader. Or we could upgrade PineTime from nRF32832 to nRF52840 to double the ROM size (1 MB!). This makes PineTime more expensive of course. Application Code Images are digitally signed to ensure they are authentic, so it's possible to receive Application Code updates via Bluetooth. About the Assembly Code generated by the Rust Compiler... The Rust Compiler generates Assembly Code that's surprisingly readable, almost like C! (I browse the Assembly Code sometimes to check for performance issues) Check this out... https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/pinetime/logs/libapp-demangle.S#L2143-L3018 This Assembly Code corresponds to this Rust code for rendering the UI... https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/pinetime/rust/app/src/display.rs#L44-L145 That disassembly was generated by "objdump" from the compiled Rust ".o" files. The Rust Compiler generates machine code that's as clean as the C Compiler, no function prologues and epilogues. This is the same machine code that goes into the actual PineTime Firmware. Here's the "objdump" disassembly of the PineTime nRF52 Firmware, look at lines 22030 to 22872... https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/pinetime/logs/my_sensor_app.elf.lst#L22030-L22827 Another example: Here's an Interrupt Handler written in Rust: https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/pinetime/rust/app/src/touch_sensor.rs#L72-L80 And here's the "objdump" disassembly of the compiled ".o" file: https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/pinetime/logs/libapp-demangle.S#L861-L899 About Static vs Dynamic Memory Allocation... I'm also a stubborn believer that all memory in embedded devices should be Statically Allocated, budgeted way in advance. (And if we didn't budget enough, it's our fault!) The Rust code I have written is based on the "[no_std]" convention: No heap, no dynamic memory allocation ("Box"), no standard library for String() support (which uses heap). Which causes some pain because some Rust libraries insist on using the "[std]" convention with heap support. So you see this weird code below for formatting numbers as strings... The write!() macro insists on using a heap-based string for storing the formatted output. Thus we fake it by passing an "arrayvec::ArrayString", which comes from an external library that uses a fixed-size array ("buf_x") to simulate a heap-based string... From https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/pinetime/rust/app/src/display.rs#L98-L123 Code: /// Display the touched (X, Y) coordinates RE: official software project ? (Rust for IOT ?) - pfeerick - 11-20-2019 Hi there, writer of that long article! Love your work, look forward to seeing more of your exploration of the PineTime... means I can learn more about them while I wait for GA of the Dev kits. The breakdown of FLASH memory usage... looks quite reasonable, considering the current state of development. And as you said, there's still that SPI Flash that assets such as fonts, graphics, even apps, can be offloaded to. The MCUboot mechanism sounds very much like the eboot one used on the ESP8266/ESP32... i.e. allowing OTA updates via multiple application slots. Anyway, nice to see you on the forum! RE: official software project ? (Rust for IOT ?) - Luke - 11-20-2019 @lupyuen Welcome to the forums amazing work RE: official software project ? (Rust for IOT ?) - lupyuen - 11-20-2019 Thanks everyone for the warm welcome! I think there's plenty of room for all kinds of PineTime environments: C, TinyGo, MicroPython, Rust, ... Most important thing is that we share our porting experiences so that we may all learn! Now I know that Rust can be intimidating. (Some members of the Rust Community weren't exactly as welcoming as the folks here.) But I feel that Rust is great for practical embedded development. I don't believe in 100% pure functional programming in Rust (because that's unrealistic). And I don't believe in piling on so many Type Abstractions that make Embedded Rust impossible to learn. Like I always tell my IoT students... Don't be afraid to challenge me on anything that I say So feel free to ask me anything... And suggest how I can make things better. BTW just call me Lup |