nuttx icon indicating copy to clipboard operation
nuttx copied to clipboard

[Discussion] Rust integration in Nuttx

Open rushabhvg opened this issue 1 year ago • 29 comments

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 avatar Mar 13 '24 07:03 rushabhvg

@xiaoxiang781216 @anchao @raiden00pl Please give your suggestions.

rushabhvg avatar Mar 13 '24 07:03 rushabhvg

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 avatar Mar 13 '24 07:03 xiaoxiang781216

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.

ppisa avatar Mar 13 '24 08:03 ppisa

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)

lupyuen avatar Mar 13 '24 08:03 lupyuen

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

rushabhvg avatar Mar 13 '24 14:03 rushabhvg

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

lupyuen avatar Mar 13 '24 14:03 lupyuen

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

acassis avatar Mar 13 '24 18:03 acassis

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...

TimJTi avatar Mar 13 '24 18:03 TimJTi

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

patacongo avatar Mar 13 '24 19:03 patacongo

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

acassis avatar Mar 13 '24 19:03 acassis

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?

TimJTi avatar Mar 13 '24 20:03 TimJTi

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.

patacongo avatar Mar 13 '24 22:03 patacongo

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

cederom avatar Mar 13 '24 23:03 cederom

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

rushabhvg avatar Mar 14 '24 05:03 rushabhvg

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 :-)

lupyuen avatar Mar 14 '24 09:03 lupyuen

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

rushabhvg avatar Mar 14 '24 10:03 rushabhvg

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 :-)

lupyuen avatar Mar 14 '24 10:03 lupyuen

Okay thanks! @lupyuen

rushabhvg avatar Mar 14 '24 10:03 rushabhvg

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 [email protected] and then reply the received email

acassis avatar Mar 14 '24 13:03 acassis

@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.

acassis avatar Mar 14 '24 14:03 acassis

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 avatar Mar 15 '24 06:03 lupyuen

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

lupyuen avatar Mar 15 '24 07:03 lupyuen

@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.

acassis avatar Mar 15 '24 14:03 acassis

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

  • Coding Guidelines for Rust in Linux Kernel: https://docs.kernel.org/rust/coding-guidelines.html
  • Rust Template for Out-Of-Tree Linux Kernel Module: https://github.com/Rust-for-Linux/rust-out-of-tree-module
  • Rust Crate for Linux Kernel Module: https://rust-for-linux.github.io/docs/v6.8-rc3/kernel/ (Since we don't allow Rust Crates in NuttX, we might need a similar preloaded library for NuttX Interfaces)
  • The links above are from the "Rust For Linux" website: https://rust-for-linux.com/

lupyuen avatar Mar 16 '24 00:03 lupyuen

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

lupyuen avatar Mar 17 '24 01:03 lupyuen

@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.

patacongo avatar Mar 17 '24 01:03 patacongo

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

  • Rust Standard Library: This is used by most Rust Apps on desktops and servers. Supports Heap Memory and the Rust Equivalent of POSIX Calls.
  • Rust Core Library (no_std): Barebones Rust Library that runs on Bare Metal, used by Rust Embedded Apps. Calls minimal libc functions, doesn't support Heap Memory and POSIX.

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)

lupyuen avatar Mar 17 '24 03:03 lupyuen

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.

patacongo avatar Mar 17 '24 12:03 patacongo

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.

acassis avatar Mar 20 '24 00:03 acassis

Late to the party but using make isn't the right way to go about integrating rust into any RTOS.

Half the appeal of rust isn't just memory safety, but the tools that come with cargo such as a package manager, clippy, etc. what are the roadblocks to making a fully fledged build system with cargo instead of make?

nakajimayoshi avatar Mar 17 '25 14:03 nakajimayoshi