Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/tylerwhall/zephyr-rust

API bindings, libstd, and Cargo integration for running Rust applications on a Zephyr kernel
https://github.com/tylerwhall/zephyr-rust

Last synced: 3 months ago
JSON representation

API bindings, libstd, and Cargo integration for running Rust applications on a Zephyr kernel

Awesome Lists containing this project

README

        

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

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