最新电影在线观看,jrs低调看直播,avav天堂,囯产精品宾馆在线精品酒店,亚洲精品成人区在线观看

Rust 為什么適合嵌入式開發?

Rust 作為一門年輕的語言,聚焦與安全、并發、高性能等特點,號稱能替代 C/C++,那么究竟有多少優點能值得我們來切換呢?本文將告訴你為什么 Rust 適合嵌入式開發。

工具鏈

  1. 輕松搭建各種不同類型的芯片編譯環境,使用 cargo、rustup 等命令快速搭建新的環境。
  2. 統一的編譯、調試工具、下載工具, 如cargo build,cargo falsh,probe-rs
  3. 快速生成代碼文檔,cargo doc直接生成網頁文檔,能讓新手快速了解整個項目的模塊、接口框架。

  1. 內置代碼格式化工具 fmt,輕松就各個代碼文件統一格式,標準規范,團隊作戰無需在吐槽隊友的代碼風格,cargo fmt 后格式都會統一好,新手無需學習新公司的編碼格式規范,公司也無需過多培訓編碼格式規范。

庫的集成

  1. 移植優勢

可移植性移植是嵌入式開發的一個大問題,每個工作可能或多或少會考慮一些模塊的可移植性,想進來在不同框架不同平臺上能夠共有這些模塊,避免重復造輪子。Rust 則提供了高效的方法來保證庫能夠輕松移植,避免庫接口域業務接口雜糅到一起。trait 等特性讓 Rust 的庫能在不同的 CPU 如 ARM 或 RISV-V 甚至操作系統上方便得使用,無需過多關注庫的文件數量、無需手動添加庫的每個文件,僅僅只需在toml文件中添加庫的名字、版本、開啟所需的featues即可。在 Rust 中你可以輕松得將各種 IIC 的傳感器庫添加到自己的工程,很少花時間在適配上。

[dependencies]
panic-halt = "0.2.0"
ufmt = "0.2.0"
nb = "1.1.0"
embedded-hal = "1.0"
pwm-pca9685 = "1.0.0"
infrared = "0.14.1"
embedded-storage = "0.2"

[dependencies.embedded-hal-v0]
version = "0.2.3"
package = "embedded-hal"

2.Rust 官方發布了許多標準的庫,基于這些庫能簡化開發、指導用戶完成統一的適配接口。Rust 社區也非常活躍,發布了大量的開源庫。

As part of the Rust open source project, support for embedded systems is driven by a best-in-class open source community with support from commercial partners.

調試

Rust 生成的固件能使用 openocd 來輕松 gdb 調試,與 C/C++ 完全一樣,單步、斷電、查看等操作都支持。無需擔心調試障礙。

(gdb) break main
Breakpoint 1 at 0x8000d18: file examples/hello.rs, line 15.

(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, main () at examples/hello.rs:15
15          let mut stdout = hio::hstdout().unwrap();

語言優勢

1.內存安全優勢。

C/C++嵌入式工程師肯定知道,經常在編碼完成后,燒錄程序到芯片測試運行,經常會出現莫名的內存泄露、異常退出甚至死機的現象,這種內存問題有時非常難怕查,也許編碼十分鐘調試兩小時。當然目前也有一些先進的工具用來輔助調試,如 ASan,Valgrind、Memcheck 等工具,但這些工具本身就需要復雜的調試手段,需要仔細查看日志才能得出結果,但是對于某些資源受限嵌入式設備,很難使用這些工具來輔助排查。對于新手來說學習這些工具的使用就讓人頭疼。而 Rust 天生保證內存安全,沒有豐富的 Rust 經驗很難寫出能讓內存異常的代碼,是的你沒聽錯,Rust 對于新手保護特別友好,需要有經驗的人才能故意寫出不安全的代碼。Rust 的生命周期的約束使得實現內存安全而且零成本,也就是無需在時間和空間上浪費資源。

2.語法優勢:語法中新的枚舉,閉包、異步、流控、變量生命周期控制、安全宏等,基于這些基礎語法能最方便、便捷的表達問題的邏輯,無需使用太多的技巧。讓編程更加簡潔和優雅。

// 定義一個數組,并初始化數組內容全部為 0x5f
let mut uart_rx_buf:[u8; 100] = [0x5f; 100];

// 定義一個閉包
let f_max_closue = |a: u32, b: u32| -> bool {
    a > b
}
let max = f_max_closue(1, 2);
// 異步函數
let rst = rx.read().wait;

Rust 作為強類型的語言,但是在使用時無需過多指定變量類型,Rust 編譯器會自動推導變量的類型,并基于生命周期的約束可以重復使用變量名,原理上保證使用這些語法就像 C 語言一樣安全,但是用起來像 Python 一樣方便。

3.線程安全,無畏并發

Rust makes it impossible to accidentally share state between threads. Use any concurrency approach you like and you’ll still get Rust’s strong guarantees

一般來說 Rust 與其他語言也會面臨同一樣的并發問題。對于嵌入式軟件環境,包括:

  • 多線程
  • 多核處理器
  • 中斷處理

對于以上三種常見并發的問題,Rust 也提供了高效的解決方案,如定義原子類型、臨界類型、互斥體防止被中斷影響。同時也在編譯期間檢測多線程引起死鎖風險,讓風險扼殺在編譯期間。目前已經有優秀的embassy,rtic等框架提供異步操作系統。

4.智能的編譯提示,對于編譯時的錯誤,給出詳細的原因,對于有風險的代碼段給出解決的意見,從代碼編寫階段提高代碼質量,無需在調試時去發現再優化,讓程序員花給多的時間來考慮代碼邏輯,業務邏輯,避免低效的調試過程。

5.輕松銜接 C/C++的代碼,零成本接口綁定

Integrate Rust into your existing C codebase or leverage an existing SDK to write a Rust application.

如果目前你的項目無法使用 Rust 來完成所有的模塊,你也可以使用 FFF 機制來輕松綁定原項目的 C/C++接口,能夠輕松與 C/C++互相操作。可以使用bindgen命令來輕松構建外部接口,也可在build.rs中編譯 C/C++ 文件,也能 C/C++ 調用庫文件如*.a。輕松集成。

/* File: cool_bindings.rs */
#[repr(C)]
pub struct CoolStruct {
    pub x: cty::c_int,
    pub y: cty::c_int,
}

pub extern "C" fn cool_function(
    i: cty::c_int,
    c: cty::c_char,
    cs: *mut CoolStruct
);
pub extern "C" fn cool_function( ... );

extern crate cc;

fn main() {
    cc::Build::new()
        .file("foo.c")
        .compile("libfoo.a");
}

6.底層控制能力

Rust 也提供了接口能盡可能安全訪問地訪問底層接口,如 PAC 包用來抽象微控制器的外設寄存器的訪問,能編譯成高效的二進制代碼且接口容易使用,用戶無需太多關注寄存器各域的位置,只需聚焦于芯片手冊來操作各域的值,不會出現移位錯或寫錯的低級錯誤。

#![no_std]
#![no_main]

extern crate panic_halt; // panic handler

use cortex_m_rt::entry;
use tm4c123x;

#[entry]
pub fn init() -> (Delay, Leds) {
    let cp = cortex_m::Peripherals::take().unwrap();
    let p = tm4c123x::Peripherals::take().unwrap();

    let pwm = p.PWM0;
    pwm.ctl.write(|w| w.globalsync0().clear_bit());
    // Mode = 1 => Count up/down mode
    pwm._2_ctl.write(|w| w.enable().set_bit().mode().set_bit());
    pwm._2_gena.write(|w| w.actcmpau().zero().actcmpad().one());
    // 528 cycles (264 up and down) = 4 loops per video line (2112 cycles)
    pwm._2_load.write(|w| unsafe { w.load().bits(263) });
    pwm._2_cmpa.write(|w| unsafe { w.compa().bits(64) });
    pwm.enable.write(|w| w.pwm4en().set_bit());
}
聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 3
收藏 3
關注 19
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧