Using Rust with RIOT-OS

Hey, is anyone (besides @chrysn :slight_smile: ) looking into using Rust? I gave myself a new challenge. I want to learn Rust. And to start off with a real challenge I want to learn Rust in an embedded environment, with RIOT-OS.

@chrysn created riot-examples [1] which is, I think, a good starting point. However, not everything is working for me. It works for BOARD=stm32l476g-disco but not for my SODAQ boards such as BOARD=sodaq-sara-sff. Both use the same toolchain, but for any cortexm board the build fails with that it cannot find stdio.h. I tried to understand what is happening (cargo build is a beast), used strace and more. Still I have no clue what is going on and why it fails to find stdio.h in one case but not in the other.

Thus my question: who else has tried this?

[1] https://gitlab.com/etonomy/riot-examples

2 Likes

@Kaspar is also looking into Rust + RIOT, maybe he would have an idea as well?

Can’t help you with that one because of a different issue.

This I can only recommend, Rust is awesome. :wink:

I’ve started experimenting with core written in Rust which can be used together with RIOT. The thing also makes use of @chrysn’s riot-wrappers. It is very experimental, but initial code is here. But so far it only supports the nrf52840dk.

@Kaspar can you try to just build saul_blink for some samd21 board. I want confirmation that it is not my own installation at fault.

I’m getting the same stdio.h error:

  /home/kaspar/src/riot.tmp/cpu/cortexm_common/include/cpu.h:33:10: fatal error: 'stdio.h' file not found, err: true
  thread 'main' panicked at 'Unable to generate bindings: ()', /home/kaspar/.cargo/registry/src/github.com-1ecc6299db9ec823/riot-sys-0.3.1/build.rs

This worked before, no idea what has changed.

Thanks

Let’s hope @chrysn will chime in someday :slight_smile:

My suspicion is that clang is called in the build process and that it is using the wrong set of include directories. I believe clang is used to preprocess some files, but in doing so, it should never fall back to the “system” (i.e. host version) include directories. And with strace I could see that it is doing just that.

Plus, it remains a mystery that two arm-none-eabi boards can give different result. One builds, the other one doesn’t.

Does someone know if etonomy is still active with https://gitlab.com/etonomy/riot-examples i got a PR open there for some time

AFAIK etonomy is using the underlying riot-wrappers for their product. I guess the examples don’t get as much attention because @chrysn is busy.

Sorry, missed the notification, I’ll get back to it.

@chrysn Do you have an idea why the examples don’t build for samd21 boards? (See my initial message in this thread.)

Mh, I can reproduce it (based on 2021.01 RIOT and latest HEAD (96fbfd46) of the examples); looking into it.

What I got so far:

  • It seems to be CPU core specific; I’ve only seen this on cortex-m0 and cortex-m0plus boards, which are both armv6s-m (like stk3200 or nucleo-f072rb even though they hit stdint.h first; not m3 as in stk3700).

  • When using TOOLCHAIN=llvm, the trouble goes away (except for stk3200 but it’s a ROM overflow that kills it there – haven’t tried to optimize anything there yet, but Rust’s standard string formatting is pretty heavy).

    I think I should make LLVM the recommendation for Rust-on-RIOT anyway.

Still looking for what actually causes this, but at least using LLVM should get you going again.

The whole process is quiet complicated. I got lost in all the details. Somehow I got the impression that one of the (underlying) compilation/preprocessing was done with the host environment instead of the cross-compile environment.

Doing an strace I could see /usr/include/stdio.h being used and that can never be correct for a non-native board. But like I said, it’s complicated, I could be totally wrong.

And there may even be a RIOT problem with detection the correct details of the toolchain (especially include directories).

But do you get your applications to work with TOOLCHAIN=llvm at least? (Honestly, it may be that GCC is something supporting which I’d postpone.)

The over-all situation is admittedly far from ideal. Trouble is that neither bindgen nor c2rust are particularly cross-building friendly (even tough Rust itself usually is). Maybe I’m also doing it wrong, and should (rather than trying to find the right build arguments half-on-my-own) ask the RIOT build system for the right build arguments for LLVM, apply those and trust the implied promise that no matter the toolchain, the C ABI is upheld and they can link interchangably.

Knowing whether the problem dissolves for you too with TOOLCHAIN=llvm would be one data point to guide that decision. (If I go the abovementioned route in the default build integrations, the GCC could then become usable again).

I can confirm that the saul_blink example works with TOOLCHAIN=llvm

1 Like

Having dug farther and farther into which CFLAGS are set why and when, I think more and more that the right way for riot-sys (or, more, the build integration) is to ask the RIOT build system for which CFLAGS would be set if building with CLANG.

Unfortunately, these are not set just in the toolchain specific includes, but at several places by checking for TOOLCHAIN. That should also solve the issues about the host stdio.h being used, because when clang is used, the makefiles pass the rigth libc to use in CFLAGS (eg. libc/newlib.mk in NEWLIB_INCLUDES).

(Really, that the libc is entangled with the compiler in the first place is a mess of its own).

The easy step is to update the examples (done), the next step is properly resolving #3.

That’s what I’m doing with RIOT-rs, just use the output of “make info-debug-variable-CFLAGS” etc.

Great to see that Rust on RIOT still is moving forward. Keep up the good work.

1 Like

Hi, I’m having trouble running make on examples/rust-hello-world.

  • command: make RUST_BACKTRACE=full BOARD=native all term
  • toolchain: nightly, due to error[E0554]: #![feature] may not be used on the stable release channel.
  • OS: linux debian 10
Full log output of `make`
    Building application "hello-world" for "native" with MCU "native".

"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/boards/native compile-commands
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/boards/native/drivers compile-commands
make[3]: Nothing to be done for 'compile-commands'.
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/core compile-commands
make[2]: Nothing to be done for 'compile-commands'.
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/cpu/native compile-commands
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/cpu/native/periph compile-commands
make[3]: Nothing to be done for 'compile-commands'.
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/cpu/native/stdio_native compile-commands
make[3]: Nothing to be done for 'compile-commands'.
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/drivers compile-commands
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/drivers/periph_common compile-commands
make[3]: Nothing to be done for 'compile-commands'.
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/sys compile-commands
"make" -C /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/sys/auto_init compile-commands
make[3]: Nothing to be done for 'compile-commands'.
   Compiling riot-sys v0.5.2
error: failed to run custom build command for `riot-sys v0.5.2`

Caused by:
  process didn't exit successfully: `/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/examples/rust-hello-world/bin/native/target/release/build/riot-sys-947eab958480932d/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-env-changed=RIOT_COMPILE_COMMANDS_JSON
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/examples/rust-hello-world/bin/native/cargo-compile-commands.json
  cargo:rerun-if-env-changed=RIOT_USEMODULE
  cargo:rerun-if-env-changed=RIOT_CC
  cargo:rerun-if-env-changed=RIOT_CFLAGS
  cargo:CC=clang
  cargo:CFLAGS="-DRIOT_FILE_RELATIVE=\"/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/cpu/native/async_read.c\"" "-DRIOT_FILE_NOPATH=\"async_read.c\"" -DDEVELHELP -Werror -Wall -Wextra -pedantic -g3 -Og -U_FORTIFY_SOURCE "-std=gnu11" -m32 -fstack-protector-all -ffunction-sections -fdata-sections -DDEBUG_ASSERT_VERBOSE "-DRIOT_APPLICATION=\"hello-world\"" "-DBOARD_NATIVE=\"native\"" "-DRIOT_BOARD=BOARD_NATIVE" "-DCPU_NATIVE=\"native\"" "-DRIOT_CPU=CPU_NATIVE" "-DMCU_NATIVE=\"native\"" "-DRIOT_MCU=MCU_NATIVE" -fwrapv -Wstrict-overflow -fno-common -ffunction-sections -fdata-sections -Wall -Wextra -Wmissing-include-dirs -fno-delete-null-pointer-checks -fdiagnostics-color -Wstrict-prototypes -Wold-style-definition -gz "-Wformat=2" -Wcast-align -include /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/examples/rust-hello-world/bin/native/riotbuild/riotbuild.h -DNATIVE_INCLUDES -I/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/boards/native/include/ -I/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/core/include/ -I/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/drivers/include/ -I/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/cpu/native/include -I/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/sys/include -MQ async_read.o -MD -MP -DMODULE_AUTO_INIT -DMODULE_BOARD -DMODULE_CORE -DMODULE_CORE_IDLE_THREAD -DMODULE_CORE_INIT -DMODULE_CORE_MSG -DMODULE_CORE_PANIC -DMODULE_CPU -DMODULE_NATIVE_DRIVERS -DMODULE_PERIPH -DMODULE_PERIPH_COMMON -DMODULE_PERIPH_GPIO -DMODULE_PERIPH_GPIO_LINUX -DMODULE_PERIPH_INIT -DMODULE_PERIPH_INIT_GPIO -DMODULE_PERIPH_INIT_GPIO_LINUX -DMODULE_PERIPH_INIT_PM -DMODULE_PERIPH_INIT_UART -DMODULE_PERIPH_PM -DMODULE_PERIPH_UART -DMODULE_STDIO_NATIVE -DMODULE_SYS -DMODULE_
  cargo:rerun-if-changed=riot-bindgen.h
  cargo:rerun-if-changed=/usr/include/fcntl.h
  cargo:rerun-if-changed=/usr/include/features.h
  cargo:rerun-if-changed=/usr/include/stdc-predef.h
  cargo:rerun-if-changed=/usr/include/sys/cdefs.h
  cargo:rerun-if-changed=/usr/include/bits/wordsize.h
  cargo:rerun-if-changed=/usr/include/bits/long-double.h
  cargo:rerun-if-changed=/usr/include/gnu/stubs.h
  cargo:rerun-if-changed=/usr/include/gnu/stubs-32.h
  cargo:rerun-if-changed=/usr/include/bits/types.h
  cargo:rerun-if-changed=/usr/include/features.h
  cargo:rerun-if-changed=/usr/include/bits/wordsize.h
  cargo:rerun-if-changed=/usr/include/bits/typesizes.h
  cargo:rerun-if-changed=/usr/include/bits/fcntl.h
  cargo:rerun-if-changed=/usr/include/bits/fcntl-linux.h
  cargo:rerun-if-changed=/usr/include/bits/types/struct_timespec.h
  cargo:rerun-if-changed=/usr/include/bits/types.h
  cargo:rerun-if-changed=/usr/include/bits/stat.h

  (... truncated ...)

  cargo:rerun-if-changed=/usr/include/errno.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/sys/include/phydat.h
  cargo:rerun-if-changed=/usr/lib/llvm-7/lib/clang/7.0.1/include/stddef.h
  cargo:rerun-if-changed=/usr/lib/llvm-7/lib/clang/7.0.1/include/stdint.h
  cargo:rerun-if-changed=/usr/include/stdint.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/core/include/kernel_defines.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/sys/include/saul_reg.h
  cargo:rerun-if-changed=/usr/lib/llvm-7/lib/clang/7.0.1/include/stdint.h
  cargo:rerun-if-changed=/usr/include/stdint.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/drivers/include/saul.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/sys/include/phydat.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/boards/native/include/board.h
  cargo:rerun-if-changed=/usr/lib/llvm-7/lib/clang/7.0.1/include/stdint.h
  cargo:rerun-if-changed=/usr/include/stdint.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/drivers/include/motor_driver.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/drivers/include/periph/pwm.h
  cargo:rerun-if-changed=/usr/lib/llvm-7/lib/clang/7.0.1/include/stdint.h
  cargo:rerun-if-changed=/usr/include/stdint.h
  cargo:rerun-if-changed=/usr/lib/llvm-7/lib/clang/7.0.1/include/limits.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/cpu/native/include/periph_cpu.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/cpu/native/include/periph_conf.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/drivers/include/periph/gpio.h
  cargo:rerun-if-changed=/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/core/include/mutex.h
  cargo:rerun-if-changed=riot-c2rust.h
  Running C2Rust on /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/examples/rust-hello-world/bin/native/target/i686-unknown-linux-gnu/release/build/riot-sys-0ecdd0d8caa105c6/out/compile_commands.json

  --- stderr
  thread 'main' panicked at 'C2Rust failed: Os { code: 2, kind: NotFound, message: "No such file or directory" }', /home/geovane/.cargo/registry/src/github.com-1ecc6299db9ec823/riot-sys-0.5.2/build.rs:259:10
  stack backtrace:
     0:     0x55930ee0677c - std::backtrace_rs::backtrace::libunwind::trace::h8be286d067839d4f
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
     1:     0x55930ee0677c - std::backtrace_rs::backtrace::trace_unsynchronized::h44b722b66416ac08
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
     2:     0x55930ee0677c - std::sys_common::backtrace::_print_fmt::h2b78b2a0da201765
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/sys_common/backtrace.rs:67:5
     3:     0x55930ee0677c - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h890804b6cfffe9fc
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/sys_common/backtrace.rs:46:22
     4:     0x55930ee2bf2c - core::fmt::write::h0200d27bf417ad61
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/core/src/fmt/mod.rs:1149:17
     5:     0x55930ee02455 - std::io::Write::write_fmt::h917ab11fd974bb56
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/io/mod.rs:1660:15
     6:     0x55930ee08210 - std::sys_common::backtrace::_print::hc83d16fbacc2fa85
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/sys_common/backtrace.rs:49:5
     7:     0x55930ee08210 - std::sys_common::backtrace::print::hf2dccf30793e7b28
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/sys_common/backtrace.rs:36:9
     8:     0x55930ee08210 - std::panicking::default_hook::{{closure}}::h8710dbf03f1859af
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:211:50
     9:     0x55930ee07dc9 - std::panicking::default_hook::h86966dcda268d57f
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:228:9
    10:     0x55930ee08846 - std::panicking::rust_panic_with_hook::h7a6b21c56a75680a
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:606:17
    11:     0x55930ee083a0 - std::panicking::begin_panic_handler::{{closure}}::h0b5fbdfb333891b7
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:502:13
    12:     0x55930ee06c14 - std::sys_common::backtrace::__rust_end_short_backtrace::h00f7bbe7bd683fd2
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/sys_common/backtrace.rs:139:18
    13:     0x55930ee08309 - rust_begin_unwind
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:498:5
    14:     0x55930e8f3b51 - core::panicking::panic_fmt::h8bc989e1fc10c635
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/core/src/panicking.rs:107:14
    15:     0x55930e8f3c43 - core::result::unwrap_failed::hddb26cddfa4f23d4
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/core/src/result.rs:1661:5
    16:     0x55930e908111 - core::result::Result<T,E>::expect::h7c6cb85fa04698aa
    17:     0x55930e90b98f - build_script_build::main::h0f22d1b7414bfb57
    18:     0x55930e914173 - core::ops::function::FnOnce::call_once::hcb005b2721bc47ff
    19:     0x55930e8fe289 - std::sys_common::backtrace::__rust_begin_short_backtrace::hf2fa7b8054e63c44
    20:     0x55930e9164e9 - std::rt::lang_start::{{closure}}::h650f35655fd2908a
    21:     0x55930ee05f7e - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::hf229fdbad64016f2
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/core/src/ops/function.rs:259:13
    22:     0x55930ee05f7e - std::panicking::try::do_call::h7d8598f65f6219c4
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:406:40
    23:     0x55930ee05f7e - std::panicking::try::h91692f755b878b6e
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:370:19
    24:     0x55930ee05f7e - std::panic::catch_unwind::h5667558f93dc5a36
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panic.rs:133:14
    25:     0x55930ee05f7e - std::rt::lang_start_internal::{{closure}}::h744d08babf4d6cde
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/rt.rs:128:48
    26:     0x55930ee05f7e - std::panicking::try::do_call::h42aa3ce4fdbcbb52
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:406:40
    27:     0x55930ee05f7e - std::panicking::try::hcafbaff38524399c
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panicking.rs:370:19
    28:     0x55930ee05f7e - std::panic::catch_unwind::h1f614557dce738da
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/panic.rs:133:14
    29:     0x55930ee05f7e - std::rt::lang_start_internal::h75965f95c98f11d8
                                 at /rustc/34926f0a1681458588a2d4240c0715ef9eff7d35/library/std/src/rt.rs:128:20
    30:     0x55930e9164d1 - std::rt::lang_start::h4f98c55f05635953
    31:     0x55930e90d7d3 - main
    32:     0x7f68bf27109b - __libc_start_main
                                 at /build/glibc-vjB4T1/glibc-2.28/csu/../csu/libc-start.c:308:16
    33:     0x55930e8f42ea - _start
    34:                0x0 - <unknown>
make: *** [/home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/makefiles/cargo-targets.inc.mk:20: /home/geovane/dev/swarm/dev/tmp/explore-riot/RIOT-geo/examples/rust-hello-world/bin/native/target/i686-unknown-linux-gnu/release/librust_hello_world.a] Error 101

The main error seems to be error: failed to run custom build command for riot-sys v0.5.2.

Any ideas?

I didn’t notice that rust-hello-world needs nightly. I’d like to fix that. Looking at the details, which I saw by email, and I have no idea how to show online, I think that the issue is:

  thread 'main' panicked at 'C2Rust failed: Os { code: 2, kind: NotFound, message: "No such file or directory" }', /home/geovane/.cargo/registry/src/github.com-1ecc6299db9ec823/riot-sys-0.5.2/build.rs:259:10

I think that this is rust macros that are being used at runtime, but I admit that I don’t know how this is goign together. Yoichi and I created a different way to integrate Rust and RIOT-OS. It was in our RIOT-OS talk, if your goal is just to get the job done, rather than to integrate this way.