Using Rust for Embedded Development

Follow+Star PublicAccount, don’t miss exciting content
Using Rust for Embedded Development
Author | Papalymo
Rust is a widely used programming language in the 21st century. One widely recognized aspect of Rust is that it can run on diverse targets, from desktop and server devices to resource-constrained embedded devices.

What is Rust

Rust is a language that empowers everyone to build reliable and efficient software.
  • High Performance: Incredible speed and high memory efficiency
  • Reliability: Eliminates various memory errors at compile time
  • Productivity: Excellent documentation, friendly compiler, and clear error messages

Why Use Rust for Embedded Development

The design philosophy of Rust: safe and high performance. The design philosophy of Rust is exactly what embedded development needs.
Most problems in embedded software during execution are caused by memory issues. Rust can be considered a compiler-oriented language. It ensures safe memory usage during the compilation phase.
Currently, the mainstream development language for embedded systems is still C, and we cannot simply re-implement the underlying logic in Rust. However, Rust can be embedded in C code.

Calling Rust from C

To call Rust code from C code, we need to package the Rust source code into a static library file and link it during the C code compilation.

Create a Lib Library

1. In Clion, use <span>cargo init --lib rust_to_c</span> to create a lib library. Add the following code to lib.rs to compute the sum of two integers using Rust:
 1#![no_std]
 2use core::panic::PanicInfo;
 3
 4#[no_mangle]
 5pub extern "C" fn sum(a: i32, b: i32) -> i32 {
 6    a + b
 7}
 8
 9#[panic_handler]
10fn panic(_info:&PanicInfo) -> !{
11    loop{}
12}
Add the following code to the Cargo.toml file to generate the static library file:
1[lib]
2name = "sum"
3crate-type = ["staticlib"]
4path = "src/lib.rs"

Cross Compilation

1. Install armv7 target:
1rustup target add armv7a-none-eabi
2. Generate the static library file:
1PS C:\Users\LiuKang\Desktop\RUST\rust_to_c> cargo build --target=armv7a-none-eabi --release --verbose
2       Fresh rust_to_c v0.1.0 (C:\Users\LiuKang\Desktop\RUST\rust_to_c)
3    Finished release [optimized] target(s) in 0.01s

Generate Header Files

1. Install cbindgen](https://github.com/eqrion/cbindgen)), cbindgen generates C/C++ 11 header files from Rust libraries:
1cargo install --force cbindgen
2. Create a new file <span>cbindgen.toml</span> in the project folder:
3. Generate the header file:
1cbindgen --config cbindgen.toml --crate rust_to_c --output sum.h

Calling Rust Library Files

1. Place the generated <span>sum.h</span> and <span>sum.a</span> files into the <span>rt-thread\bsp\qemu-vexpress-a9\applications</span> directory
2. Modify the SConscript file to add the static library:
 1from building import *
 2
 3cwd     = GetCurrentDir()
 4src     = Glob('*.c') + Glob('*.cpp')
 5CPPPATH = [cwd]
 6
 7LIBS = ["libsum.a"]
 8LIBPATH = [GetCurrentDir()]
 9
10group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, LIBS = LIBS, LIBPATH = LIBPATH)
11
12Return('group')
3. Call the sum function in the main function and get the return value
 1#include <stdint.h>
 2#include <stdio.h>
 3#include <stdlib.h>
 4#include <rtthread.h>
 5#include "sum.h"
 6
 7int main(void)
 8{
 9    int32_t tmp;
10
11    tmp = sum(1, 2);
12    printf("call rust sum(1, 2) = %d\n", tmp);
13
14    return 0;
15}
4. In the env environment, use scons to compile the project:
 1   LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9
 2   $ scons -j6
 3   scons: Reading SConscript files ...
 4   scons: done reading SConscript files.
 5
 6   scons: warning: you do not seem to have the pywin32 extensions installed;
 7   parallel (-j) builds may not work reliably with open Python files.
 8   File "D:\software\env_released_1.2.0\env\tools\Python27\Scripts\scons.py", line 204, in <module>
 9   scons: Building targets ...
10   scons: building associated VariantDir targets: build
11   LINK rtthread.elf
12   arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin
13   arm-none-eabi-size rtthread.elf
14  text    data     bss     dec     hex filename
15628220    2148   86700  717068   af10c rtthread.elf
16   scons: done building targets.
17
18   LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9
19   $ qemu.bat
20   WARNING: Image format was not specified for 'sd.bin' and probing guessed raw.
21Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
22Specify the 'raw' format explicitly to remove the restrictions.
23
24\ | /
25   - RT -     Thread Operating System
26/ | \     4.0.4 build Jul 28 2021
272006 - 2021 Copyright by rt-thread team
28   lwIP-2.1.2 initialized!
29   [I/sal.skt] Socket Abstraction Layer initialize success.
30   [I/SDIO] SD card capacity 65536 KB.
31   [I/SDIO] switching card to high speed failed!
32   call rust sum(1, 2) = 3
33   msh />

Add, Subtract, Multiply, Divide

1. In the lib.rs file, implement addition, subtraction, multiplication, and division using Rust:
 1  #![no_std]
 2  use core::panic::PanicInfo;
 3
 4
 5  #[no_mangle]
 6  pub extern "C" fn add(a: i32, b: i32) -> i32 {
 7      a + b
 8  }
 9
10  #[no_mangle]
11  pub extern "C" fn subtract(a: i32, b: i32) -> i32 {
12      a - b
13  }
14
15  #[no_mangle]
16  pub extern "C" fn multiply(a: i32, b: i32) -> i32 {
17      a * b
18  }
19
20  #[no_mangle]
21  pub extern "C" fn divide(a: i32, b: i32) -> i32 {
22      a / b
23  }
24
25  #[panic_handler]
26  fn panic(_info:&PanicInfo) -> !{
27      loop{}
28  }
2. Generate the library file and header file and place them in the application directory
3. Use scons to compile. If there are linking errors, a solution can be found in the Rust GitHub repository’s issues (https://github.com/rust-lang/compiler-builtins/issues/353):
1   LINK rtthread.elf
2   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':
3   (.text+0x304): multiple definition of `__aeabi_ul2d'
4   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
5   collect2.exe: error: ld returned 1 exit status
6   scons: *** [rtthread.elf] Error 1
7   scons: building terminated because of errors.
4. Modify rtconfig.py to add the linking parameter --allow-multiple-definition:
1    DEVICE = ' -march=armv7-a -marm -msoft-float'
2    CFLAGS = DEVICE + ' -Wall'
3    AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__ -I.'
4    LINK_SCRIPT = 'link.lds'
5    LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors,--allow-multiple-definition'+\
6                      ' -T %s' % LINK_SCRIPT
7
8    CPATH = ''
9    LPATH = ''
5. Compile and run qemu:
 1   LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9
 2   $ scons -j6
 3   scons: Reading SConscript files ...
 4   scons: done reading SConscript files.
 5
 6   scons: warning: you do not seem to have the pywin32 extensions installed;
 7   parallel (-j) builds may not work reliably with open Python files.
 8   File "D:\software\env_released_1.2.0\env\tools\Python27\Scripts\scons.py", line 204, in <module>
 9   scons: Building targets ...
10   scons: building associated VariantDir targets: build
11   LINK rtthread.elf
12   arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin
13   arm-none-eabi-size rtthread.elf
14  text    data     bss     dec     hex filename
15628756    2148   90796  721756   b035c rtthread.elf
15   scons: done building targets.
16
17   LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9
18   $ qemu.bat
19   WARNING: Image format was not specified for 'sd.bin' and probing guessed raw.
20             Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
21             Specify the 'raw' format explicitly to remove the restrictions.
22
23     \ | /                                                                                                                       
24    - RT -     Thread Operating System                                                                                          
25     / | \     4.0.4 build Jul 28 2021                                                                                          
26     2006 - 2021 Copyright by rt-thread team                                                                                     
27     lwIP-2.1.2 initialized!                                                                                                      
28     [I/sal.skt] Socket Abstraction Layer initialize success.                                                                 
29     [I/SDIO] SD card capacity 65536 KB.                                                                                         
30     [I/SDIO] switching card to high speed failed!                                                                                
31     this is from rust                                                                                                            
32     call rust sum(1, 2) = 3                                                                                            
33     call rust subtract(2, 1) = 1                                                                                                 
34     call rust multiply(2, 2) = 4                                                                                                 
35     call rust divide(4, 2) = 2                                                                                     
Rust Calling C
Rust code can also call C code. We can call the rt_kprintf function in Rust code:

Modify the lib.rs File

 1    // List of imported rt-thread functions
 2    extern "C" {
 3        pub fn rt_kprintf(format: *const u8, ...);
 4    }
 5
 6    #[no_mangle]
 7    pub extern "C" fn add(a: i32, b: i32) -> i32 {
 8        unsafe {
 9            rt_kprintf(b"this is from rust\n\0" as *const u8);
10        }
11        a + b
12    }

Generate Library File

1    cargo build --target=armv7a-none-eabi --release --verbose
2       Compiling rust_to_c v0.1.0 (C:\Users\LiuKang\Desktop\RUST\rust_to_c)
3         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
4    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
5    T\rust_to_c\target\armv7a-none-eabi\release\deps -L dependency=C:\Users\LiuKang\Desktop\RUST\rust_to_c\target\release\deps`
6        Finished release [optimized] target(s) in 0.11s

Run

Copy the library files generated by Rust to the application directory.
 1    LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9                                                        
 2    $ scons -j6                                                                                                              
 3    scons: Reading SConscript files ...                                                                                  
 4    scons: done reading SConscript files.                                                                                                      
 5    scons: warning: you do not seem to have the pywin32 extensions installed;                                                    
 6            parallel (-j) builds may not work reliably with open Python files.                                                 
 7    File "D:\software\env_released_1.2.0\env\tools\Python27\Scripts\scons.py", line 204, in <module>                            
 8    scons: Building targets ...                                                                                                 
 9    scons: building associated VariantDir targets: build                                                                                                                                        
10    LINK rtthread.elf                                                                                                            
11    arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin                                                                    
12    arm-none-eabi-size rtthread.elf                                                                                              
13       text    data     bss     dec     hex filename                                                                                                                                            
14     628812    2148   90796  721756   b035c rtthread.elf                                                                                                                                        
15    scons: done building targets.                                                                                                
16
    LiuKang@DESKTOP-538H6DE D:\repo\github\rt-thread\bsp\qemu-vexpress-a9                                                        
18    $ qemu.bat                                                                                                                  
19    WARNING: Image format was not specified for 'sd.bin' and probing guessed raw.                                                
20             Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.    
21             Specify the 'raw' format explicitly to remove the restrictions.                                 
22
23     \ | /                                                                                                                       
24    - RT -     Thread Operating System                                                                                          
25     / | \     4.0.4 build Jul 28 2021                                                                                          
26     2006 - 2021 Copyright by rt-thread team                                                                                     
27     lwIP-2.1.2 initialized!                                                                                                      
28     [I/sal.skt] Socket Abstraction Layer initialize success.                                                                 
29     [I/SDIO] SD card capacity 65536 KB.                                                                                         
30     [I/SDIO] switching card to high speed failed!                                                                                
31     this is from rust                                                                                                            
32     call rust sum(1, 2) = 3                                                                                            
33     call rust subtract(2, 1) = 1                                                                                                 
34     call rust multiply(2, 2) = 4                                                                                                 
35     call rust divide(4, 2) = 2                                                                                     
Source:
https://club.rt-thread.org/ask/article/2944.html
Disclaimer: The materials of this article are sourced from the internet, and the copyright belongs to the original author. If there are any copyright issues, please contact me to delete.
———— END ————
Using Rust for Embedded Development
●Column “Embedded Tools
●Column “Embedded Development”
●Column “Keil Tutorial”
●Selected Tutorials from Embedded Column
Follow the public account reply “Join Group” to join the technical exchange group according to the rules, reply “1024” to see more content.
Using Rust for Embedded Development
Using Rust for Embedded Development
Click “Read Original” to see more shares.

Leave a Comment