Nim has been great for use on the ESP32's and I've implemented a few different projects this way. However, the ESP32's are pretty limited in their selection and only a fraction of the overall microcontroller / MCU market. FreeRTOS as a target is also pretty limited as it really doesn't provide much in the way of cross-hardware / brand support. Each manufacturer has their own build system, IDE, SDK's, etc.
As such I'm contemplating porting Nim to Zephyr RTOS and also wrapping the Arm hardware API. Most newer microcontrollers nowadays are Arm Cortex chips. So a good target for supporting a lot of hardware would be wrapping Arm's hardware API called CMSIS which would be provide baseline support for many Arm Cortex chips. Each family of Cortex M0, M4, etc all have different subsets or additions, AFAICT, but likely could live in a single Nim library. Cortex A's (like the RPi's) may or may not fit in the same library. If anyone is familiar with CMSIS Cortex A/M differences it'd be great to get some advice on this!
Wrapping Arm's CMSIS and the Zephyr RTOS would be separate projects libraries as they could be very useful independently. However, together they'd enable a very capable embedded environment for use with Nim. I've yet to write any code for this, however, the general approach would be:
Generally I'm also considering Zephyr RTOS as a good base as well. FreeRTOS is probably more common but really doesn't share standard components across microcontroller's (aside from Amazon's newer libraries for networking). In theory Nim could be better suited to write many OS libraries in (like a FAT32 driver) it would essentially be duplicating much of the effort being put into Zephyr by several MCU manufacturers. I suspect Nim could get more adoption in the field if it wraps a well supported RTOS with drivers and a single build system for multiple MCU families and brands.
It'd be great if anyone on here would like to help and be part of this. Perhaps even creating a GitHub organization specifically for embedded programming with Nim! If anyone is interested in helping port to the NXP M33 based chips I'd be willing to donate a few boards to people as well. :-)
Anyone interested?
I'm interested in this project.
I've been thinking of porting NuttX and littleVGL to Nim; but Zephyr is also on my radar.
I think a github org is the easier way to organize.
Great!
@Araq Even a bit of help reviewing wrapping various API's would be handy. There's still lots of Nim where I'm not sure of the idiomatic or best ways to do things.
@Clonk Choosing the RTOS is tricky... NuttX seems like it could be a good choice as well. I've actually never used either NuttX or Zephyr but was leaning toward Zephyr as it appeared to be winning mindshare and has gained official support from a couple of different micro-controller manufacturers.
@Araq any thoughts about a EmbeddedNim Github organization? Not sure if it's too soon for that but it'd be nice to have a single place to put similar projects.
I think a github organization is easier to work collaboratively. We have SciNim for scientific computing. Why not have EmbeddedNim ?
What would be cool is a bridge between Matrix and the Embedded channel on Discord as well
I'm also interested in this! The 2 recent talks at nimconf on embedded applications were really interesting.
I also agree that NXP would be a good first target, if only because of teensy v4.1, which is currently one of the best values for these sorts of dev boards and also readily available and accessible for hobbyists.
Personally I don't think porting Nim to an RTOS is necessary, at least not as a first step. Just wrapping CMSIS and getting good support for cross compiling etc would enable a lot of applications. Nim being a powerful yet friendly and fast language would be a great fit besides Arduino/C++ and micropython.
I also agree that NXP would be a good first target, if only because of teensy v4.1, which is currently one of the best values for these sorts of dev boards and also readily available and accessible for hobbyists.
Great point, the Teensy 4.1 would be a great target. It's popular and uses NXP chips. Now if only I can find any to purchase! The last I tried they were sold out.
Personally I don't think porting Nim to an RTOS is necessary, at least not as a first step. Just wrapping CMSIS and getting good support for cross compiling etc would enable a lot of applications.
This approach works best with a specific target like the Teensy 4.1 where you can make use of boards developers toolchain and documentation.
Setting up a new board consists of a fair bit of tedious work:
For the Teensy 4.1 has most of these details worked out by PJRC. It would valuable to setup Nim for many of these developer board chips though. Especially popular chips like the Teensy 4.1's or the RPi RP2040 which have broad community support.
For my use cases however, I find porting Nim to a RTOS much less tedious and less work than figuring out those details for various boards. It's the route I'll probably take as it provides more value for my employer long term. Zephyr in particular wraps the cross compilers, flashers, board init code for around a 100 different boards along with QEMU emulators! That means once it's up and running you gain a lot of flexibility in using a wide range of MCU's like the RISC-V ones, NXP, or TI, and more.
Though the RTOS is easier for me since I also know many of the tricks of porting Nim stdlib to an OS, and Zephyr appears to provide a lot of POSIX compliant API's so it should be pretty easy for me to get up and running (:fingers-crossed:).
The RTOS approach has a few downsides too. It means that it means the Nim code is reliant on an underlying C codebase with it's own potential flaws. The ESP-IDF FreeRTOS implementation has been somewhat of a headache for me. The driver's are buggy, the malloc and printf's have race conditions, etc. Also RTOS'es incur a bit of extra overhead.
I hopeful Zephyr will provide a much more stable and well tested RTOS option though. They really are emphasizing more modern software testing like integration testing, etc.
Just wrapping CMSIS and getting good support for cross compiling etc would enable a lot of applications.
This would be a very useful project in itself. The RTOS route is one I like, but wrapping CMSIS directly would provide Nim with a lot of power for programming ARM chips, including the Arm SoC's. This means Nim could be used to program firmware for everything from the Raspberry Pi 4 to the PineBook Pro down to a huge swath of embedded MCU's. This would make it easier to do things like bit-bang raspberry pi hardware to interface with non-standard hardware like string LEDs, or fast GPIOs, or a bunch of things. That'd be really fun. :-)
Though I'm not to clear on the details of CMSIS. It seems like it'd be possible to write pure Nim code but that'd take some bit of work. It seems the embedded Rust projects are taking this approach. It might be possible to copy their implementations and/or approaches?
Ideally, an EmbeddedNim umbrella organization could help support both wrapping CMSIS directly, and also wrapping Zephyr and other RTOS'es.
Would you be interested in moving the CMSIS library to EmbeddedNim? We can keep it somewhat updated there, and perhaps inspire others to contribute.
Definitely!
I think I need permissions to create repositories in nim-embedded in order to do the transfer however? Or just let me know if there's another way.
Personally, I don't like this approach.
My preferred way is:
Hi. That's what I was recently trying to do.
I made a static lib in Nim and tried to link it with ESP32's ESP-IDF as a component. However it was not full-on success. I managed to compile and link it together, but float and double (int worked) operations were not behaving correctly - I tested the same program compiled for Linux and it was ok.
I suspect it has to do something with compiler / linker flags not matching. @elcritch 's Nesper and it's generated C files seem to compile alongside ESP-IDF, so GCC is set up right.
This is my nim.cfg file:
--gcc.path:"/home/ado/.espressif/tools/xtensa-esp32-elf/esp-2021r1-8.4.0/xtensa-esp32-elf/bin"
--gcc.exe:"xtensa-esp32-elf-gcc"
--gcc.linkerexe:"xtensa-esp32-elf-gcc"
--passC:"-mlongcalls" # Without this I get "dangerous relocation: call8: call target out of range"
# it is used in xtensa's CPUs
--cpu:esp
--os:freertos
--gc:orc
-d:nimAdaptiveOrc
-d:use_malloc
-d:no_signal_handler
--debugger:native
--tls_emulation:off
--app:staticLib
--noMain
--header
--nimcache:"nimcache"
-o:"lib/libnim.a"
-f
Somebody any idea? If it's not the compiler flags then maybe it could be xtensa gcc using glibc instead of newlib (I didn't specify this), but that's just a wild (and probably wrong) guess...
Somebody any idea? If it's not the compiler flags then maybe it could be xtensa gcc using glibc instead of newlib (I didn't specify this), but that's just a wild (and probably wrong) guess...
That'd seem a good guess. Mixing C libraries doesn't usually go too well. Though there may be some other tweaks. Nesper has a list of extra compile flags that were needed to get the Nim generated C code compiling that might help you.
Setting all of that up is why Nesper compiles Nim to C and then uses esp-idf's CMake build. Everything works nicely, and there's also the linker offsets if you want to setup the bootloader.
I've been thinking of porting NuttX and littleVGL to Nim; but Zephyr is also on my radar.
littleVGL would be really useful! I've not used NuttX but let me know if you'd like to include it in EmbeddedNim.