zephyr-rust
zephyr-rust copied to clipboard
API bindings, libstd, and Cargo integration for running Rust applications on a Zephyr kernel
Rust on Zephyr RTOS ###################
Overview
Zephyr_ module for building a Cargo project and linking it into a Zephyr image. Add this directory to ZEPHYR_EXTRA_MODULES to build a Cargo library project (located in the Zephyr app's source directory by default) and link it into the Zephyr app.
Version Compatibility
Zephyr: v2.3, v2.4, v2.5, v2.6, v2.7, v3.4
Rust: exactly 1.68.0
Features
-
Generated bindings for all syscalls
-
Safe wrappers for some Zephyr APIs (mutex, semaphore, timers, k_poll, UART)
-
Basic libstd port (no_std not necessary)
-
Heap (std::alloc) see CONFIG_RUST_ALLOC_POOL
-
Thread-local storage
-
Kernel or user-mode Rust
- Rust globals and heap in a Rust-specific memory segment that can be granted to specific threads
- Syscalls compile to direct C function calls when !CONFIG_USERSPACE
- Note: running kernel and user-mode Rust at the same time could pose a security risk, since there is one shared global allocator
-
Minimal std::futures executor
- Supports dynamic tasks and timers
- Currently single-threaded
- async/await UART example
-
Implemented as a Zephyr module for inclusion in existing Zephyr projects
-
No modifications to Zephyr source
.. _Zephyr: https://github.com/zephyrproject-rtos/zephyr
Building and Running
Clone the repo
Make sure to clone the submodules recursively. This points to modified Rust libstd.
.. code-block:: console
git clone --recurse-submodules https://github.com/tylerwhall/zephyr-rust.git
Zephyr setup
Refer to the Zephyr getting started guide_. This includes installing west, getting Zephyr source, and the Zephyr toolchain. Make sure you can build a C sample within Zephyr.
.. _guide: https://docs.zephyrproject.org/2.5.0/getting_started/index.html
See above for tested compatible Zephyr releases. Please try a release if master
does not work. Due to differences in the syscall header generation, v1.14 LTS
is no longer supported.
See issue 16 <https://github.com/tylerwhall/zephyr-rust/issues/16>
_.
Rust toolchain
The compiler version must exactly match the version of standard library included as a submodule of this project. In practice, using a different compiler version often fails to compile because of Rust internally making heavy use of unstable compiler features.
The current base is stable-1.68.0. Rustup is the default workflow, and the rust-toolchain file in this repo should cause rustup to automatically install and use the right version. If not, manually install:
.. code-block:: console
rustup toolchain install 1.68.0
If supplying your own rustc and cargo, make sure they are the version above. The build will fail if it detects a version mismatch.
Also install clang from your distro. This is required by bindgen to generate syscall bindings. Else you will get this error
.. code-block:: console
thread 'main' panicked at 'Unable to find libclang: "couldn\'t find any valid shared libraries matching: [\'libclang.so\', \'libclang-*.so\', \'libclang.so.*\']
Build
.. code-block:: console
west build -p auto -b <board name> samples/rust-app/
Native:
.. code-block:: console
west build -p auto -b native_posix samples/rust-app/
qemu_x86:
.. code-block:: console
west build -p auto -b qemu_x86 samples/rust-app/
ARM Cortex-M:
.. code-block:: console
west build -p auto -b qemu_cortex_m3 samples/rust-app/
These errors are normal. Needs investigation, but the binary is still created successfully.
.. code-block:: console
x86_64-zephyr-elf-objdump: DWARF error: mangled line number section (bad file number)
Run (QEMU targets):
.. code-block:: console
cd build
ninja run
Sample Output
.. code-block:: console
*** Booting Zephyr OS build zephyr-v2.2.0 ***
Hello Rust println
Hello from Rust kernel with direct kernel call
Hello from Rust kernel with runtime-detect syscall
Hello from second thread
second thread: f = 1
second thread: now f = 55
Time InstantMs(20)
Time Instant(InstantMs(20))
Locking
Unlocking
No device
Boxed value 1
main thread: f = 1
main thread: now f = 2
Hello from Rust userspace with forced user-mode syscall
Locking
Unlocking
INFO app: TEST: info!()
WARN app: TEST: warn!()
ERROR app: TEST: error!()
main thread: f = 2
main thread: now f = 3
Hello from Rust userspace with forced user-mode syscall
Hello from Rust userspace with runtime-detect syscall
Next call will crash if userspace is working.
FAILED: zephyr/CMakeFiles/run
Failure is from an intentional crash at the end of the sample.
Testing
The Zephyr test runner can be used:
.. code-block:: console
$ZEPHYR_BASE/scripts/sanitycheck --testcase-root tests -p native_posix -N
Or you can build and run the test manually:
.. code-block:: console
west build -p auto -b native_posix tests/rust
cd build
ninja run
Supported Architectures
- native_posix
- x86
- armv7m
- armv7r
- thumbv7em
Really anything that works with Zephyr and Rust should work. Only need to define a target.json and add a case for it in CMakelists.
TODO
- Figure out how to fail tests through assertions in code
- Support #[test]
- Ability to build multiple independent apps
- More safe bindings (e.g. GPIO)
Features Not Planned to Support
- std::thread. Requires thread resources to be dynamically allocated. This is possible, but not common for Zephyr.
- Defining static threads in Rust. Zephyr uses many layers of architecture-specific C macros that would not be wise to try to duplicate exactly in Rust. Possibly could generate C code like in the "cpp" crate, but for now just define threads in C and point them at a Rust FFI entry point.
- std::sync::{Mutex, RwLock}. Mutex should work when built without userspace support. Userspace would require (at least) CONFIG_DYNAMIC_OBJECTS. While this is possible, I don't want to require it to use libstd. May revisit. The small number of uses in libstd are patched out.
License
Licensed under either of
- Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0
- MIT license http://opensource.org/licenses/MIT
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.