如何使用 Rust 进行嵌入式开发?

新闻周刊 | 福布斯发布“区块链50强”榜单 7家中国公司入选

金色周刊是币妈妈推出的一档每周区块链行业总结栏目,内容涵盖一周重点新闻、矿业信息、项目动态、技术进展等行业动态。本文是其中的新闻周刊,带您一览本周区块链行业大事。 头条 ▌印度报业托拉斯:印度数字货币将在明年初推出 2月6日消息,据印度报业托拉斯:印度数字货币…

👇 星标嵌入式大杂烩」,一起进步!👇

作者:RT-Thread社区团队  liukang

原文链接:

https://club.rt-thread.org/ask/article/2944.html

Rust 是什么

Rust 是一门赋予每个人 构建可靠且高效软件能力的语言。

  • 高性能:速度惊人且内存利用率极高

  • 可靠性:在编译期就能消除各种内存错误

  • 生产力:出色的文档,友好的编译器和清晰的错误提示信息

为什么要用 Rust 进行嵌入式开发

Rust 的设计理念:既要安全,也要高性能。Rust 的设计理念完全是嵌入式开发所需要的。

嵌入式软件在运行过程中出现问题,大部分是由于内存引起的。Rust 语言可以说是一门面向编译器的语言。在编译期间,就能够确保你安全地使用内存。

目前,嵌入式的主流开发语言还是 C 语言,不能上来就把底层的逻辑用 Rust 重新实现一遍。但是可以在 C 代码中嵌入 Rust 语言。

C 调用 Rust

在 C 代码中调用 Rust 代码,需要我们将 Rust 源代码打包为静态库文件。在 C 代码编译时,链接进去。

创建 lib 库

1、在 Clion 中使用 cargo init --lib rust_to_c 建立 lib 库。添加以下代码到 lib.rs 中,使用 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}

在 Cargo.toml 文件中添加以下代码,生成静态库文件:

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

交叉编译

1、安装 armv7 target:

1rustup target add armv7a-none-eabi

2、生成静态库文件:

1PS C:UsersLiuKangDesktopRUSTrust_to_c> cargo build --target=armv7a-none-eabi --release --verbose
2       Fresh rust_to_c v0.1.0 (C:UsersLiuKangDesktopRUSTrust_to_c)
3    Finished release [optimized] target(s) in 0.01s

生成头文件

1、安装 cbindgen](https://github.com/eqrion/cbindgen)), cbindgen 从 rust 库生成 C/C++ 11 头文件:

1cargo install --force cbindgen

2、在项目文件夹下新建文件 cbindgen.toml 文件:

3、生成头文件:

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

调用 Rust 库文件

1、将生成的sum.h 以及 sum.a 文件放入 rt-threadbspqemu-vexpress-a9applications 目录下

2、修改 SConscript 文件,添加静态库:

 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、在 main 函数中调用 sum 函数, 并获取返回值

 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(12);
12    printf("call rust sum(1, 2) = %dn", tmp);
13
14    return 0;
15}

4、在 env 环境下,使用 scons 编译工程:

 1   [email protected]-538H6DE D:repogithubrt-threadbspqemu-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:softwareenv_released_1.2.0envtoolsPython27Scriptsscons.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   [email protected]-538H6DE D:repogithubrt-threadbspqemu-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(12) 3
33   msh />

加减乘除

1、在 lib.rs 文件中,使用 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、生成库文件和头文件并放在 application 目录下

3、使用 scons 编译,链接时报错,在 rust github 仓库的 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/thumblibgcc.a(_arm_addsubdf3.o): In function `__aeabi_ul2d':
3   (.text+0x304): multiple definition of `__aeabi_ul2d'
4   applicationslibsum.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、修改 rtconfig.py 文件, 添加链接参数 --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、编译并运行 qemu:

 1   [email protected]-538H6DE D:repogithubrt-threadbspqemu-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:softwareenv_released_1.2.0envtoolsPython27Scriptsscons.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   86700  717604   af324 rtthread.elf
16   scons: done building targets.
17
18   [email protected]-538H6DE D:repogithubrt-threadbspqemu-vexpress-a9
19   $ qemu.bat
20   WARNING: Image format was not specified for 'sd.bin' and probing guessed raw.
21    Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
22    Specify 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(12) 3
33   call rust subtract(21) 1
34   call rust multiply(22) 4
35   call rust divide(42) 2

Rust 调用 C

可以 在 C 代码中调用 Rust,那么在 Rust 中也可以调用 C 代码。我们在 Rust 代码中调用 rt_kprintf 函数:

修改 lib.rs 文件

 1    // 导入的 rt-thread 函数列表
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 rustn" as *const u8);
10        }
11        a + b
12    }

生成库文件

1    cargo build --target=armv7a-none-eabi --release --verbose
2       Compiling rust_to_c v0.1.0 (C:UsersLiuKangDesktopRUSTrust_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:UsersLiuKangDesktopRUSTrust_to_ctargetarmv7a-none-eabireleasedeps --target armv7a-none-eabi -L dependency=C:UsersLiuKangDesktopRUS
5    Trust_to_ctargetarmv7a-none-eabireleasedeps -L dependency=C:UsersLiuKangDesktopRUSTrust_to_ctargetreleasedeps`
6        Finished release [optimized] target(s) in 0.11s

运行

复制 rust 生成的库文件到 application 目录下。

 1    [email protected]-538H6DE D:repogithubrt-threadbspqemu-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:softwareenv_released_1.2.0envtoolsPython27Scriptsscons.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
17    [email protected]-538H6DE D:repogithubrt-threadbspqemu-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(12) 
3                                                                                           
33    call rust subtract(21) 1                                                                                                
34    call rust multiply(22) 4                                                                                                
35    call rust divide(42) 2                                                                                     
36    msh />                                                                                                                      

如何使用 Rust 进行嵌入式开发?

版权归原作者所有。如涉及作品版权问题,请联系我进行删除,感谢~



往期推荐:

跨平台构建工具,cmake是 yyds ? bjd !

Linux下嵌入式开发学习建议!

在公众号聊天界面回复1024,可获取嵌入式资源;回复 ,可查看文章汇总。


点击阅读原文,查看更多分享

英特尔:将在今年晚些时候上市区块链加速器芯片

财联社2月12日消息,英特尔周五表示,区块链加速器芯片将于今年晚些时候上市。

Click to rate this post!
[Total: 0 Average: 0]

人已赞赏
Rust开发

youki:Rust开发的容器运行时

2022-2-17 11:01:06

Rust开发每日优选

【Rust日报】2022-02-23 官方博客:Rust编译器的2022雄心

2022-2-24 10:14:45

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索