Skip to content

Rust support for RIOT #9799

@chrysn

Description

@chrysn

It would be nice to be able to write applications in Rust that would run on a RIOT board, especially when sharing libraries with non-embedded systems. Before I plunge head-first into a third attempt (after #5740 and #6162), I'd like to look at an outline of what needs to be done for this to be usable, and before that, to look at what being usable actually means in this case.

Usage scenarios I see are (to be ticked when there's actual need for them):

  • Having individual applications (eg. network services) written in Rust run on RIOT – this is what I'd like to do.
  • Write complete hardware drivers in Rust. API-call-wise, this is not so much different from applications, but might be in terms of the build system.
  • Use Rust libraries that provide C wrappers inside RIOT applications
  • Explore the viability of RIOT components as part of the Rust ecosystem. (eg. "Could GNRC and SAUL work for embedded-rust in general?")

Technically, the nontrivial tasks I see are:

  • Build system integration
  • Making RIOT API available in Rust as an embedded-hal
    • Finding adequate lifetimes (how long can I use a saul_reg?)
    • How to deal with API that's dependent on board.h or cpu_*.h? (Initial approach: #define UART_STDIO_DEV irrelevant and assert that it has no impact on the actual API functions)
    • How to deal with static inline functions? (This ties into the build system as AFAICT static is used to allow inlining down to board configuration like clock speed. Initial approach: Have the rump application export non-static versions of them.)
    • Finding a versioning scheme for the API that works both with Rust's semver versioning and RIOT (probably see [RFC] Versioning our user facing APIs #8561)
    • Making uart_stdio_write usable by Rust's write! (not actually tricky but done)

Given my use cases, my exploratory work is more focused on the API part; I'd like to have a "raw" (possibly bindgen generated) API that more or less just gets rid of the extern "C" parts, and Rust's famous safe zero-cost abstractions on top of that. Ideally, RIOT peripherals could thus implement the embedded-hal interfaces, making the OS agnostic drivers usable immediately.

As far as the build system is concerned, my use case comes with low expectations towards integration: what I currently do works reasonably well, which is making cargo output a static library for the application, and having a rump RIOT application that calls once into a rust_main(), which then sets up any threads etc. (Quite possibly, having main in Rust could work just as well). The only thing I needed in the build system was to set BASELIBS+=.../target/.../libapplication.a; from there, everything builds and flashes fine.

@kaspar030, @nmeum, what were your applications, and what are your expectations on build system integration? Given that embedded Rust has come some way in the meantime (eg. xargo is not needed any more), do you think one of the build system integration approaches should be resurfaced? How far did you get with making RIOT's APIs usable from Rust?

[Apologies for the many editing iterations; my new keyboard is more Ctrl-Return happy than my old one. This is the final version of the issue's initial comment, except for later additions to the checkboxes which are accompanied by new comments on the thread.]

Metadata

Metadata

Assignees

Labels

Area: RustArea: Rust wrapperType: new featureThe issue requests / The PR implemements a new feature for RIOTType: trackingThe issue tracks and organizes the sub-tasks of a larger effort

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions