作者 | Elektor
譯者 | 禾沐
國內(nèi)嵌入式軟件開發(fā)一直比較傳統(tǒng),除涉及關(guān)鍵系統(tǒng)外的多數(shù)項目,都是在“編程”優(yōu)先的開發(fā)方式驅(qū)動下實(shí)施的。
這背后的原因有很多,除了產(chǎn)品上市壓力大、建模和仿真工具價格不菲之外,還有一個重要因素——嵌入式
軟件開發(fā)的思維方式轉(zhuǎn)變需要漫長時間和教育過程才能完成。
本篇譯文詳細(xì)闡述了如何改變嵌入式軟件開發(fā)思維方式,并結(jié)合幾款很實(shí)用的工具和汽車電子實(shí)例進(jìn)行了具體分析。
嵌入式軟件開發(fā)者們總是喜歡躲開關(guān)于
軟件架構(gòu)、
抽象化、
建模和
模擬的討論,直接開始進(jìn)行編程,而嵌入式軟件代碼往往一旦發(fā)布就不能進(jìn)行改動了,出錯的余地非常小。
既然我們都知道測試對嵌入式軟件非常重要,也有很多進(jìn)行建模/仿真的工具,那么,為什么還會先編程,然后等待很久才開始測試呢?
啄木鳥帶來的危險
那是一次“原來是這樣!”的頓悟。當(dāng)時正在為了一個培訓(xùn)課程進(jìn)行準(zhǔn)備,我在想,為什么嵌入式軟件工程師如此不愿意使用在其他軟件開發(fā)過程中常見的概念和方法呢?
在微控制器相關(guān)的工程中,我時常會遇到這樣的工程師:他們既不定義代碼風(fēng)格標(biāo)準(zhǔn)(盡管軟件開發(fā)有多個工程師參與),也不會定義任何幫助提高代碼可移植性和可用性的設(shè)計準(zhǔn)則,更不會關(guān)心面向?qū)ο笤O(shè)計、建模和仿真。
我的腦海中浮現(xiàn)出了下面這句話:“
如果木匠用程序員編程的方法建造建筑,只需要一只啄木鳥就可以摧毀整個人類文明。”
這句話從溫伯格法則稍微修改而來,它著實(shí)引起了我的共鳴。為什么嵌入式軟件開發(fā)者們不
借鑒計算機(jī)科學(xué)研究成果,使用正確的方式構(gòu)建代碼,或者借力建模/仿真技術(shù)呢?
編程太快了嗎?
一個原因可能是來自這一代程序員的經(jīng)歷。他們的生涯從資源受限的8位微控制器開始,用匯編語言最高程度地利用硬件的性能是王道,抽象化和工具自動生成的代碼只能意味著代碼冗余和失去對代碼的完全控制。轉(zhuǎn)移到C語言對于一些人來說都有難度,盡管C語言已經(jīng)非常貼近硬件了。
另一個角度是C語言的教學(xué)方式往往注重語法,而不是如何最佳地使用這門語言。但是,就像自然語言一樣,精通語法并不能讓你成為一位演說家。
物聯(lián)網(wǎng)(IoT)應(yīng)用出現(xiàn)以前,升級微控制器的固件基本意味著親自前往設(shè)備的所在地,代碼出錯的余地非常小。即便如此,許多嵌入式程序員的開發(fā)方式也始終沒有改變。
推廣新的開發(fā)方式?
過去,運(yùn)行在微控制器上的代碼往往可以用一個簡單的
狀態(tài)機(jī)表示,如今微控制器需要解決多維的問題。今天的微控制器可以通過磁場導(dǎo)向控制(FOC)技術(shù)對電動機(jī)進(jìn)行換向操作,并同時運(yùn)行其他任務(wù)。
雖然相關(guān)的代碼已經(jīng)存在,但是,實(shí)時確定電動機(jī)的角度和計算下次換向的時機(jī)就已經(jīng)非常復(fù)雜了。
這樣的微控制器如果出現(xiàn)在家用洗衣機(jī)中的話,我們還需要考慮IEC 60730標(biāo)準(zhǔn)(自動電子控制 – 第1部分:一般要求)。大多數(shù)微控制器廠商會提供能夠執(zhí)行CPU寄存器、程序計數(shù)器、內(nèi)存完整性和時鐘測試的“B類”庫,庫代碼應(yīng)該在運(yùn)行實(shí)時電動機(jī)控制的同時執(zhí)行。
系統(tǒng)中一般還會有能快速響應(yīng)的通訊接口和人機(jī)交互界面,嵌入式開發(fā)者也許可以保證每個部分都能單獨(dú)運(yùn)行,但是
整合在一起后系統(tǒng)是否依然可靠呢?
一個選項是用
統(tǒng)一建模語言(UML)針對應(yīng)用進(jìn)行建模并運(yùn)行仿真。嵌入式軟件開發(fā)者往往非常不喜歡這種方式,他們認(rèn)為這樣做是浪費(fèi)時間:如果有時間建模和運(yùn)行仿真,還不如直接把代碼寫出來。
一些人還在系統(tǒng)設(shè)計中濫用UML,導(dǎo)致UML染上了不好的名聲。抽象的設(shè)計方式還意味著不同的開發(fā)過程,說服一個開發(fā)團(tuán)隊轉(zhuǎn)變開發(fā)過程并不是一件容易的事情。
對于在設(shè)計和實(shí)現(xiàn)中各編程一次的擔(dān)心,我們稱為過程的不連續(xù)性(phase discontinuity)。理想狀況下,建模過程應(yīng)該解決這一問題,比如實(shí)時面向?qū)ο蠼#≧OOM)領(lǐng)域特定語言(DSL)。
ROOM專門針對事件驅(qū)動的實(shí)時系統(tǒng),它支持建模和模擬,還能夠生成針對目標(biāo)硬件的代碼。
ROOM從三個維度描述軟件:結(jié)構(gòu)、行為和繼承。結(jié)構(gòu)可以用角色(actor)通過端口(port)互相通信表示,消息通過運(yùn)行時軟件庫進(jìn)行傳遞。角色的行為通過多層有限狀態(tài)機(jī)進(jìn)行表示,并可以圖表形式輸出。
進(jìn)入和離開狀態(tài)的代碼可以用代碼生成器(比如針對微控制器的C編譯器)的目標(biāo)語言進(jìn)行定義。當(dāng)端口接收消息或者收到回應(yīng)時,狀態(tài)改變會發(fā)生。
繼承提供了ROOM中面向?qū)ο蟮牟糠郑葘⒔巧醋骺梢远啻螌?shí)例化的類。每個實(shí)例繼承狀態(tài)機(jī),需要的話,狀態(tài)機(jī)還可以進(jìn)一步擴(kuò)展。最后一個概念是分層(layering),它允許應(yīng)用互相進(jìn)行通信,或者通過服務(wù)訪問點(diǎn)(SAP)使用服務(wù)(比如定時器)。
Eclipse集成開發(fā)環(huán)境插件eTrice支持這一
軟件開發(fā)方式。模型可以通過圖形或者文本創(chuàng)建,并可以輸出C、C 或者Java代碼。在模型上運(yùn)行模擬將會輸出消息序列圖(MSC),UML工具Trace2UML(Astade[8]的一部分)可以將序列圖進(jìn)行可視化。
圖1所示的是一個簡單的“乒乓” 樣例應(yīng)用,其中定時器SAP決定了響應(yīng)延遲的時間。通過圖像和ROOM DSL可以檢查應(yīng)用的結(jié)構(gòu)和行為。執(zhí)行模型將會在命令行上輸出結(jié)果,模擬的輸出是MSC(見圖2)。
圖1 eTrice“乒乓”樣例工程,可以看到“乒”和“乓”的角色(左)以及它們的行為(右)
圖2 在“乒乓”模型上運(yùn)行模擬所產(chǎn)生的消息序列圖
為什么測試開始得很晚?
在匆匆開始編程之后,許多嵌入式開發(fā)團(tuán)隊往往會等到已經(jīng)編寫了不少代碼后才考慮開始測試問題,這樣做的背后有很多繁雜的原因,比如錯誤地認(rèn)為測試必須由一個團(tuán)隊或者部門負(fù)責(zé),或是缺乏清晰、易于測試的軟件需求。
集成開發(fā)環(huán)境強(qiáng)大的調(diào)試器也可能讓我們產(chǎn)生了虛假的安全感。
Lisa Simone在《If I Only Changedthe Software, Why is the Phone on Fire?》一書[9]中用幽默的方式探討了程序錯誤帶來的后果。在一個例子中,不當(dāng)?shù)臄?shù)據(jù)類型導(dǎo)致了溫度控制算法的錯誤。
雖然Simone完整地描述了尋找這類問題根源的過程,但事實(shí)上,這些問題在單元測試中就應(yīng)該被發(fā)現(xiàn)。
單元測試是一種白盒風(fēng)格測試,即編寫測試的工程師有源代碼的知識,往往編寫者就是源代碼的作者。在微控制器上,單元測試需要一個能夠執(zhí)行測試和分析輸出的應(yīng)用,最終結(jié)果往往通過串口輸出到控制臺上。
這意味著,我們需要能夠執(zhí)行測試的硬件平臺。Arduino和其他類似的平臺提供UART到USB轉(zhuǎn)換,這讓在控制臺上輸出測試結(jié)果變得更容易。但是,針對每個軟件模塊開發(fā)和維護(hù)一個測試應(yīng)用確實(shí)是很大的工作量。
iSYSTEM開發(fā)的testIDEA提供了顯著降低測試難度的方法。iSYSTEM開發(fā)的調(diào)試工具意味著開發(fā)環(huán)境不僅能訪問源代碼,還可以通過調(diào)試接口訪問微控制器的環(huán)境。使用testIDEA只需要提供能夠?qū)懭胛⒖刂破鏖W存的編譯過的應(yīng)用代碼(ELF格式)。
在testIDEA中定義的測試用預(yù)定義的參數(shù)單獨(dú)測試函數(shù)(圖3)。在軟件中我們能夠任意修改RAM,從而注入任何類型的數(shù)據(jù)和指針。
測試的通過與否取決于函數(shù)的的返回值是否正確,測試中還可以通過跟蹤功能提供代碼覆蓋的數(shù)據(jù)。
工具中有對C 的支持,但是在測試各類方法之前需要先調(diào)用構(gòu)造函數(shù)。測試還可以輸出進(jìn)入Python環(huán)境,幫助測試的自動化。
圖3 通過testIDEA測試在微控制器上運(yùn)行的軟件函數(shù)
testIDEA的一大功能是所有內(nèi)部和私有變量值都可以在測試時進(jìn)行注入,當(dāng)你調(diào)試時可以想做什么就做什么。
這對于在編譯中優(yōu)化過的代碼非常有幫助:我們都知道無用代碼的移除和代碼段的重組意味著優(yōu)化后代碼的行為和優(yōu)化前并不完全一致,換言之,代碼和二進(jìn)制代碼的關(guān)系會變得模糊,這讓調(diào)試變得更加有挑戰(zhàn)性。
通過在testIDEA中運(yùn)行同樣的測試,你可以在進(jìn)行系統(tǒng)整合前確定基礎(chǔ)代碼的行為沒有變化。
多少測試才足夠?
對初次接觸測試的工程師來說,確定最佳的策略并不簡單。像《愛麗絲夢游仙境》中的兔子洞一深入研究測試的方法,你會覺得需要測試的東西越來越多。
軟件的多維性和復(fù)雜的依賴關(guān)系意味著我們很難預(yù)估多少測試是足夠的。參與過安全關(guān)鍵項目的工程師都知道,相關(guān)的標(biāo)準(zhǔn)都不是絕對的,比如汽車相關(guān)的ISO 26262和醫(yī)療相關(guān)的ISO 14971、IEC 60601。
舉例來說,ISO 26262“非常推薦”代碼分支覆蓋作為測試覆蓋的基準(zhǔn),然后只是“推薦”語句覆蓋和MC/DC(修改條件、決策覆蓋)。只有和測試領(lǐng)域的專家合作,才能確定在你的應(yīng)用中如何測試才是最佳的。
為了確保代碼的全部分支都被覆蓋,所有可能的代碼組合都要被測試到,我們可以借助sepp.med GmbH公司的MBTsuite產(chǎn)品。其基于模型的測試框架能夠幫助確定所有可能的測試組合,因而非常適合系統(tǒng)集成和測試。
確定測試范圍的第一步是將系統(tǒng)需求輸入到Enterprise Architect這類的工具中。接下來構(gòu)造系統(tǒng)的模型,將其和系統(tǒng)需求鏈接在一起。設(shè)計中較為復(fù)雜的部分可以用子模型來表示,從而保持模型整體的抽象程度和簡潔性(見圖4和圖5)。
圖4 電子駐車制動裝置的EnterpriseArchitect模型
圖5 釋放剎車部分的Enterprise Architect子模型,可以看到模型到要求間的鏈接
接下來將完成的模型導(dǎo)入到MBTsuite中。軟件允許你定義不同的測試策略,全路徑覆蓋(Full Path Coverage)會生成覆蓋整個模型的測試方案,最短路覆蓋(Shortest Path)用最短的路徑遍歷模型(見圖6)。
此外,隨機(jī)策略可以幫助發(fā)現(xiàn)形式化策略可能無法發(fā)現(xiàn)的問題,也可以作為在目標(biāo)硬件上驗(yàn)證測試機(jī)制的冒煙測試(smoke test )的一部分。
圖6 MBTsuite中電子駐車剎車的模型產(chǎn)生全路徑覆蓋測試方案
從電子駐車剎車(EPB)的模型(見圖4)可以看出,遍歷節(jié)點(diǎn)的過程中可能會進(jìn)入無限循環(huán)。循環(huán)數(shù)目(number of loop)和最長路徑長度(maximum path length)參數(shù)可以用來避免這一情況的產(chǎn)生。你也可以通過指定模型的區(qū)域來生成針對特定功能的測試。
MBTsuite最簡單的用法是產(chǎn)生Word或Excel文檔詳述測試的步驟和各個驗(yàn)證點(diǎn)預(yù)期的結(jié)果,手動測試時可以勾選每一步的完成情況,最終給出通過/失敗的結(jié)果。自動化測試的情形下,軟件根據(jù)模板生成合適的格式,比如Python代碼。
在硬件上快速測試
理想條件下,應(yīng)用在開發(fā)過程中應(yīng)該進(jìn)行硬件在環(huán)(HIL)測試,這對于在高壓、高電流或者有活動部件的環(huán)境中運(yùn)行的應(yīng)用尤其重要。
但是,這樣的測試機(jī)制可能會很昂貴,許多團(tuán)隊也可能需要在同一套硬件上測試多種產(chǎn)品。其結(jié)果是HIL測試的瓶頸效應(yīng)導(dǎo)致測試直到開發(fā)末期才進(jìn)行。在當(dāng)前新冠疫情的影響下,HIL測試甚至可能完全無法進(jìn)行。
為了應(yīng)對這一挑戰(zhàn),PROTOS Software GmbH開發(fā)了miniHIL平臺。平臺包括一個A4紙大小的硬件板,其上右側(cè)是安裝STM32 Nucleo開發(fā)板的位置,左側(cè)有一個強(qiáng)力的STM32H743微控制器,中間則是連接兩側(cè)的針腳矩陣。
STM32H743的作用是模擬STM32 Nucleo控制的設(shè)備,并產(chǎn)生同樣的信號。這一平臺非常適用于在沒有實(shí)體洗衣機(jī)或者電鉆的情況下測試電動機(jī)控制應(yīng)用。
miniHIL環(huán)境支持eTrice和CaGe(Case Generator)語言進(jìn)行測試的開發(fā)。這既讓開發(fā)者可以快速檢查代碼改動的正確性,也允許整個平臺和持續(xù)集成(CI)平臺相結(jié)合,比如Jenkins。這樣一來,自動測試可以定期在硬件上執(zhí)行,比如每晚執(zhí)行測試,第二天一早在儀表盤上檢查結(jié)果(見圖7)。
圖7 miniHIL和運(yùn)行Jenkins持續(xù)集成平臺服務(wù)器的PC整合(來源:PROTOS SoftwareGmbH)
尋找偶發(fā)失效
今天的汽車應(yīng)用非常復(fù)雜,在一輛汽車上運(yùn)行的代碼量和Windows NT類似。代碼開發(fā)的分布性意味著很多供應(yīng)商(甚至客戶)都參與到了其中。偶發(fā)的失效往往和定時有關(guān),而不是功能,多核處理器和虛擬機(jī)的廣泛應(yīng)用更是加劇了這一情況。
即使在測試充分的情況下,即將發(fā)貨的硬件上,甚至是客戶環(huán)境中,奇怪的事情還是時而發(fā)生。一個汽車電子的實(shí)例:兩個通過CAN總線相連的電子控制單元(ECU)會偶發(fā)錯誤,ECU A和B連接偶爾會出錯,但是和C連接不會,ECU B和C能正常協(xié)同工作。
問題的根本原因是ECU石英頻率的微小不同,運(yùn)行時間足夠長的情況下,兩個微控制器的時鐘差異會導(dǎo)致CAN消息的偶爾丟失。
Inchron AG[17]的chronSIM和chronVIEW,以及Vector InfomatikGmbH的TA Tool Suite等工具將定時看得和功能一樣重要。它們允許在編寫任何代碼前在目標(biāo)系統(tǒng)上構(gòu)建模型,從而幫助系統(tǒng)架構(gòu)師針對多種不同的硬件設(shè)計最佳的系統(tǒng)架構(gòu)。
這些工具會分析在不同處理器核上運(yùn)行代碼的影響,這對于在核心頻率不同的異構(gòu)多核處理器上運(yùn)行的應(yīng)用而言至關(guān)重要。最后,工具分析事件鏈(見圖8),并測量事件從傳感器到達(dá)系統(tǒng),并最終到達(dá)執(zhí)行器的時間。這些工作對于整合若干數(shù)據(jù)速率不同的傳感器數(shù)據(jù)的自動駕駛系統(tǒng)而言尤為重要。
圖8 Inchron Tool Suite通過建模、仿真和分析等方法突出定時的重要性,圖中展示的是一個事件鏈的分析(來源:INCHRON AG)
通過定義代碼段的超時時間,以及同時注意功能和定時特性,與時間相關(guān)的ECU通過CAN連接的問題可以在設(shè)計層面上解決。在模型中,可以理解時鐘頻率變動、核心分配、代碼執(zhí)行時間和時鐘頻率變化的影響。
這些工具還可以分析在實(shí)際硬件上運(yùn)行的微控制器產(chǎn)生的跟蹤數(shù)據(jù),檢查在不同測試條件下代碼段的執(zhí)行時間是否合乎需求。
是更加重視建模的時候了?
嵌入式軟件開發(fā)領(lǐng)域一直比較傳統(tǒng)?!凹庇诰幊獭钡乃季S方式被微控制器供應(yīng)商提供的編程和調(diào)試工具鏈所加劇,這些工具多是免費(fèi)的,這樣一來其他付費(fèi)授權(quán)的工具鏈就失去了存在的意義。
支持嵌入式系統(tǒng)建模和仿真的工具提供了一個在開始編程前后退一步、進(jìn)一步抽象化的機(jī)會。這一方式的背后是重復(fù)性的分析和測試,它因此可以幫助在開發(fā)太過深入前以較低的成本糾正設(shè)計上的問題。
桌面HIL還允許通過壓縮的測試周期快速驗(yàn)證小的代碼改動,而不是在整合后的代碼上運(yùn)行完整的測試。最后,雖然最復(fù)雜的實(shí)時應(yīng)用(比如汽車)開發(fā)中建模和測試手段已經(jīng)被廣為應(yīng)用,我們還是應(yīng)該在功能要求的基礎(chǔ)上添加定時的要求。
采用這些基于模型的工具的最大挑戰(zhàn),是對改變的畏懼。它們的抽象性讓傳統(tǒng)嵌入式開發(fā)者不得不離開他們熟悉和喜歡的硬件,前往一個陌生的地方。它們還需要開發(fā)過程做出改變,這導(dǎo)致了很多負(fù)面的意見。
這些工具從紙面上看非常合理,但只有真正開始使用,我們才能知道在實(shí)際操作中它們帶來的益處。許多此類工具已經(jīng)存在了十年或者更久,它們的地位和作用已經(jīng)建立起來了。
這些工具可以降低開發(fā)時間和開銷、提高產(chǎn)品的質(zhì)量,開發(fā)者們需要從實(shí)際的開發(fā)過程出發(fā),分析這類選項是否適用于他們的產(chǎn)品。
相關(guān)鏈接
[1]https://quoteinvestigator.com/2019/09/19/woodpecker/.
[2]IEC 60730-1:2013. https://webstore.iec.ch/publication/3117.
[3]例如Hitex B類庫:http://www2.hitex.com/dl-classb-sam-d2x.
[4]A. E. Bell. Death by UML Fever. https://queue.acm.org/detail.cfm?id=984495.
[5]B. Selic, G. Gullekson, P. Ward, Real-TimeObject-Oriented Modeling, Wiley, 1994.
[6]https://en.wikipedia.org/wiki/Real-Time_Object-Oriented_Modeling.
[7]https://www.eclipse.org/etrice/downloads/.
[8]https://wiki.astade.de/dokuwiki/doku.php?id=start.
[9]L. Simone, If I Only Changed the Software,Why is the Phone on Fire?, Newnes, 2007.
[10]https://www.isystem.com/products/software/testidea.html.
[11]Feabhas Ltd, “A Quick Guide to ISO 26262,”2016. https://www.feabhas.com/sites/default/files/2016-06/A quick guide to ISO 26262[1]_0_0.pdf.
[12]https://mbtsuite.com/.
[13]https://sparxsystems.com/.
[14]https://docs.protossoftware.de/minihil/latest/Reference/CaGe/index.html.
[15]https://www.jenkins.io/.
[16]https://www.visualcapitalist.com/millions-lines-of-code/.
[17]https://www.inchron.com/.
[18]https://www.vector.com/int/en/products/products-a-z/software/ta-tool-suite/.
往期推薦:
往期推薦
實(shí)用 | 一個簡單易用的菜單框架
實(shí)用 | 手頭上無LCD卻又急著開發(fā)UI?LCD模擬器了解一下~
基于EasyX寫的一個小應(yīng)用,源碼拿走不謝~
分享一款嵌入式人必備繪圖工具,讓你的工作匯報更精彩!(附安裝、踩坑、填坑教程)
基于vs2019的lvgl模擬器使用
wireshark抓包工具的使用及分析