使用 Rust 进行嵌入式开发

2023-05-16

05e3df27bb037073c76a308c204a4cae.png

作者: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:\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

生成头文件

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-thread\bsp\qemu-vexpress-a9\applications 目录下

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

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

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 />

加减乘除

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/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、修改 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   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   86700  717604   af324 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.
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(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 调用 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 rust\n\0" 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:\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

运行

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

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
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                                                                                     
36    msh />

db2b71213746bfd33cb7b2e3e0858671.png

1.Arm全新物联网解决方案,缩短2年芯片开发周期,再造一个“智能手机市场”

2.树莓派Zero 2 W正式发布!一起了解一下!

3.一本系统性介绍RISC-V开发技术的新书出版了~

4.多核CPU和单核的区别~

5.2021慕尼黑华南电子展延期通知

6.原来搞单片机也可以面向对象!

1bf1db528bef6e6439feef022a8b5931.gif

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Rust 进行嵌入式开发 的相关文章

随机推荐

  • 国产开源基础软件MiniGUI宣布支持RT-Thread!

    北京飞漫软件技术有限公司宣布 xff1a 将在 MiniGUI 4 0 2 版本中支持国产操作系统 RT Thread xff01 这是自 MiniGUI 创始人魏永明在本月初宣布启动 1998 年年底 xff0c 魏永明开始在清华大学开发
  • 既然C编译器是C语言写的,那第一个C编译器是怎样来的?

    来源 xff1a 伯乐在线 xff0c 作者 xff1a Chaobs 首先向C语言之父Dennis Ritchie致敬 xff01 当今几乎所有的实用的编译器 解释器 xff08 以下统称编译器 xff09 都是用C语言编写的 xff0c
  • Oracle推出全球首个自治操作系统~

    原创 xff1a 程序员的那些事 xff08 id xff1a iProgrammer xff09 导读 xff1a 保持系统的修补和安全是 IT 部门目前面临的最大挑战之一 在大规模云环境中 xff0c 此类任务乏味 容易出错 xff0c
  • 基于Autosar的网络安全理解

    目录 1 车载网络安全说明 2 常用的安全加密算法 2 1 对称加密 2 2 非对称加密 2 3 混合加密 2 4 单向散列函数 2 5 消息认证码 2 6 数字签名 3 Autosar的加密模块 3 1 模块说明 3 2 关键数据流说明
  • Linux实用程序——Make快速入门

    1 Make make 是 linux 系统的实用程序 它用于管理对于大型程序的自动编译任务 xff0c 自动决定程序某一部分需要重新编译 xff0c 并发出编译指令 虽然 xff0c 我们最常见于 C 语言程序的编译 但是 xff0c m
  • 干货!学习STM32的一些经验分享

    前言 前两天在群里看到群友们在讨论学习STM32的话题 xff0c 并且今天也有一位机械专业的准研究生读者也问了STM32的入门问题 正好我也有一点点经验 xff0c 所以试着分享一下这个话题 我也不是什么大神 xff0c 只是一名普通的工
  • 为什么买了开发板只能吃灰,还是学不会嵌入式?

    经常有同学问我 xff1a 老师 xff0c 我想学嵌入式 xff0c 应该买哪个板子 xff1f 这个问题本身就是错的 如果你去问10个买过开发板的人 xff0c 至少有8个最终都吃灰了 xff0c 而且他也没通过这个板子以及板子附带的所
  • 基于LiteOS的智慧农业案例实验分享!

    最近在指导一位读者朋友做毕业设计 xff0c 该毕设是关于端云互通的 xff0c 基于小熊派 43 LiteOS 43 华为云 在指导他的过程中我也学到了不少东西 xff0c 这里通过一个案例实验 xff08 智慧农业 xff09 给大家分
  • 漫谈C变量—为什么嵌入式项目中常用静态变量?

    在C语言中 xff0c 按照生命周期来分 xff0c 变量只有两类 xff1a 静态变量和动态变量 其中 xff0c 静态变量是指 xff0c 在编译时刻 xff08 Compiling time xff09 变量的地址和大小都已经确定下来
  • 10月1日后,GitHub用main替代master

    转自 xff1a 开源中国 GitHub 官方表示 xff0c 从 2020 年 10 月 1 日起 xff0c 在该平台上创建的所有新的源代码仓库将默认被命名为 34 main 34 xff0c 而不是原先的 34 master 34 值
  • C++在嵌入式中表现如何?

    这是知乎嵌入式领域的一个热门话题 xff0c 原文链接 xff1a https www zhihu com question 374663834 几个高赞回答 xff1a idea4good xff1a 先说结论 xff1a 嵌入式 单片机
  • 选微处理器MPU,还是单片机MCU?

    每项新应用设计都需要一个单片机或微处理器 当在两者之间选择其一时 xff0c 需要考虑一些因素 以下是微处理器 单片机的概述和对比 考虑选择微处理器 MPU 或者单片机 MCU 时 xff0c 应用类型通常是关键因素 另一方面 xff0c
  • 图解FreeRTOS 原理系列之任务管理器基本框架!

    导读 学习梳理一下FreeRTOS任务管理单元实现思路 xff0c 代码分析基于V10 4 3 从本文开始计划写个图解freeRTOS内核系列笔记分享给朋友们 xff0c 希望大家喜欢 本文主要学习梳理FreeRTOS任务管理器的基本原理
  • 一文带你快速理解FreeRTOS代码规范~

    导读 遇到些朋友感觉FreeRTOS内核代码看起来很不习惯 xff0c 不习惯其编码风格 xff0c 本文就来梳理一下其代码规范 xff0c 便于提高阅读其代码的效率 代码基于FreeRTOS V10 4 3 FreeRTOS代码结构 其内
  • [Adaptive Autosar]深入理解--Persistency

    目录 1 Per架构 2 Per初始化 3 Per错误处理 4 多进程访问 5 冗余存储 6 安装和更新per数据 7 Key Value 方式 8 file storage 方式 9 典型使用代码 Persistency模块对比 CP 中
  • 用Excel教会你PID算法!

    01 引入PID 电机控制 这样是没有反馈的 xff0c 也就是说我们完全相信输入的数字 xff0c 且是理想化的模型 xff0c 比如输入占空比为50 的25Kz的PWM xff0c 车轮速度为1m s xff0c 实际产品中会受到各种这
  • 带你快速理解FreeRTOS的代码规范~

    导读 遇到些朋友感觉FreeRTOS内核代码看起来很不习惯 xff0c 不习惯其编码风格 xff0c 本文就来梳理一下其代码规范 xff0c 便于提高阅读其代码的效率 代码基于FreeRTOS V10 4 3 FreeRTOS代码结构 其内
  • 单片机串口最底层的本质​!

    嵌入式开发中 xff0c UART串口是最常见的一种通信接口 xff0c 你知道为啥串口这么常见吗 xff1f 本文就带你深入了解串口最底层的本质内容 一 什么是串口通讯 xff1f 串行通讯是指仅用一根接收线和一根发送线就能将数据以位进行
  • 一个本科生学习嵌入式的心得~

    为毕业后能找到工作而读书 xff0c 本着务实精神 xff0c 从入学那一刻起就要开始准备找工作了 发这篇文章主要是针对大学刚接触嵌入式的同学 很多新手觉得嵌入式入门并不容易 xff0c 牵扯的内容 知识点太多 像C语言基础是否掌握 xff
  • 使用 Rust 进行嵌入式开发

    作者 xff1a RT Thread社区团队 liukang 原文链接 xff1a https club rt thread org ask article 2944 html Rust 是什么 Rust 是一门赋予每个人构建可靠且高效软件