PIL 基本介紹
在航空和汽車等安全攸關的行業,如果采用基于模型的設計方法論(MBD),需要額外引入背靠背測試的概念,具體來說,使用模型開發的過程中,背靠背測試包含 SIL(Software-in-the-Loop)和 PIL(Processor-in-the-Loop)兩種。其中 PIL 測試是驗證模型和目標碼(Object code,即編譯鏈接之后的產物)等效性的有效手段,也是諸如 DO178C,ISO26262 等功能安全標準推薦的一種測試方法。
為了更好的理解本文,首先來看看什么是硬件支持包(注:PIL 功能通常是一個完整硬件支持包的其中一個功能),在 MBD 語境下,一個相對完整的硬件支持包通常包含以下組件:
Toolchain - 實現將 Simulink 模型或 M 代碼一鍵自動化編譯、鏈接和下載的核心手段
Device Driver - MCU/MPU/FPGA 等的外設或者片外設備,比如 ADC,PWM,GPIO,SCI 等
Code Replacement Library(CRL) - 將生成的標準代碼替換成廠商的高效庫函數/匯編碼
Processsor-In-the-Loop(PIL) - 將算法模型生成可執行文件后(如.out)放到目標硬件上執行并和主機上的仿真結果進行對比的一種等效性測試手段
External Mode - 將(算法)模型生成可執行文件后獨立運行在目標硬件上并和原模型保持連接,此時原模型可理解為一種上位機“界面”,上位機模型和下位機目標碼可以聯動。
注:MathWorks 官方推出的硬件支持包通常是兼顧芯片級和板級,以芯片級為主,板級主要是支持一些官方或熱門的開發板。
硬件支持包的開發要求開發人員具備相應的知識和技能,以下是最基本的要求:
嵌入式軟硬件知識,通常包括使用 MCU/MPU/FPGA,調試工具和常用設備等技能
嵌入式軟件知識,通常包括熟悉嵌入式操作系統,編程,常用 IDE 的使用,通信協議,手寫 makefile 等能力
Embedded Coder 定制化知識和代碼生成的深刻理解
MATLAB 面向對象編程的知識
常見通信協議知識,包括 SCI,TCP/IP,CAN 等
只有在具備以上能力的前提下才能較好的開發出硬件支持包。另外,MathWorks 官方以及三方芯片廠商也會提供一些熱門芯片的現成的硬件支持包,在確定開發之前,應該進行相關調研,如果市面上已經存在相應的支持包,建議直接使用現成的。比如 NXP 針對其各系列芯片就提供了對應的硬件支持包供客戶選擇。
本文將聚焦硬件支持包中 PIL 功能的開發,介紹如何開發自己的 PIL 支持包。
PIL 基本原理
? ?
首先介紹下 PIL 的基本概念,如圖所示,PIL 測試供包含兩次仿真,分別是:
1)將軟件的Simulink模型首先在Simulink環境中運行一次,在給定激勵下會產生一些輸出,記錄下來;
2)接著將軟件的 Simulink 模型生成代碼并編譯鏈接成可執行目標碼,下載至下位機板子上運行,在相同的激勵下軟件在板子上運行也會產生一些輸出,也記錄下來。
3)最后將兩次輸出的結果進行等效性比對。
目前這些基本操作在 MathWorks 提供的工具鏈中都是傻瓜式操作,大家可自行查閱文檔學習,本文不做贅述。
如圖所示,一個完整的 PIL 仿真過程由以下各階段組成:
選擇三種 PIL 仿真方式中的一種啟動 PIL 仿真,至于哪三種方式可參考文檔
驗證上位機下位機連接配置
模型生成核心代碼
實例化 PIL API 組件(即 PIL Framework,就是幾個 PIL 專用的 MATLAB 類文件)
繼續生成額外的 PIL 需要用到的輔助代碼,配合模型生成的核心代碼組成一個包含上位機下位機通信和控制的完整應用代碼
基于注冊好的 ToolchainInfo 對象中的編譯信息,調用三方交叉編譯器將完整的應用代碼生成可執行的目標文件。同時調用上位機的 C/C++ 編譯器 (MinGW 或 Visual Studio) 把 PIL Framework 中涉及的 C/C++ 代碼編譯成 C Mex S Function(可簡單理解成加殼的 dll 或 so 文件),這些代碼主要是上位機端的 C/C++ 通訊源碼。
上位機 Simulink 模型下發指令啟動下位機運行目標代碼
Simulink Engine 通過 C Mex S Function 和下位機進行數據交互
上位機 Simulink 模型下發指令終止下位機目標代碼的運行
Simulink 模型停止 PIL 仿真
PIL 開發方法論
第一步
軟硬件開發環境
開發的第一步是搭建軟硬件開發環境,具體來說:
●硬件環境:開發板,調試器,外圍電路,通訊接口等
●軟件環境:IDE,MATLAB 等,特別注意 IDE 一定要支持命令行調用,這是自動化的前提,有些 IDE 的非商業版本只允許界面操作,這個是做不了支持包的!
●資料收集:各種可能涉及的參考資料,比如芯片的數據表,開發板的原理圖,IDE 的使用手冊等等
●通訊:PIL 會涉及上位機和下位機通信,所以通訊協議和通訊的硬件部分必須匹配,比如我們希望所開發的支持包支持上位機下位機通過 CAN 進行程序的燒寫和數據交互,那么要求板子上的硬件必須支持 CAN 通訊,并且上位機一般要通過 USB-CAN 卡與下位機相連,如下圖所示。理論上,任何通訊協議都可以,MathWorks 內置有部分現成的上位機通訊協議,包括串口和 TCP/IP,下位機部分仍然需要自己編寫。其他協議如 CAN 則需要自己編寫上位機和下位機通訊驅動。
一個良好的軟硬件開發環境可以通過寫個 makefile 來點燈的例子進行驗證。一旦完成點燈,意味著我們已經具備的基本的軟硬件開發環境。
第二步
Toolchain 的開發和 Hardware Board 注冊
從上文知道 PIL 仿真過程需要一鍵編譯鏈接和下載目標碼,這個動作是由 Toolchain 來實現的,因此開發 PIL 的第一步是開發 Toolchain。
這里先解釋下 Toolchain 在本文的含義,我們知道嵌入式開發自動化腳本通常就是 makefile,而 Toolchain 大家可以認為就是 MATLAB 版本的 makefile,是用 M 語言按照一定的要求和格式進行編寫,其中需要寫明匯編器、編譯器、鏈接器、下載器、格式轉換器等工具的命令行調用方法,編譯成目標碼所需要使用的各種依賴庫等。這樣可以將其自動嵌入到代碼生成的流程中去,實現所謂的“一鍵編譯下載”。
為了更好的講解后續內容,建議大家先跳到 第5步 - 細節學習,安裝 C2000 的官方支持包,這是一個非常好的學習對象。這里就以 C2000 支持包為例講解下 Toolchain 開發的要點。
C2000 支持包的安裝目錄(位置參考第 5 步中的截圖)找到 tiCCS.m 文件,大家可以直接使用這個文件作為自己 Toolchain 開發的模板,這個文件中最核心的部分包括:
●coder.make.ToolchainInfo:定義 ToolchainInfo 對象,下圖是該對象的透視圖,可以說開發 Toolchain,本質就是操作這個 ToolchainInfo 對象
●使用上述對象的 getBuildTool 方法注冊各類工具,比如 Assembler,Compiler,Linker,Archiver
●使用上述對象的 getPrebuildTool/getPostbuildTool 方法注冊各類代碼生成前后處理工具,比如編譯后自動下載等
●使用上述對象的 getBuildConfiguration 方法提供不同等級的 Build Configuration,比如保留調試能力的編譯配置,高度優化的編譯配置等,它們的本質區別就是編譯器優化等級不同
一旦完成上述內容的開發,下一步就是注冊該文件,這里我們以 TI TMS320 C6678 DSP 的 Toolchain 開發為例介紹:
●TI_TMS320C6678_toolchain.m – 所開發的toolchain 的 M 代碼
●sl_customization.m – 用來注冊硬件板子和 Toolchain 對象,這樣用戶可以在 Hardware Implementation 和 Code Generation 下面看到板子和 Toolchain 可供選擇。
function sl_customization(cm) cm.registerTargetInfo(@loc_createDevice); end function thisDev = loc_createDevice thisDev(1) = RTW.HWDeviceRegistry; thisDev(1).Vendor = 'Texas Instruments'; thisDev(1).Type = 'TMS320C6678'; thisDev(1).Alias = {}; thisDev(1).Platform = {'Prod', 'Target'}; thisDev(1).setWordSizes([8 16 32 32 32 32 64 32]); thisDev(1).LargestAtomicInteger = 'Long'; thisDev(1).LargestAtomicFloat = 'Double'; thisDev(1).Endianess = 'Little'; thisDev(1).IntDivRoundTo = 'Zero'; thisDev(1).ShiftRightIntArith = true; end
●refreshTITMS320C6678Toolchain.m – 注冊 Toolchain的 腳本,包括調用 TI_TMS320C6678_toolchain.m 并將其保存成 TI_TMS320C6678_toolchain.mat 格式,進一步調用 RTW.TargetRegistry.getInstance('reset') 注冊 Toolchain。
function refreshTITMS320C6678Toolchain %Make sure we are in the right directory currentDir = pwd; toolchainPath = getpref(' MyToolchainName', 'TOOLCHAINPATH'); cd(toolchainPath); % Create a new configuration gtc= MyToolchainName_toolchain; tc=gtc(1); save([toolchainPath ' TI_TMS320C6678_toolchain.mat'], 'tc'); % Refresh customisations defined by rtwTargetInfo.m RTW.TargetRegistry.getInstance('reset'); % Return to directory cd(currentDir) end
一旦注冊完成后我們就可以在模型參數配置界面上找到這個 Toolchain 作為代碼生成的選項,其中:
Hardware Implementation->Hardware board 中可選擇剛剛注冊的板子:
Code Generation中可選擇剛剛注冊的板子:
最后構建一個極簡的模型來驗證該Toolchain能夠完成模型的一鍵編譯下載。
第三步
PIL 工具鏈的組成
接著就是 PIL 最核心的開發部分,圖中紅色部分就是我們需要開發的內容,其中 PIL API Components 即 MathWorks 官方提供的一套標準的 PIL 開發框架,包括:上位機和下位機端各自的通訊協議,Build Process 和 Launcher等,該框架的核心就是名為 Connectivity Configuration 的幾個類文件組成,以下為開發要點:
●開發 PIL Target 核心功能類(即 Connectivity Configuration 類的編寫)
●桌面端和 IDE 中分別調通上位機和下位機的通訊功能,移植到核心功能類中
●下位機 Timer 配置并注冊核心功能類中,主要服服務于后續下位機上任務運行時間的統計和分析
這里對上述要點進一步展開介紹下,還是以 TI TMS320 C6678 DSP 的支持包開發為例,下圖是一個典型的 PIL Target 目錄,這里便于我們進行講解:
1)開發上位機和下位機通訊協議
比如截圖中是使用串口協議,并把上位機的串口協議和下位機的串口協議代碼分別放到 host_dll 和 target_src 中。如果是其他通訊協議,則把相應的協議代碼分門別類放好即可。通訊協議代碼需要按照一定的格式使用 rtiostream 函數進行封裝。
關于 rtiostream 函數的使用請查閱文檔示例或者 C2000 支持包安裝目錄中的代碼。另外,對于串口和 TCP/IP,MATLAB 官方提供了現成的上位機協議 dll 供使用,具體位置請查閱幫助文檔。
2)開發 PIL Target 核心功能類
其中 +tic6678codetargetpil 中存放了 PIL 的核心功能類,這些類文件都是通用的,大家可以直接使用官方 C2000 支持包安裝目錄中的 pil 代碼作為模板進行微調基本就能滿足要求。各個類的使用細節請直接參考文檔。
3)注冊硬件定時器 Timer
Timer 的注冊有兩種方式:1)crtool;2)Timer 類。C2000 支持包使用的是 crtool 方式,在文檔中搜索:Specify Hardware Timer 關鍵字即可找到操作指南,這種方式略微復雜些。當然也可以使用類的方式進行 Timer 注冊,以下為前述 C6678 示例中 Timer 的注冊方式:
classdef Timer < rtw.connectivity.Timer % TIMER Get timing information for C6678 application % ? Copyright 2022 The MathWorks, Inc. ? ?methods ? ? ? ?function this = Timer(varargin) ? ? ? ? ? ? ? ? ? ? ? ?this.setTimerDataType('uint32'); % i.e. unsigned long ? ? ? ? ? ?% Look for an input providing ticks per second ? ? ? ? ? ?if (nargin > 0) ticksPerSecond = varargin{1}; else ticksPerSecond = round(1.0e9/6); end this.setTicksPerSecond(ticksPerSecond); % The timer counts upwards this.setCountDirection('up'); % Extract path information from MATLAB Preferences timerSrcFolder = fullfile(fileparts(mfilename('fullpath')),'..','rtiostream','rtiostreamserial','target_src'); % Configure source files required to access the timer timerHeaderFile = fullfile(timerSrcFolder, 'ProfilerTimer.h'); timerSourceFile = fullfile(timerSrcFolder, 'ProfilerTimer.c'); this.setSourceFile(timerSourceFile); this.setHeaderFile(timerHeaderFile); % Configure the expression used to read the timer readTimerExpression = 'profileTimerRead()'; this.setReadTimerExpression(readTimerExpression); end end end
4)注冊整個 PIL 硬件支持包
function rtwTargetInfo(tr) %RTWTARGETINFO Target info callback,register individual targets with Coder Target % Copyright 2022 The MathWorks, Inc. tr.registerTargetInfo(@loc_createToolchain); tr.registerTargetInfo(@loc_createConfig); codertarget.TargetRegistry.addToTargetRegistry(@loc_registerThisTarget); codertarget.TargetBoardRegistry.addToTargetBoardRegistry(@loc_registerBoardsForThisTarget); end % ------------------------------------------------------------------------- % Create ToolchainInfoRegistry entries for TI TMS320C6678 function config = loc_createToolchain config = coder.make.ToolchainInfoRegistry; % initialize % Append to last in the toolchain registry base config(end).Name = 'TI TMS320C6678 Toolchain v1.0 | gmake (win64)'; toolchainPath = mfilename('fullpath'); [toolchainDir, ~] = fileparts(toolchainPath); config(end).FileName = fullfile(toolchainDir,'toolchain','TI_TMS320C6678_toolchain_win64.mat'); %MODIFY %List the platform or platforms supported by the custom toolchain %'*' means it supports any hardware device. config(end).TargetHWDeviceType = {'*'}; %config(end).Platform = {computer('arch')}; config(end).Platform = {'win64'}; end function ret = loc_registerThisTarget() ret.Name = 'TI TMS320C6678'; [targetFilePath, ~, ~] = fileparts(mfilename('fullpath')); ret.TargetFolder = targetFilePath; end % ------------------------------------------------------------------------- function boardInfo = loc_registerBoardsForThisTarget() target = 'TI TMS320C6678'; [targetFolder, ~, ~] = fileparts(mfilename('fullpath')); boardFolder = codertarget.target.getTargetHardwareRegistryFolder(targetFolder); % Point to folder registry/targethardware boardInfo = codertarget.target.getTargetHardwareInfo(targetFolder, boardFolder, target); end % ------------------------------------------------------------------------- % Specify settings for valid PIL configuration function config = loc_createConfig % Create object for serial connectivity configuration config(1) = rtw.connectivity.ConfigRegistry; % Assign connectivity configuration name config(1).ConfigName = 'TMS320C6678 PIL Serial'; % Associate the connectivity configuration with the connectivity % API implementation config(1).ConfigClass = 'tic6678codetargetpil.SerialConnectivityConfig'; % match TI C6678 toolchains config(1).Toolchain = {'TI TMS320C6678 Toolchain v1.0 | gmake (win64)'}; % Match only ert.tlc config(1).SystemTargetFile = {'ert.tlc'}; % Through the HardwareBoard and TargetHWDeviceType properties, % define compatible code for the target connectivity configuration % match only TI C6678 config(1).HardwareBoard = {}; config(1).TargetHWDeviceType = {'Texas Instruments->TMS320C6678'}; end
第四步
PIL 支持包的測試
可以自行構建一個簡單的模型,使用 SIL/PIL Manager 進行測試,具體的操作技巧請查閱文檔,這里不做贅述。
第五步
細節學習
限于篇幅和嵌入式本身的復雜性,本文無法面面俱到,最好的學習資料就是仔細研究一些現成的硬件支持包,比如 MathWorks 官方提供的 C2000 硬件支持包:
大家安裝完成后,結合本文,仔細翻閱支持包安裝目錄,基本就能把各種細節摸清楚。幫助文檔中也有 PIL 的示例和資料,相對來說篇幅較多也比較零散,需要耐心閱讀。R2019a 引入了 target Package,即一組高度抽象的 API 來便利化硬件支持包的開發,由于其高度抽象性,建議仍然使用本文描述的方法進行 PIL 支持包開發,這樣調試起來會方便很多。
說的再多,都不如找一塊板子實際開發一遍,祝大家都能掌握PIL開發的方法論,在項目中引入PIL測試環節,以期提高產品質量,減少后期枯燥地調試工作。
審核編輯:劉清
-
FPGA
+關注
關注
1626文章
21670瀏覽量
601875 -
GPIO
+關注
關注
16文章
1196瀏覽量
51919 -
MBD
+關注
關注
0文章
24瀏覽量
8941 -
PIL
+關注
關注
0文章
19瀏覽量
8603 -
SIL
+關注
關注
0文章
9瀏覽量
2521
原文標題:PIL (Process-in-the-Loop) 硬件支持包開發指南
文章出處:【微信號:MATLAB,微信公眾號:MATLAB】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論