apache / nuttx

Apache NuttX is a mature, real-time embedded operating system (RTOS)
https://nuttx.apache.org/
Apache License 2.0
2.52k stars 1.07k forks source link

[Discussion] Rust integration in Nuttx #11907

Open rushabhvg opened 4 months ago

rushabhvg commented 4 months ago

As a part of GSOC 2024, I wish to integrate Rust into Nuttx. For that, a new coding standard for Rust programming language will be required and there's no mention of it anywhere. Before writing any rust code, a coding standard would be required. Please give your inputs. I was able to find C coding standards at: C Coding Standard

rushabhvg commented 4 months ago

@xiaoxiang781216 @anchao @raiden00pl Please give your suggestions.

xiaoxiang781216 commented 4 months ago

NuttX doesn't support Rust yet, that's why no Rust coding standard exist in official document. As far as I know, Rust defines an official coding standard, so I would suggest that NuttX follow this style too. @patacongo @acassis what do you thinking?

ppisa commented 4 months ago

I think that it would worth to discuss Rust on NuttX with @lupyuen https://lupyuen.github.io/ . I have seen lot of useful information on his site.

lupyuen commented 4 months ago

Yep sure let's have a chat. I'm more into Rust Apps for NuttX, not so much Rust Kernel for NuttX. But let's talk :-)

(Linux Kernel Rust might be a good model to adopt)

rushabhvg commented 4 months ago

Hello @lupyuen then maybe I can start with Rust Apps for Nuttx? How should we communicate?

lupyuen commented 4 months ago

@rushabhvg Let's discuss over email: luppy@appkaki.com. I'm in Singapore (GMT+8) so my response may be slow. Thanks :-)

acassis commented 4 months ago

NuttX doesn't support Rust yet, that's why no Rust coding standard exist in official document. As far as I know, Rust defines an official coding standard, so I would suggest that NuttX follow this style too. @patacongo @acassis what do you thinking?

@xiaoxiang781216 you mean for Rust applications or Rust code used on kernel right? I think it makes sense because Rust developer could feel uncomfortable reading/write Rust code using NuttX Coding Style

TimJTi commented 4 months ago

Is this a suggestion that NuttX RTOS itself will move from C to Rust? Or a mix of the two? Sorry if it's a dumb question but I know nothing about rust other than what's on my car...

patacongo commented 4 months ago

I would think that a mix of the two could be a maintenance problem.

acassis commented 4 months ago

Is this a suggestion that NuttX RTOS itself will move from C to Rust? Or a mix of the two? Sorry if it's a dumb question but I know nothing about rust other than what's on my car...

I thought exactly that when I read Xiang comments at first time, but no, he was just saying: let Rust code to use Rust coding style, that makes sense. But as Greg commented we need to figure out how to improve the maintenance to have two coding styles. Maybe just having CI checker for .c and .rs is enough, not sure

TimJTi commented 4 months ago

Is this a suggestion that NuttX RTOS itself will move from C to Rust? Or a mix of the two? Sorry if it's a dumb question but I know nothing about rust other than what's on my car...

I thought exactly that when I read Xiang comments at first time, but no, he was just saying: let Rust code to use Rust coding style, that makes sense. But as Greg commented we need to figure out how to improve the maintenance to have two coding styles. Maybe just having CI checker for .c and .rs is enough, not sure

Where would Rust code be used - approved to be used - though?

patacongo commented 4 months ago

Where would Rust code be used - approved to be used - though?

It is somewhat less concerning if restricted to architecture- or board- specific logic as Alan suggested in an dev email.

Any use of use of Rust in the OS must have the support of the NuttX community. Not just the small group of people with special interests in this issue.

cederom commented 4 months ago

Hello @rushabhvg and thank you for your interest in NuttX RTOS :-) My suggestions for the workplan in 5 simple steps is presented below :-)

  1. Limit Rust use for APPLICATIONS ONLY and NOT THE KERNEL.
  2. Work on application layer just like other programming languages do in NuttX (i.e. existing Basic code or new ZigLang apps created by @lupyuen).
  3. Work out optional setup that will allow porting and running Rust applications on NuttX. Use most generic and well known Rust tool set for integration like [1].
  4. Create and/or Port some demo applications including peripherals use cases (i.e. UART, SPI, I2C, graphical display, audio, input, network). Note that applications should only use existing underlying RTOS drivers (i.e. Arch + Board setup with devfs+ioctl interface) and not their own drivers that would interfere with existing RTOS drivers.
  5. Create documentation on how to setup local environment for Rust build, how to setup NuttX to work with Rust, how to build a firmware with NuttX and example Rust applications, how to port new Rust applications to NuttX (including KConfig, Makefile, etc).

[1] https://github.com/rust-embedded/awesome-embedded-rust

rushabhvg commented 4 months ago

Okay @cederom I will follow this worklplan. ANd, work with @lupyuen .

lupyuen commented 4 months ago

Hi All: @rushabhvg couldn't register on the NuttX Mailing List to read our thoughts about Rust. Any idea how we can troubleshoot this? Thanks :-)

rushabhvg commented 4 months ago

I have tried creating my account through this url when I click on "Subscribe to list" button, nothing happens. Kindly guide.

lupyuen commented 4 months ago

Hi @rushabhvg thanks for chatting over email (and listening to my rant on Rust pros and cons :-) I suggest we begin with this:

  1. Let's build and run a simple Rust App on NuttX: https://gist.github.com/lupyuen/7be4bedc6a109b2c3d1201aee6030428
  2. If you see this error, let's discuss over email: "Can't link soft-float modules with double-float modules"
  3. Assuming our Rust App runs OK on NuttX: Let's port this LED Blinky App from C to Rust (because it demonstrates POSIX Support): https://github.com/lupyuen2/wip-pinephone-nuttx-apps/blob/nim/examples/hello/hello_main.c#L40-L85
  4. ULEDIOC_SETALL is explained here: https://lupyuen.github.io/articles/nim#blink-an-led
  5. Then we'll do the same for larger Rust Apps, hopefully we'll work out the Rust Coding Guidelines along the way. Thanks :-)
rushabhvg commented 4 months ago

Okay thanks! @lupyuen

acassis commented 4 months ago

I have tried creating my account through this url when I click on "Subscribe to list" button, nothing happens. Kindly guide.

You can send a email to dev-subscribe@nuttx.apache.org and then reply the received email

acassis commented 4 months ago

@lupyuen I think you pointed to hello world in C, the hello world in rust is at hello_rust. But as Dan Gohman ( @sunfishcode ) commented in this Rustix presentation, the integration has some issues, the way it was done we will need a wrapper (extern "C" {} ) for all functions of NuttX. I don't know if he still available to help us, let me ping him and see.

lupyuen commented 4 months ago

For the record: This PR explains why we're not using Rust Crates, cargo build and Cargo.toml in NuttX: https://github.com/apache/nuttx/pull/5566

Which presents interesting challenges for Rust Apps in NuttX :-) @rushabhvg Let's document the workarounds that we used (patching of ELF Header, RUSTFLAGS=-O), I think it will be highly useful for other devs

(Might be a good topic for the upcoming NuttX Workshop!)

lupyuen commented 4 months ago

Some folks are wondering: Why not use the Rust Standard Library, instead of the barebones no_std? (Rust Core Library) Isn't the Rust Standard Library a lot simpler for doing Console I/O and other POSIX Operations?

  1. Traditionally when we build firmware for Embedded Devices, we use no_std: https://docs.rust-embedded.org/book/intro/no-std.html

  2. Each Embedded OS will have its own C Function for Console I/O. On NuttX: It just happens that we call the C Standard Library, because NuttX supports POSIX. On FreeRTOS: It would be a totally different C Function.

  3. NuttX is a little different from other RTOS because it's compatible with POSIX. In theory, Rust Standard Library could run on NuttX, thanks to POSIX. But it needs work.

  4. Rustix Project is working on supporting Rust Standard Library on NuttX. But it seems to have stalled:

    https://www.reddit.com/r/rust/comments/zfwaqf/integrating_rustix_on_nuttx/

    https://github.com/bytecodealliance/rustix/tree/nuttx

    https://www.youtube.com/watch?v=JTJW6kOqf9I

  5. In any case, running Rust Standard Library on Embedded Devices will have impact on Memory Size and Real-Time Performance. Consider Rust on ESP32: It supports Rust Standard Library as well as no_std: https://docs.esp-rs.org/book/overview/using-the-standard-library.html

    ESP32 Rust Standard Library is not recommended if we need Small Memory Footprint, Direct Hardware Control and Real-Time Performance: https://docs.esp-rs.org/book/overview/using-the-core-library.html

  6. So for NuttX: We should probably provide Minimal Rust Wrappers around the POSIX Functions that we actually need, instead of supporting the entire Rust Standard Library. If we look at LED Blinky: We'll need open(), close(), ioctl(), sleep(), ...

    The Rust Wrappers should allow Strings and Pointers to be passed safely to/from NuttX. Maybe the Rustix Project has something we can borrow: https://github.com/bytecodealliance/rustix/tree/nuttx

acassis commented 4 months ago

@lupyuen thank you for summarize it very well. Let's ping @ptka he could be interested to see this progress and hopeful help us on this effort.

lupyuen commented 4 months ago

FYI @rushabhvg Linux Kernel has Coding Guidelines and Templates that might be helpful:

lupyuen commented 4 months ago

FYI: Zephyr OS is also working on supporting Rust Apps and Rust Drivers: https://github.com/zephyrproject-rtos/zephyr/issues/65837

patacongo commented 4 months ago

@lupyuen I have a question that maybe you can answer. Everything that I have read says that Rust runs "on top of an OS". I can't find the exhaustive list of OS interfaces required by Rust. Such a thing must exist somewhere to support porting to other OSs.

I checked a couple of specific interfaces. malloc(), for example, seems to be required by Rust.

In KERNEL and PROTECTED build modes, malloc() is not available in the kernel. kmm_malloc() must be used instead to allocate from the kernel heap. So I suppose that in these modes you would need wrappers around all of the application OS functions required by Rust to use the internal OS functions: To fix functionality in some cases. What about cancellation points and returned errno values? There is no errno within the OS.

Even in the FLAT build, OS code avoids calling application interfaces directly to eliminate spurious cancellation points and clobbering the per-task errno value.

lupyuen commented 4 months ago

Hi @patacongo :-) There are 2 "flavours" of Rust, depending on the Rust Libraries that we use:

The malloc() that you mentioned: It's called by the Rust Standard Library. (Like this)

For Kernel Dev (like Linux): We'll use the Rust Core Library. Which doesn't support Heap Memory and doesn't need malloc().

But most Kernel Drivers will need Kernel Heap. That's why Linux Kernel also supports the alloc Rust Library / Crate. To implement Rust alloc, Linux Kernel calls krealloc() to allocate Kernel Heap. (Like this)

For NuttX Kernel: We'll implement Rust alloc by calling kmm_malloc().

Since we're calling Rust Core Library in the Kernel, we won't touch any POSIX Application Interfaces. So if we need to support the Kernel Equivalent of Cancellation Points and Errno, we'll have to build the Rust Library ourselves. (Here's the Rust Library for Linux Kernel)

patacongo commented 4 months ago

Since we're calling Rust Core Library in the Kernel, we won't touch any POSIX Application Interfaces. So if we need to support the Kernel Equivalent of Cancellation Points and Errno, we'll have to build the Rust Library ourselves

No, I meant the opposite. The kernel should never initiate a cancellation point and should never modify the errno. My concern was that any application interfaces called from a kernel-embedded, run-time library might do just that.

Related: NuttX does not support shared libraries in these build modes. This means that there might be multiple copies of whatever necessary run-time support is needed in each user and kernel address space. The C libraries really have this same problem at present.

acassis commented 4 months ago

That is an interesting interview with Linus Torvalds about Rust: https://www.youtube.com/watch?v=YyRVOGxRKLg

Although he doesn't program in Rust, he seems to agree it is an important addition to Linux.