Using Rust Packages in a C Project on Nordic Devices

This example shows how to call a function from a Rust package from C on a nRF5340 DK and nRF52840 DK.
Source: https://www.rust-lang.org/

Why would you want to use Rust?

Rust is a pretty cool programming language that aims to make fast, safer executables. There has been a strong effort to get Rust working well on embedded devices, and it’s definitely showing.

Rust is also safer. This is because it was designed around excellent memory management practices unlike C/C++ all while still maintaining a majority of their speed advantages.. In practice, this means fewer crashes and fewer vulnerabilities.

We recently had a request to call some Rust functions from inside an existing C program that uses the nRF Connect SDK (NCS). While it wasn’t too difficult, there definitely were some challenges.

To demonstrate this, we’ll start from the most simple NCS example, which we will modify to blink each of four LEDs on the nRF5340 DK, one at a time. We will compute the delays between blinks with a Rust library.

Book a Call with Dojo Five Embedded Experts

Development

We started from the NCS blinky example as reference but modified it to blink all four LEDs on the Development Kit (DK) board. We then created a Rust library project. After writing a simple Rust function that squares its input, we modified the CMakeLists.txt from the NCS project to build the Rust portion and link it all together. Then, we call the square function from our main.c. At this point, we’ve got one CMakeLists.txt file that builds some Rust and some C, and the C program calls the Rust library and uses the output!

We’ve posted our example online

Trying it out

You’ll need the nRF Connect SDK extension for VS Code, Rust, and our repository.

Source: https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-DK

Install the nRF Connect SDK extension for VS Code by following the instructions in the link.

Next, go through the Rust development environment setup.

In order to be able to compile the Rust library to run on the nRF DK targets, you need to make sure to install the correct Rust target.In our case, for the nRF5340 DK, use thumbv8m.main-none-eabi target. Use the following command:

rustup target add thumbv8m.main-none-eabi

If you are using the nRF52840 DK, use thumbv7em-none-eabi target. Use the following command:

rustup target add thumbv7em-none-eabi

Next, download our example from GitLab.

Here is a summary of the relevant steps we took for this implementation:

  1. Created a new Rust library using Cargo in a new square_rust_lib directory
    1. mkdir square_rust_lib
    2. cd square_rust_lib
    3. cargo init --lib
  2. Added [lib] section in the Cargo.toml to specify this package is a static library
    1. Specified the name of the library – name = "square"
    2. Specified the type of crate being built – crate-type = ["staticlib"]
  3. Added .cargo/config.toml to specify a global configuration in Rust to specify the target during the build.
  4. The following were added to square_rust_lib/src/lib.rs
    1. #![no_std] – removes the Rust standard library to use the core library instead which does not depend on the underlying operating system.
    2. extern crate panic_semihosting – brings a crate to handle panics (unrecoverable errors) required by Rust. This is also added to Cargo.toml in [dependencies].
    3. #[unsafe(no_mangle)]no_mangle tells the Rust compiler not to mangle the name of the function since we are going to call this function from another language. The unsafe keyword indicates the block of code is potentially unsafe (since this is going to be called outside of Rust context).
  5. The CMakeLists.txt is updated to add a section for building the Rust library using ExternalProject_Add as a library dependency when the blinky example is built.

Next, from the nRF Connect SDK extension in VS Code, you can build and flash the project into your DK. You’ll know it’s working when you see something like this!

Wrapping Up

If you have some C or C++ that’s working fine, but you want to add some Rust to it, you can! You may not get 100% of the benefits of Rust in your whole system, but this hybrid approach can be fast and effective. By calling into Rust from C or C++, you can take advantage of embedded Rust while keeping your tried and true existing code.

Next Steps

And if you have questions about an embedded project you’re working on, Dojo Five can help you with all aspects of your devops for embedded journey! 

Project leaders – you can book a call with us to start the conversation about your project that needs modern embedded expertise. 

Engineers – if you are looking for a better CI build platform, check out our EmbedOps product to increase your productivity. 

Discover why Dojo Five EmbedOps is the embedded enterprise choice for build tool and test management.

Sign up to receive a free account to the EmbedOps platform and start building with confidence..

  • Connect a repo
  • Use Dev Containers with your Continuous Integration (CI) provider
  • Analyze memory usage
  • Integrate and visualize static analysis results
  • Perform Hardware-in-the-Loop (HIL) tests
  • Install the Command Line Interface for a developer-friendly experience

Subscribe to our Monthly Newsletter

Subscribe to our monthly newsletter for development insights delivered straight to your inbox.

Interested in learning more?

Best-in-class embedded firmware content, resources and best practices

Laptop with some code on screen

I want to write my first embedded program. Where do I start?

The boom in the Internet of Things (IoT) commercial devices and hobbyist platforms like the Raspberry Pi and Arduino have created a lot of options, offering inexpensive platforms with easy to use development tools for creating embedded projects. You have a lot of options to choose from. An embedded development platform is typically a microcontroller chip mounted on a circuit board designed to show off its features. There are typically two types out there: there are inexpensive versions, sometimes called

Read More »
Medical device monitoring vitals

IEC-62304 Medical Device Software – Software Life Cycle Processes Primer – Part 1

IEC-62304 Software Lifecycle requires a lot of self-reflection to scrutinize and document your development processes. There is an endless pursuit of perfection when it comes to heavily regulated industries. How can you guarantee something will have zero defects? That’s a pretty hefty task. The regulatory approach for the medical device industry is process control. The concept essentially states that if you document how every step must be completed, and provide checks to show every step has been completed properly, you

Read More »
Operating room filled with medical devices

IEC-62304 Medical Device Software – Software Life Cycle Processes Primer – Part II

Part I provides some background to IEC-62304. Part II provides a slightly more in-depth look at some of the specifics. The IEC 62304 Medical Device Software – Software Lifecycle Processes looks into your development processes for creating and maintaining your software. The standard is available for purchase here. So what activities does the standard look at? Here are some of the major topics. For any given topic, there will be a lot more specifics. This will look at a few

Read More »