5 ms·
Nim on a Real-Time Operating System: Apache NuttX RTOS and Ox64 BL808 SBC
- elcritch 3y agoNice write up! Note Nim can also run FreeRTOS and Zephyr with networking support. It can also run on Arduino or the Pi Pico.
- lupyuen 3y agoThanks! Yep we should do more Nim programming on microcontrollers, since they have lots more RAM nowadays.
- brabel 3y agoNim uses the ORC "GC" by default, which is Reference-Count with cycle detection. I don't get why calling the GC explicitly is needed in your examples given RC will drop memory as soon as it goes out of scope (and there are no other aliases to it). Perhaps the "cycle detection" happens at indeterminate times? But can't you use the simple RC GC in such cases? That should also ensure you don't use more memory than C at all?!
- lupyuen 3y agoThanks for the tip! I'll check with the folks who added Nim support to NuttX, and figure out whether we should call GC_runOrc()
- auxym 3y agoFor all embedded purposes, I'd strongly recommend sticking with `--mm:arc` and avoiding cyclical data structures (can't see much of a use for that anyways). With ARC, you don't need to "run" any runtime GC. ARC is a fully static thing, the reference-counting happens at compile time (static analysis) and the compiler injects (the equivalent of) malloc() and free() calls in the compiled code based on that. It's great for embedded IMO. You get the performance of manual memory management with the convenience of GC. The only thing to be wary of is that it "hides" a bit when allocation happens. On embedded, you often want to minimize dynamically allocated memory for performance and heap fragmentation reasons, though the latter should be less of an issue with 64 mb of RAM. In nim, you just have to remember that creatin a string, a seq or a `ref object` allocates. So you want to eg. avoid creating and destroying a string repetitively in a loop. Instead create a `var` (allocate a buffer) once, outside the loop, and modify it as needed in the iterations. Everything else in nim (including plain objects, which map to regular C structs) is stack allocated, so ARC doesn't get involved at all. Further reading: https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc-in-nim.html https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc... https://nim-lang.org/docs/mm.html https://nim-lang.org/docs/mm.html https://nim-lang.org/docs/destructors.html https://nim-lang.org/docs/destructors.html https://nim-lang.org/docs/nimc.html#nim-for-embedded-systems https://nim-lang.org/docs/nimc.html#nim-for-embedded-systems
- elcritch 3y agoIn my experiments 64+ kB of RAM works pretty with Nina allocator. It’s also a O(1) allocator. Still limiting allocations is important on embedded.
- mratsim 3y agoThe default is ARC, no cycle detection. ARC is deterministic. ORC isn't, but doing cycles in general is usually a code smell, especially on embedded. Also the GC is type-bound and only needed if you use ref objects. If you don't, no GC.
- brabel 3y ago> The default is ARC, no cycle detection. How long haven't you checked that for? It's been ORC for years. Try this with a recent nim version: nim --fullhelp -mm:orc|arc|refc|markAndSweep|boehm|go|none|regions select which memory management to use; default is 'orc' When you confidently try to correct someone, at least consider you may be wrong.
- mratsim 3y ago> How long haven't you checked that for? Orc was blocked for a while due to cycles with async. I was under the impression that they were still there. > It's been ORC for years. The switch has been made for Nim v2 announced in December 2022, the PR #19972 that defaults to ORC has been made on September 2023. ORC has just celebrated 1 year as default GC, certainly not years. > When you confidently try to correct someone, at least consider you may be wrong. I don't get why you're so butthurt about this and feel the need to be so nasty in your replies.
- brabel 3y agoTelling you that you're factually wrong (which you could easily check yourself in 1 minute) and that you should not jump to correct people on the Internet, propagating wrong information without considering they may actually be right, does not amount to being nasty.
- mratsim 3y agoYour tone is nasty
- warangal 3y agoJust wanted to say thanks for this and all other such detailed posts!. Found your blog a few weeks ago and have been going through posts running NuttX RTOS on these SBCs, but admittedly feel overwhelmed with sheer amount of information packed together !
- lupyuen 3y agoThank you so much! 2024 will be an awesome year for 64-bit RISC-V Gadgets (like Ox64), I'll write lots more :-)
- deleted 3y ago[deleted]
- MarcusE1W 3y agoGreat write up and a good opportunity to get the Ox64 out of his box and try to make a few lights blinky blinky. It’s one of the unexpected joys in IT to take a microcontroller, add a few cable, all per detailed instruction for beginners and then yes the light goes blink, as per instructions . At yet it makes you happy ;-)
- eterps 3y agoI often have GPT-4 translate C code fragments into Nim for me because I find Nim’s readability enhances clarity, allowing me to catch more details in a shorter amount of time. But I'm aware that this is probably a personal preference thing.
- elcritch 3y agoI did a bunch of PRs last year on c2nim, which can parse and translate most C code now. The hardest was handling C function pointers that take function pointers. The C for those is hard to parse and easy to second guess, but Nim makes it a breeze.
- jqpabc123 3y agoSo why 64 bit for embedded when the address space or math capability of 64 bit registers is rarely needed or used?
- irdc 3y agoI’m speculating here, but isn’t the fact that you can just run the exact same binary everywhere an advantage? Makes testing a lot easier. And these devices are (currently) too low-power for emulated code to thrive.
- jqpabc123 3y agoI’m speculating here, but isn’t the fact that you can just run the exact same binary everywhere an advantage? "Embedded" typically means specialized hardware and code. "Running the same binary everywhere" is generally not a practical consideration with specialized hardware. Typical concerns I associate with "embedded" are minimizing production cost and maximizing efficiency in order to try and achieve a marketplace cost advantage. It is not clear how 64bit will help in this regard.
- flohofwoe 3y ago64-bit registers can be very useful for bit twiddling code (for instance my home computer emulators depend on 64-bit integers for efficiently manipulating and passing chip in/out pins around). 64-bit pointers on the other hand are overkill, but so are 32-bit pointers for most applications ;)
- jqpabc123 3y agobut so are 32-bit pointers for most applications The address space of 16 bit pointers is only 64KB so I can understand 32 bit for pointers as well as math use in some cases. But the need to exceed a 4 GB/32bit address space for "embedded" is extremely rare at this time..