Hey all! I'm experimenting with an OS port for FreeRTOS, similar to that for the Nintendo Switch. Currently I'm focusing on the esp-idf (esp32) which includes LwIP. Essentially so far it's posix.nim with all the non-FreeRTOS parts removed (probably 80% of it). Importantly, there's a couple of core IP addr structs that differ due to LwIP. My main goal is getting net module (esp select for sockets) working with async. It'd be fun to have a Nim async-http server "just work" on FreeRTOS/LwIP devices.
Would anyone else be interested in helping with such a project? Given Amazon's acquisition and re-licensing of FreeRTOS, it has given it a bit of a market boost. It appears to be a (the?) market leader, but it lacks a number of POSIX standards. Still a surprising amount of the standard libs works despite that. Currently I'm not sure how/if the net libraries for interfaces can be handled.
The branch can be found here: https://github.com/elcritch/Nim/tree/freertos
I've made a bit more progress. I've got an example esp32 Ethernet server to compile.
But ran into something that's not quite clear:
proc newSelectEvent*(): SelectEvent =
var fds: array[2, cint]
if posix.pipe(fds) != 0:
raiseIOSelectorsError(osLastError())
...
There are no pipe's on FreeRTOS/ESP32 so I excluded them. It seems this just provides custom user event's and doesn't seem necessary.
This is great! ESP32 is a nice platform; I've used it a bit in the past, with C++. It'd be good to have Nim running on it.
I don't have the time to contribute right now; just offering moral support and thumbs-up 👍🏻
@araq, that's great! I was hoping to do a PR, but wasn't sure if there would be interest. It seems, LwIP and FreeRTOS support could be split. Most of what I've done is actually port Nim sockets to LwIP. That'd mean it'd be easy to combine Nim & LwIP on many embedded devices.
Once I get networking tested I'll create a PR. Would appreciate a code review! There are lots of areas of Nim & FreeRTOS I'm not familiar with. Not really sure how to do the CI, but it'd be great. There is QEMU support for the ESP32.
Got an example asynchttpserver running on an ESP32!
curl 192.168.1.22:8080
Hello World%
You can find the example here: https://github.com/elcritch/esp32_nim_net_example
The test example is an ESP32 project which starts the asynchttpserver (see nim/run_http_server.nim and main/ethernet_example_main.c).
@foldl, @dom96, @rayman22201 this also follows up on the discussion at: https://forum.nim-lang.org/t/5522#34460
This example relies on ARC. I haven't done any memory profiling but ARC appears to do a great job keeping memory usage very low on tests I've done.
I'll try and cleanup my branch for a PR later this week.
FYI: you don't need
--exceptions:goto
--dead_code_elim:on
Because:
NuttX and Zephyr could be also good candidates, they support a lot of hardware. Since they provide a decent posix API it might be easier.
Implementing CMSIS , could also be worthwhile as it is an ARM standard API implemented by several RTOS (now I just need a board).
Got an example asynchttpserver running on a wESP32
Out of curiosity, does debugging using the JTAG connector points to the correct Nim source code ?
@Yardanico oh thanks!
@Clonk, it would be nice to support those but are outside the scope of my efforts. The ESP32 is my current target so that's why I'm going for FreeRTOS + LwIP. Though, I've been toying with using a "embeededos" or "oslite" so other embedded RTOS'es could use the work... but that'll be tricky as I'd suspect each RTOS would support slightly different subsets of POSIX. sigh Still getting a working FreeRTOS target should make it a lot easier for others to copy and add Zephyr/Contiki/etc support. Particularly it's been a bit gnarly to get the os module working with embedded, but it'd not be too bad to re-use that work for other RTOS'es!
I was able to auto-merge your branch with upstream devel with no immediate problems, but only tested a hello world, didn't test all the POSIX stuff.
Excellent! Been a while since I tried, shipping hardware and all. The issues I ran into were git conflicts on merging. I think there'd been small changes in a few of the net libs and similar which, while not changed were spaced still caused git conflicts.
Bikesheading appreciated! Some of the decisions were unclear, and it's nice to have another pare of eyes on it.
The question of how to separate the different options is fraught... It would be great to be able to specify --os:esp-idf and have it work as smoothly as, e.g. --os:nintendoswitch Or are you thinking that since there's so many variants, better to specify each separately? How do you specify --lwip when compiling?
Yah, it'd be nice to have a for --os:esp-idf. That's what I started with. However, I realized that esp-idf is just a fork of FreeRTOS plus the attached libraries.
The Nim compiler also has a few internal feature flags that can be configured, so I think it'd make sense to have a base FreeRTOS option that internally sets an lwip option. Then others who wanted to use FreeRTOS on other platforms wouldn't be glued to esp-idf, but luckily it'd be pretty easy to create a --os:esp-idf that just sets FreeRTOS & LwIP internally. Perhaps @Araq can give some feedback regarding what would be the best approach. I'm new to Nim, and found the internal OS stuff surprisingly easy to hack, but I've still only been using Nim for a month so not an expert. ;-)
Personally, I don't like this approach. If we have --os:esp-idf, then will we have --os:companly_a, --os:company_b, etc, later?
Fully support (100%) of FreeRTOS is welcome, but a 50%, or even 90% support of it will make only users unhappy. Does Nim Team/Community have sufficient resources on this?
So, at least for me, for today, since Nim inter-operates with existing C code easily and nicely, when working on embedded systems, bare metal mode is preferred.
Personally, I don't like this approach. If we have --os:esp-idf, then will we have --os:companly_a, --os:company_b, etc, later?
Yah, that's part of why I realized really it's about supporting FreeRTOS + LwIP. Then each cpu is just setting the RTOS people might be using. Though I imagine community members would like a few "pre-canned" selections like the ESP32 since they're pretty popular in Maker circles.
Fully support (100%) of FreeRTOS is welcome, but a 50%, or even 90% support of it will make only users unhappy. Does Nim Team/Community have sufficient resources on this?
I don't really follow the same reasoning about needing full 100%, especially as it's currently an "experimental port". I wanted it, so I ported it and maybe others will like it too. It'll take a while to work out kinks before it's not "experimental", so caveat emptor for now. Still with one person, I was able to get a majority of the LWIP working with Nim's network libraries. FreeRTOS really isn't that big. Getting automated testing and CI will be trickier, but maybe the community can help.
Currently I envision support for FreeRTOS / ESP32 specific's to be in separate libraries. Maybe someone could wrap Nim libraries dealing with threads, but IMHO, it's better just to use libraries for that part.
Really the only need for Nim support of LwIP (& FreeRTOS) is to provide access to all the wonderful Nim networking libraries, and async servers, etc without mucking with C memory management. Otherwise libraries work best.
Sorry for the wait, but finally got around to fixing up the PR for this: https://github.com/nim-lang/Nim/pull/15250
If anyone could try it out, that'd be great! There's work to do on wrapping other things on FreeRTOS like tasks/queue's and semaphores/locks.