Follow+Star PublicAccount, don’t miss exciting content
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
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 = ''
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 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
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.
●Column “Embedded Development”
●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.
Click “Read Original” to see more shares.