Rust編程語言因其獨特的安全性、性能和生產(chǎn)力組合而受到關(guān)注。Rust旨在消除常見的編程負(fù)擔(dān)并處理編譯時use-after-free錯誤等問題。值得注意的是,它在不使用垃圾回收器的情況下實現(xiàn)了這一點,生成的機(jī)器代碼的性能可與C和C++相媲美。
在這個由三部分組成的博客系列中,Ferrous Systems 的高級工程師兼培訓(xùn)師Jonathan Pallant概述了Arm架構(gòu)的Rust支持,包括對 Ferrocene的介紹,F(xiàn)errocene 是用于任務(wù)關(guān)鍵型和安全關(guān)鍵型應(yīng)用的合格Rust工具鏈。對于任何考慮將Rust用于下一個基于Arm的項目的人來說,這個概述都是必不可少的。
本系列探討了從廣泛的Arm領(lǐng)域中挑選的三個示例,研究了在裸機(jī)、RTOS和Rich OS應(yīng)用程序上使用Rust的細(xì)節(jié)。此外,它還討論了Ruston Arm的現(xiàn)狀,重點介紹了Rust項目和第三方提供的功能和庫,無論是否有商業(yè)支持。
圖1:編寫Rust應(yīng)用程序的方法
第1部分:裸機(jī)系統(tǒng)
我們將探討的第一個領(lǐng)域是運行純Rust編寫的裸機(jī)應(yīng)用的微控制器案例。在第二部分中,我們將在其基礎(chǔ)上加入一個已有的用C或C++編寫的實時操作系統(tǒng)(RTOS)。
這里使用的術(shù)語“微控制器”指的是帶有集成SRAM(可能還有Flash)的小型片上系統(tǒng)(SoC)。在Arm架構(gòu)上,這些設(shè)備在AArch32模式下執(zhí)行T32指令集,但有些系統(tǒng)可能會使用A32指令集。這里討論的許多“裸機(jī)”問題同樣適用于較大應(yīng)用處理器上的低級代碼,比如安全啟動固件或虛擬機(jī)監(jiān)視器。然而,本節(jié)將著眼于運行在nRF52-DK開發(fā)套件上的NordicnRF52840微控制器。這款流行的微控制器包含一個ArmCortex-M4處理器,以及256KiB的SRAM和1MiB的Flash。
針對ArmCortex-M的裸機(jī)Rust固件可以依賴由Rust嵌入式設(shè)備工作組提供的啟動代碼,這些代碼封裝在一個名為cortex-m-rt的crate中。這個crate允許固件完全用Rust編寫——所需的少量內(nèi)聯(lián)匯編(例如,在main之前初始化數(shù)據(jù)段)被捆綁在cortex-m-rt內(nèi)部,它只需帶你走到Rust的fn main()函數(shù)處即可。
當(dāng)系統(tǒng)啟動并運行Rust代碼時,有一個豐富的驅(qū)動程序生態(tài)系統(tǒng)可供選擇。例如,nrf-hal項目為我們的nRF52840中的每個外設(shè)提供了驅(qū)動程序。實際上,許多基于Arm的微控制器都有一套出色的開源驅(qū)動程序,包括來自NordicSemi、STMicro和RaspberryPi的許多驅(qū)動。
像embedded-hal這樣的跨平臺抽象讓這些驅(qū)動程序可以用標(biāo)準(zhǔn)化的方式描述外設(shè),使用戶能夠構(gòu)建可重用的組件和庫,這些組件和庫可以在任何合適的實現(xiàn)上工作,即使跨越不同的芯片制造商。在2021年最近的芯片短缺期間,許多使用Rust的嵌入式系統(tǒng)開發(fā)者發(fā)現(xiàn)這一點非常有用,因為根據(jù)可用性更換微控制器變得容易得多。
如果您以前沒有見過裸機(jī)Rust代碼,圖2提供了一個針對nRF52840的完整“blinky”示例。
圖2:用于nRF52-DK的最小但完整的Rust“blinky”,使用提供UART驅(qū)動程序,GPIO等的開源板支持包。
如示例所示,Rust允許開發(fā)豐富的API來描述各種硬件接口,如LED和UART。然而,Rust編譯器內(nèi)置的強(qiáng)大優(yōu)化器產(chǎn)生的機(jī)器代碼與C編譯器產(chǎn)生的機(jī)器代碼大致相似。
圖1中顯示的Led類型(支持nrf52.leds.led_2值)在運行時不占用內(nèi)存。它是所謂的零大小類型。這意味著系統(tǒng)類型可用于將安全性和穩(wěn)健性引入API,而絕對沒有運行時開銷。
當(dāng)然,對于許多應(yīng)用程序來說,這已經(jīng)足夠了,但開發(fā)人員不僅限于使用Rust在微控制器上編寫基本的事件循環(huán)和中斷例程。
基于ArmCortex-M的微控制器可以運行AsyncRust,使用純Rust編寫的小型輕量級異步執(zhí)行器,例如embassy。這通常是啟動完整RTOS的一種高效且經(jīng)濟(jì)的替代方案,尤其是當(dāng)您只需要同時執(zhí)行少量任務(wù)時。
但有時,完整的RTOS才是正確的解決方案。在第2部分中,我們將探討如何將Rust與現(xiàn)有的C API集成,包括使用Free RTOS和Eclipse ThreadX等RTOS的實際示例。
圖3:nRF52840 DK(來源:Nordic Semiconductor)
第二部分:Arm上高級Rust與RTOS的集成
在本博客系列的第1部分中,我們探討了如何使用Rust在Arm微控制器上構(gòu)建裸機(jī)應(yīng)用程序。在第2部分中,我們將重點介紹如何將Rust與微控制器和中型微處理器上的實時操作系統(tǒng)(RTOS)進(jìn)行集成。
大多數(shù)現(xiàn)有的RTOS都是用C編寫的,因此在其上運行的任何Rust程序都需要與現(xiàn)有的CAPI交互。RTOS的示例包括但不限于Eclipse ThreadX、Free RTOS或Zephyr。
在Arm上,這些系統(tǒng)通常在AArch32模式下在Cortex-R52等處理器上執(zhí)行A32指令;盡管這里的概念同樣適用于Cortex-M4、Cortex-M55或類似產(chǎn)品。
圖1:編寫Rust應(yīng)用程序的方法
Rust支持導(dǎo)入和導(dǎo)出兼容C的函數(shù)、原始指針、易失性內(nèi)存訪問以及內(nèi)聯(lián)匯編,以實現(xiàn)低級別的硬件交互。一個完整的演示超出了博客文章的范圍,因此FerrousSystems發(fā)布了一個開源示例應(yīng)用,該應(yīng)用使用Eclipse ThreadXRTOS,并針對Arm Cortex-R5在Arm Versatile ApplicationBoard上(以及Arm PL011UART、Arm PL190向量中斷控制器和Arm SP804雙定時器)。
這個例子將ThreadX編譯為靜態(tài)C庫,然后將其鏈接到由Rust和Arm匯編混合編寫的二進(jìn)制文件中。此示例可以使用Ferrocene或標(biāo)準(zhǔn)Rust工具鏈進(jìn)行編譯。
就像第一部分提到的裸機(jī)微控制器一樣,在這些實時系統(tǒng)上,通常無法使用完整的Rust標(biāo)準(zhǔn)庫。相反,用戶被限制在一個更為基本的子集libcore中。
雖然不是不可能做到——對于FreeRTOS和NuttX等存在Rust標(biāo)準(zhǔn)庫移植版,但這些系統(tǒng)通常非常關(guān)注資源分配和性能,因此創(chuàng)建高性能綁定到所需的RTOS部分比嘗試將RTOS抽象到更適合應(yīng)用處理器API的做法更有意義。這種方法對功能安全系統(tǒng)也有利,因為在Rust中認(rèn)證一個小的自定義RTOS接口比認(rèn)證整個Rust標(biāo)準(zhǔn)庫更實際。
在ThreadX的例子中,匯編語言啟動代碼設(shè)置堆棧指針并啟用浮點單元(FPU)后,執(zhí)行權(quán)被交給用Rust編寫的main函數(shù)。Rust代碼初始化外設(shè)驅(qū)動程序,然后將執(zhí)行權(quán)交給ThreadX調(diào)度器。ThreadX設(shè)置的一部分涉及通過一個名為tx_application_define的函數(shù)回調(diào)到Rust固件中,該函數(shù)是用Rust編寫的,但聲明為具有“C兼容”的接口。此函數(shù)用于為任務(wù)堆棧創(chuàng)建字節(jié)池和生成各種任務(wù)。圖2展示了如何輕松地用Rust調(diào)用CAPI的一個片段。
圖2:使用Rust創(chuàng)建ThreadX字節(jié)池的示例。threadx_sys crate包含基于RTOS的C頭文件自動生成的綁定。
threadx_syscrate包含基于RTOSC頭文件自動生成的綁定。代替手動轉(zhuǎn)換ThreadX頭文件為Rust,示例使用bindgen工具自動為ThreadX生成Rust綁定。
這個最初由Mozilla開發(fā)并由Ferrous Systems支持的工具幾乎可以應(yīng)用于任何帶有標(biāo)準(zhǔn)C頭文件的庫,例如ThreadX提供的庫。示例使用來自bindgen的自動生成綁定,允許Rust代碼調(diào)用任何ThreadX函數(shù),而RTOS可以回調(diào)到任何標(biāo)記為extern"C"鏈接的Rust函數(shù)。
ThreadX源代碼必須使用標(biāo)準(zhǔn)C編譯器編譯,這在示例中是自動處理的。然后告訴Rust將生成的libthreadx.a鏈接到編譯后的Rust代碼,以生成最終的二進(jìn)制文件。
在我們的示例中,啟動代碼是用Rust編寫的,但你可能更傾向于讓RTOS從C處理啟動和驅(qū)動初始化,只將任務(wù)用Rust編寫。或者,你可以使用完全用Rust編寫的RTOS,如OxidOS。一般步驟保持不變:將你需要的庫代碼編譯成靜態(tài)庫,然后使用這些靜態(tài)庫編譯和鏈接二進(jìn)制文件。無論是RTOS作為庫還是作為二進(jìn)制文件,變化不大,只是編譯順序有所不同。
請參閱第3部分,我們將探討如何在Arm處理器上使用Rust和Linux、Windows和macOS等成熟的操作系統(tǒng)。
圖3:實時操作系統(tǒng)通常用于工業(yè)和汽車應(yīng)用程序。
第三部分,我們將探索在Arm處理器上使用Rust與完整操作系統(tǒng)如Linux、Windows和macOS的應(yīng)用。
在本博客系列的第一部分中,我們探討了使用Rust在Arm微控制器上構(gòu)建裸機(jī)應(yīng)用程序。第二部分深入研究了將Rust與實時操作系統(tǒng)(RTOS)集成在微控制器和中型微處理器上的應(yīng)用?,F(xiàn)在,在第三部分中,我們將注意力轉(zhuǎn)向使用Rust與完整操作系統(tǒng)如Linux、Windows、macOS、QNX或Android在Arm處理器上的應(yīng)用。
在Arm架構(gòu)上,這些系統(tǒng)通常執(zhí)行A64指令,在AArch64模式下運行,例如在RaspberryPi5中找到的Cortex-A76,或者最新AWSGraviton云服務(wù)器中的NeoverseV2。Rust還為32位Arm系統(tǒng)提供了良好的支持,例如Cortex-A8和Arm11,甚至可以追溯到1990年代的Arm7。圖1展示了編寫Rust應(yīng)用程序的方法。
圖1:編寫Rust應(yīng)用程序的方法
在應(yīng)用處理器上,你通??梢栽L問完整的Rust標(biāo)準(zhǔn)庫。這個庫抽象了許多特定于操作系統(tǒng)的接口,提供了一致的API用于線程、文件系統(tǒng)、網(wǎng)絡(luò)等,無論操作系統(tǒng)是什么。這意味著開發(fā)者可以使用他們喜歡的開發(fā)平臺,并且可以確信相同的源代碼可以在比如基于Linux的生產(chǎn)系統(tǒng)上編譯。
為了展示Rust的高層次表達(dá)能力,圖2顯示了一個示例Rust應(yīng)用程序。
圖2:在Rust中處理文本文件
圖1中的代碼讀取一個UTF-8編碼的文本文件到堆分配的String中,如果文件無法打開則干凈地退出。隨后逐行處理它變得非常簡單,這要歸功于內(nèi)置的迭代器支持——這個例子查找以"MESSAGE:"開頭的行并打印匹配行的其余部分。這種高層API的感覺像Java或C#,但具有C應(yīng)用程序的性能——這是Rust的獨特優(yōu)勢。
開箱即用的交叉編譯
Rust工具鏈不僅僅包括編譯器;它還包括一個結(jié)合了構(gòu)建系統(tǒng)和包管理器的工具叫做cargo。這個工具大大簡化了構(gòu)建Rust應(yīng)用程序的過程——通常只需要一條簡單的cargobuild--release命令就可以構(gòu)建最復(fù)雜的項目。作為構(gòu)建的一部分,cargo可以從第三方包倉庫(如crates.io)下載依賴項,解析語義版本,并為你的項目構(gòu)建一個完整的依賴樹——包括重要的開源許可信息。
Rust編譯器本身也是一個開箱即用的交叉編譯器。這意味著不像某些C編譯器,你不需要安裝特定版本的編譯器來適應(yīng)任何給定的主機(jī)或目標(biāo)組合。相反,你可以使用rustup(Rust工具鏈管理器),下載并安裝適合你所選目標(biāo)的預(yù)編譯Rust標(biāo)準(zhǔn)庫,然后就可以開始工作了。圖3展示了如何使用rustup添加對新目標(biāo)的支持,例如針對Armv7架構(gòu)的32位ArmLinux的交叉編譯。
圖3:使用rust up添加對新目標(biāo)的支持
Rust項目將其支持的目標(biāo)分為幾個級別。一級是最高級別,這里的任何目標(biāo)都會在每次Rust發(fā)布時進(jìn)行編譯和測試。這一級包括64位ArmLinux,以及x86Linux、Windows和macOS。
二級目標(biāo)會進(jìn)行編譯,但不會運行測試套件。這一級包括上面提到的Armv7Linux示例。三級目標(biāo)僅提供盡力而為的支持,這里是更奇特的目標(biāo)所在——例如NintendoSwitch上的Rust,或者LinuxonArm7上的Rust。目前,三級目標(biāo)僅支持使用‘nightly’Rust工具鏈,而不支持穩(wěn)定版本。值得注意的是,Rust就像C和C++一樣,需要一個適合你目標(biāo)平臺的鏈接器。對于許多目標(biāo),捆綁的LLVM鏈接器‘lld’可以工作,但在某些情況下,你可能需要安裝特定的鏈接器。
對于那些需要超出標(biāo)準(zhǔn)Rust層級系統(tǒng)提供的支持的人來說,F(xiàn)errocene提供了解決方案。Ferrocene是商業(yè)支持的Rust工具鏈下游產(chǎn)品,由Ferrous Systems制作。Arm和Ferrous Systems緊密合作,使得特定硬件目標(biāo)能夠在Ferrocene中可用,這些目標(biāo)在上游Rust項目中可能只作為二級或三級目標(biāo)。Ferrocene目標(biāo)通過了Rust測試套件,并且其中一部分已經(jīng)通過TüVSüd認(rèn)證,適用于ISO26262ASIL-D和IEC61508SIL-4,還有更多的行業(yè)特定認(rèn)證正在計劃中。
掌握整個Arm譜系上的Rust
本博客系列探討了從廣泛的Arm設(shè)備譜系中選取的三個例子,并深入研究了在這個平臺上使用Rust的具體情況。我們看到,無論是要在現(xiàn)有的完全成熟的操作系統(tǒng)上構(gòu)建,還是與實時操作系統(tǒng)協(xié)作,或者是裸機(jī)開發(fā),Rust都能幫助開發(fā)者構(gòu)建高性能、安全和可靠的軟件。它提供的特性使開發(fā)者能夠比使用傳統(tǒng)語言更快地進(jìn)入生產(chǎn)階段。
類型檢查允許構(gòu)造難以誤用的API,這意味著你更有可能正確使用它們——節(jié)省寶貴的調(diào)試時間。借用檢查意味著緩沖區(qū)溢出和釋放后使用錯誤在“安全”Rust中實際上是不可能的,而你只需要在我們的項目可能用來與硬件或操作系統(tǒng)交互的那一小部分“不安全”Rust代碼中檢查這些問題。來自使用LLVM優(yōu)化的結(jié)果是,無論是在應(yīng)用處理器、實時系統(tǒng)還是微控制器上,Rust生成的二進(jìn)制文件在性能上都與C和C++相當(dāng)。
如果你正在尋找?guī)в猩虡I(yè)支持和可選功能安全認(rèn)證的Rust編譯器,請查看FerrousSystems提供的Ferrocene。Ferrocene當(dāng)前提供經(jīng)過ISO26262ASIL-D和IEC61508SIL-4認(rèn)證的AArch64裸機(jī)目標(biāo)編譯器,同時面向32位ArmCortex-R和Cortex-M目標(biāo)的資格認(rèn)證也正在進(jìn)行中。
圖4:樹莓派5 https://www.raspberrypi.com/documentation/computers/raspberry-pi.html
本文翻譯自“community.arm.com”
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
關(guān)于億道電子
上海億道電子技術(shù)有限公司是國內(nèi)資深的研發(fā)工具軟件提供商,公司成立于2009年,面向中國廣大的制造業(yè)客戶提供研發(fā)、設(shè)計、管理過程中使用的各種軟件開發(fā)工具,致力于幫助客戶提高研發(fā)管理效率、縮短產(chǎn)品設(shè)計周期,提升產(chǎn)品可靠性。
十多年來,先后與ARM、Altium、Ansys、QT、Green Hills、Minitab、EPLAN、QA Systems、OpenText、Visu-IT、HighTec、PLS、Ashling、MSC Software、Autodesk、Source Insight、IncrediBuild、Lauterbach、Adobe、Testplant、TeamEDA等多家全球知名公司建立戰(zhàn)略合作伙伴關(guān)系,并作為他們在中國區(qū)的主要分銷合作伙伴服務(wù)了數(shù)千家中國本土客戶,為客戶提供從芯片級開發(fā)工具、EDA設(shè)計工具、軟件編譯以及測試工具、結(jié)構(gòu)設(shè)計工具、仿真工具、電氣設(shè)計工具、以及嵌入式GUI工具等等。億道電子憑借多年的經(jīng)驗積累,真正的幫助客戶實現(xiàn)了讓研發(fā)更簡單、更可靠、更高效的目標(biāo)。
歡迎關(guān)注“億道電子”公眾號
了解更多研發(fā)工具軟件知識