应用 Rust 进行嵌入式 开发
发布时间:2022-11-29 11:20:57 所属栏目:语言 来源:
导读: Rust 的高性能、高可靠性和高生产力使它适合于嵌入式系统。 在过去的几年里,Rust 在程序员中获得了热情的追捧。技术潮流来来去去,所以很难将仅仅因为某项新技术而产生的兴奋与对某项技术的优点的兴奋区分开来
|
Rust 的高性能、高可靠性和高生产力使它适合于嵌入式系统。 在过去的几年里,Rust 在程序员中获得了热情的追捧。技术潮流来来去去,所以很难将仅仅因为某项新技术而产生的兴奋与对某项技术的优点的兴奋区分开来,但我认为 Rust 是一种真正设计良好的语言。它的目标是帮助开发者建立可靠和高效的软件,而且它从一开始就是为这个目的设计的。你可能听过一些 Rust 的关键特性,在这篇文章中,我会证明这些特性正是 Rust 也恰好适合嵌入式系统的原因。比如: 高性能:它速度快,内存利用率高 可靠性:在编译过程中可以消除内存错误 生产力:很棒的文档,友好的编译器,有用的错误信息,以及一流的工具化。它有一个集成的包管理器和构建工具,智能的多编辑器支持自动补完和类型检查、自动格式化等等。 为什么使用 Rust 进行嵌入式开发? Rust 的设计是为了保证安全和高性能。嵌入式软件会出现的问题主要是内存的问题。 从某种程度上说,Rust 是一种面向编译器的语言,所以你可以确保在编译时安全使用内存。以下是使用 Rust 在嵌入式设备上开发的一些好处: 强大的静态分析 灵活的内存 无畏的并发性 互操作性 可移植性 社区驱动 在这篇文章中,我使用开源的 RT-Thread 操作系统 来演示如何使用 Rust 进行嵌入式开发。 如何在 C 语言中调用 Rust 在 C 代码中调用 Rust 代码时,你必须将 Rust 源代码打包成静态库文件。当 C 代码编译时,将其链接进去。 用 Rust 创建一个静态库 在这个过程中,有两个步骤: 1、使用 cargo init --lib rust_to_c 在 Clion 中建立一个 lib 库。在 lib.rs 中加入以下代码。下面的函数计算两个类型为 i32 的值的总和并返回结果: #![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、在你的 Cargo.toml 文件中添加以下代码,以告诉 Rustc 要生成什么类型的库: [lib] name = "sum" crate-type = ["staticlib"] path = "src/lib.rs" 交叉编译 你可以针对你的目标平台进行交叉编译。假设你的嵌入式系统是基于 Arm 的,步骤很简单: $ rustup target add armv7a-none-eabi 生成静态库文件: $ cargo build --target=armv7a-none-eabi --release --verbose Fresh rust_to_c v0.1.0 Finished release [optimized] target(s) in 0.01s 生成头文件 你也需要头文件: 1、安装 cbindgen。cbindgen 工具会从 Rust 库中生成一个 C 或 C++11 的头文件: $ cargo install --force cbindgen 2、在你的项目文件夹下创建一个新的 cbindgen.toml 文件。 3、生成一个头文件: $ cbindgen --config cbindgen.toml --crate rust_to_c --output sum.h 调用 Rust 库文件 现在你可以对你的 Rust 库进行调用了。 1、把生成的 sum.h 和 sum.a 文件放到 rt-thread/bsp/qemu-vexpress-a9/applications 目录下。 2、修改 SConscript 文件并添加一个静态库: 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、在主函数中调用 sum 函数,得到返回值,并 printf 该值: #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、在 RT-Thread Env 环境中,使用 scons 来编译项目并运行: $ scons -j6 scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... [...] scons: done building targets. $ qemu.sh \ | / - RT - Thread Operating System / | \ 4.0.4 build Jul 28 2021 2006 - 2021 Copyright by rt-thread team lwIP-2.1.2 initialized! [...] call rust sum(1, 2) = 3 加、减、乘、除 你可以在 Rust 中实现一些复杂的数学运算。在 lib.rs 文件中,使用 Rust 语言来实现加、减、乘、除: #![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{} } 构建你的库文件和头文件,并把它们放在应用程序目录中。使用 scons 来编译。如果在链接过程中出现错误,请在官方 Github 页面 中找到解决方案。 修改 rtconfig.py 文件,并添加链接参数 --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 = '' 编译并运行 QEMU 来看看你的工作。 (编辑:云计算网_汕头站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐


浙公网安备 33038102330478号