DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Tarantool: Speeding Up Development With Rust
  • Segmentation Violation and How Rust Helps Overcome It
  • While Performing Dependency Selection, I Avoid the Loss Of Sleep From Node.js Libraries' Dangers
  • Rust and WebAssembly: Unlocking High-Performance Web Apps

Trending

  • Scaling InfluxDB for High-Volume Reporting With Continuous Queries (CQs)
  • Streamlining Event Data in Event-Driven Ansible
  • Cookies Revisited: A Networking Solution for Third-Party Cookies
  • Emerging Data Architectures: The Future of Data Management
  1. DZone
  2. Coding
  3. Languages
  4. How to Use Rust for Embedded Development

How to Use Rust for Embedded Development

Rust is a programming language that empowers users to build reliable and efficient software, especially for embedded development.

By 
Nath Abby user avatar
Nath Abby
·
Sep. 28, 21 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
2.5K Views

Join the DZone community and get the full member experience.

Join For Free

Rust is a language that empowers everyone to build reliable and efficient software. It features:

  • High Performance: Rust features amazingly fast speed and high memory utilization.
  • Reliability: Memory errors are able to be eliminated during compilation.
  • Productivity: Great documentation, a friendly compiler with useful error messages, and top-notch tooling are just a few of Rust's benefits. It comes with an integrated package manager and build tool, smart multi-editor support with auto-completion and type inspections, an auto-formatter, and more.

Why Use Rust for Embedded Development?

Rust is designed to guarantee both security and high performance. The design philosophy fits right into what embedded development requires.

While embedded software has running problems that are mostly due to its memory. The Rust language can be regarded as a compiler-oriented language, so you can be sure that you are using memory safely while compiling. Here are some of the benefits of Rust developing on embedded devices:

  • Powerful static analysis
  • Flexible memory
  • Fearless concurrency
  • Interoperability
  • Portability
  • Community driven

Now, let’s get it on the Open Source RT-Thread operating system to demonstrate how rust can be used for embedded development.

Call Rust in C

When we’re calling the Rust code in C code, requires us to package the Rust source code as a static library file. When the C code compiles, link it in.

Create lib Library

1. Use cargo init --lib rust_to_c to build a lib library in Clion. Add the following code to the lib.rs. The following function evaluates the sum of two values of type i32 and returns the result :

#![no_std]
use core::panic::PanicInfo;#[no_mangle]
pub extern "C" fn sum(a: i32, b: i32) -> i32 {
    a + b
}#[panic_handler]
fn panic(_info:&PanicInfo) -> !{
    loop{}
}


2. Add the following code to the Cargo.toml file to tell Rustc what type of library to generate.

[lib]
name = "sum"
crate-type = ["staticlib"]
path = "src/lib.rs"


Cross-Compilation

1. Install armv7 target:

rustup target add armv7a-none-eabi


2. Generate static library file:

PS C:\Users\LiuKang\Desktop\RUST\rust_to_c> cargo build --target=armv7a-none-eabi --release --verbose
          Fresh rust_to_c v0.1.0 (C:\Users\LiuKang\Desktop\RUST\rust_to_c)
       Finished release [optimized] target(s) in 0.01s


Generate Header File

1. Install cbindgen, cbindgen generates C/C++11 header file from the rust library:

cargo install --force cbindgen


2. Create a new cbindgen.toml file under the project folder:

3. Generate header file:

cbindgen --config cbindgen.toml --crate rust_to_c --output sum.h


Call Rust Library File

1. Put the generated sum.h and sum.a files into the rt-thread\bsp\qemu-vexpress-a9\applications directory

2. Modify the SConscript file and add static library:

from building import *   cwd     = GetCurrentDir()
   src     = Glob('*.c') + Glob('*.cpp')
   CPPPATH = [cwd]   LIBS = ["libsum.a"]
   LIBPATH = [GetCurrentDir()]   group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, LIBS = LIBS, LIBPATH = LIBPATH)   Return('group')


3. Call the sum function in the main function and get the return value and printf the value.

#include <stdint.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <rtthread.h>
   #include "sum.h"   int main(void)
   {
       int32_t tmp;       tmp = sum(1, 2);
       printf("call rust sum(1, 2) = %d\n", tmp);       return 0;
   }


4. In RT-Thread Env environment, use scons to compile the project and run:

LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9
      $ scons -j6
      scons: Reading SConscript files ...
      scons: done reading SConscript files.      scons: warning: you do not seem to have the pywin32 extensions installed;
      parallel (-j) builds may not work reliably with open Python files.
      File "D:\software\env_released_1.2.0\env\tools\Python27\Scripts\scons.py", line 204, in <module>
      scons: Building targets ...
      scons: building associated VariantDir targets: build
      LINK rtthread.elf
      arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin
      arm-none-eabi-size rtthread.elf
     text    data     bss     dec     hex filename
   628220    2148   86700  717068   af10c rtthread.elf
      scons: done building targets.      LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9
      $ qemu.bat
      WARNING: Image format was not specified for 'sd.bin' and probing guessed raw.
   Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
   Specify the 'raw' format explicitly to remove the restrictions.   \ | /
      - RT -     Thread Operating System
   / | \     4.0.4 build Jul 28 2021
   2006 - 2021 Copyright by rt-thread team
      lwIP-2.1.2 initialized!
      [I/sal.skt] Socket Abstraction Layer initialize success.
      [I/SDIO] SD card capacity 65536 KB.
      [I/SDIO] switching card to high speed failed!
      call rust sum(1, 2) = 3
      msh />


Add, Subtract, Multiply and Divide

1. We can implement some complicated math in rust. In the lib.rs file, use the rust language to implement add, subtract, multiply and divide:

#![no_std]
     use core::panic::PanicInfo;
     #[no_mangle]
     pub extern "C" fn add(a: i32, b: i32) -> i32 {
         a + b
     }     #[no_mangle]
     pub extern "C" fn subtract(a: i32, b: i32) -> i32 {
         a - b
     }     #[no_mangle]
     pub extern "C" fn multiply(a: i32, b: i32) -> i32 {
         a * b
     }     #[no_mangle]
     pub extern "C" fn divide(a: i32, b: i32) -> i32 {
         a / b
     }     #[panic_handler]
     fn panic(_info:&PanicInfo) -> !{
         loop{}
     }


2. Build library files and header files and place them in the application directory

3. Use scons to compile, if errors jumped on link up, find the solution on its official Github.

LINK rtthread.elf
      d:/software/env_released_1.2.0/env/tools/gnu_gcc/arm_gcc/mingw/bin/../lib/gcc/arm-none-eabi/5.4.1/armv7-ar/thumb\libgcc.a(_arm_addsubdf3.o): In function `__aeabi_ul2d':
      (.text+0x304): multiple definition of `__aeabi_ul2d'
      applications\libsum.a(compiler_builtins-9b744f6fddf5e719.compiler_builtins.20m0qzjq-cgu.117.rcgu.o):/cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.35/src/float/conv.rs:143: first defined here
      collect2.exe: error: ld returned 1 exit status
      scons: *** [rtthread.elf] Error 1
      scons: building terminated because of errors.


4. Modify rtconfig.py file, add the link parameter --allow-multiple-definition:

DEVICE = ' -march=armv7-a -marm -msoft-float'
       CFLAGS = DEVICE + ' -Wall'
       AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__ -I.'
       LINK_SCRIPT = 'link.lds'
       LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors,--allow-multiple-definition'+\
                         ' -T %s' % LINK_SCRIPT       CPATH = ''
       LPATH = ''


5. Compile and run QEMU:

LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9
      $ scons -j6
      scons: Reading SConscript files ...
      scons: done reading SConscript files.      scons: warning: you do not seem to have the pywin32 extensions installed;
      parallel (-j) builds may not work reliably with open Python files.
      File "D:\software\env_released_1.2.0\env\tools\Python27\Scripts\scons.py", line 204, in <module>
      scons: Building targets ...
      scons: building associated VariantDir targets: build
      LINK rtthread.elf
      arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin
      arm-none-eabi-size rtthread.elf
     text    data     bss     dec     hex filename
   628756    2148   86700  717604   af324 rtthread.elf
      scons: done building targets.      LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9
      $ qemu.bat
      WARNING: Image format was not specified for 'sd.bin' and probing guessed raw.
       Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
       Specify the 'raw' format explicitly to remove the restrictions.   \ | /
      - RT -     Thread Operating System
   / | \     4.0.4 build Jul 28 2021
   2006 - 2021 Copyright by rt-thread team
      lwIP-2.1.2 initialized!
      [I/sal.skt] Socket Abstraction Layer initialize success.
      [I/SDIO] SD card capacity 65536 KB.
      [I/SDIO] switching card to high speed failed!
      call rust sum(1, 2) = 3
      call rust subtract(2, 1) = 1
      call rust multiply(2, 2) = 4
      call rust divide(4, 2) = 2


Call C in Rust

Great to know that Rust can be called in C code; let’s give a try to call the rt_kprintf function in Rust:


Modify the lib.rs File

// The imported rt-thread functions list
    extern "C" {
        pub fn rt_kprintf(format: *const u8, ...);
    }    #[no_mangle]
    pub extern "C" fn add(a: i32, b: i32) -> i32 {
        unsafe {
            rt_kprintf(b"this is from rust\n" as *const u8);
        }
        a + b
    }


Generate Library File

cargo build --target=armv7a-none-eabi --release --verbose
       Compiling rust_to_c v0.1.0 (C:\Users\LiuKang\Desktop\RUST\rust_to_c)
         Running `rustc --crate-name sum --edition=2018 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type staticlib --emit=dep-info,link -C opt-level=3 -C embed-bitcode=no -C metadata=a
    0723fa112c78339 -C extra-filename=-a0723fa112c78339 --out-dir C:\Users\LiuKang\Desktop\RUST\rust_to_c\target\armv7a-none-eabi\release\deps --target armv7a-none-eabi -L dependency=C:\Users\LiuKang\Desktop\RUS
    T\rust_to_c\target\armv7a-none-eabi\release\deps -L dependency=C:\Users\LiuKang\Desktop\RUST\rust_to_c\target\release\deps`
        Finished release [optimized] target(s) in 0.11s

Run

Copy the library files generated by rust into the application directory.

LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9                                                       
    $ scons -j6                                                                                                             
    scons: Reading SConscript files ...                                                                                  
    scons: done reading SConscript files.                                                                                                     
    scons: warning: you do not seem to have the pywin32 extensions installed;                                                   
            parallel (-j) builds may not work reliably with open Python files.                                                  
    File "D:\software\env_released_1.2.0\env\tools\Python27\Scripts\scons.py", line 204, in <module>                            
    scons: Building targets ...                                                                                                 
    scons: building associated VariantDir targets: build                                                                        
    LINK rtthread.elf                                                                                                           
    arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin                                                                   
    arm-none-eabi-size rtthread.elf                                                                                             
       text    data     bss     dec     hex filename                                                                            
     628812    2148   90796  721756   b035c rtthread.elf                                                                        
    scons: done building targets.                                                                                                   LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9                                                       
    $ qemu.bat                                                                                                                  
    WARNING: Image format was not specified for 'sd.bin' and probing guessed raw.                                               
             Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.    
             Specify the 'raw' format explicitly to remove the restrictions.                                                         \ | /                                                                                                                      
    - RT -     Thread Operating System                                                                                          
     / | \     4.0.4 build Jul 28 2021                                                                                          
     2006 - 2021 Copyright by rt-thread team                                                                                    
    lwIP-2.1.2 initialized!                                                                                                     
    [I/sal.skt] Socket Abstraction Layer initialize success.                                                                    
    [I/SDIO] SD card capacity 65536 KB.                                                                                         
    [I/SDIO] switching card to high speed failed!                                                                               
    this is from rust                                                                                                           
    call rust sum(1, 2) = 3                                                                                           
    call rust subtract(2, 1) = 1                                                                                                
    call rust multiply(2, 2) = 4                                                                                                
    call rust divide(4, 2) = 2                                                                                     
    msh />

Rust (programming language) Library

Published at DZone with permission of Nath Abby. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Tarantool: Speeding Up Development With Rust
  • Segmentation Violation and How Rust Helps Overcome It
  • While Performing Dependency Selection, I Avoid the Loss Of Sleep From Node.js Libraries' Dangers
  • Rust and WebAssembly: Unlocking High-Performance Web Apps

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!